pointer q

J

Joe Smith

A recent post of mine showed a sufficiently large gaffe on pointers as to
need to return to K&R 5.1-6 appendix A8.6.1 . So we have type specifiers:
int
long
.. One dreams himself variable names: qwe, qwr, writes

int qwe;
long qwr;

and thinks he knows what types he's declared. Had you asked me about:

int *qwe;
long *qwr;

I would have said the pointers declared were--while pointng to different
types--of the same type. Why am I wrong? Joe
 
B

Ben Pfaff

Joe Smith said:
Had you asked me about:

int *qwe;
long *qwr;

I would have said the pointers declared were--while pointng to different
types--of the same type. Why am I wrong?

"qwe" is of type "pointer to int".
"qwr" is of type "pointer to long".
Those are different types.
 
K

Keith Thompson

Joe Smith said:
A recent post of mine showed a sufficiently large gaffe on pointers as to
need to return to K&R 5.1-6 appendix A8.6.1 . So we have type specifiers:
int
long
. One dreams himself variable names: qwe, qwr, writes

int qwe;
long qwr;

and thinks he knows what types he's declared. Had you asked me about:

int *qwe;
long *qwr;

I would have said the pointers declared were--while pointng to different
types--of the same type. Why am I wrong? Joe

int* and long* are two different types (both pointer types).

I'm curious, what led you to think that they're the same type?
 
J

Joe Smith

Keith Thompson said:
int* and long* are two different types (both pointer types).

I'm curious, what led you to think that they're the same type?

What's to stop me from swapping an int * and a long *? Joe
 
K

Keith Thompson

Joe Smith said:
What's to stop me from swapping an int * and a long *? Joe

Um, they're different types. Given:
int *ip;
long *lp;
these assignments:
ip = lp;
lp = ip;
are both illegal (constraint violations requiring diagnostics).

You can do the assignments with explicit conversion (casts), but
there's no guarantee that the results will be meaningful.
 
D

Denis Kasak

Joe said:
What's to stop me from swapping an int * and a long *? Joe

The type system. Of course, it's not there only to annoy you, but has
very real, objective reasons to stop you from doing so.

Probably the most obvious reason is the fact that the compiler needs to
know what the pointer points in order to dereference it (in other words,
access the value of the object it points to). Different types have
different sizes and since pointer values are actually addresses of
objects, the compiler needs to know how many bits/bytes it has to read
from that address to retrieve the whole object, and only the object.

Pointer arithmetic also depends on what the pointer object points to.
Say you want to iterate over an array of int, with an int *:

int foo[10], *bar;

bar = &foo[0];
for(i = 0; i < 10; i++)
bar++;

How does the compiler know how much it needs to increment the value of
bar so it points to the next element of foo? It is obvious that using a
long * would advance it too much if sizeof (long) != sizeof (int).

Imagine a function expecting an int * as its argument and doing
something with the object it points to. Also imagine what would happen
if you passed to it the wrong type of pointer.

Also note that on some implementations the size of different pointer
types are not the same.

In short, it's not a logical thing to do. I think your confusion stems
from the (incorrect) assumption that the term 'pointer' denotes a single
kind of abstract type that 'points' regardless of what it points /to/.
So, to summarize, the type of the object the pointers points to *is* the
part of the pointer type. You cannot, therefore, exchange int * and long
* freely without casts.

-- Denis
 
E

Eric Sosman

Joe said:
What's to stop me from swapping an int * and a long *? Joe

Assume sizeof(int) < sizeof(long), and consider

long l = 42;
int *ip = &l; /* illegal, but Let's Pretend */
*ip = 76;

What value is now stored in `l'?

That's why int* and long* aren't interchangeable.
 
J

Joe Smith

Eric Sosman said:
Assume sizeof(int) < sizeof(long), and consider

long l = 42;
int *ip = &l; /* illegal, but Let's Pretend */
*ip = 76;

What value is now stored in `l'?

That's why int* and long* aren't interchangeable.

Thank you for replies. Mr. Thompson establishes that the reason not to swap
an int * and long * is that, as usual, assigning one type to another is
illegal, and that you can kludge away with castes if you so desire. Mr
Kasak and Mr Sosman show examples of bad things that would happen if you
did. What I'm trying to get my head around is how to view the memory with
C. If it is true that memory is a bunch of boxes with numbers on the side
and that different implementations may have differing sizes of pointers,
then the numbers on the sides of those boxes are less homogenous than I
thought. Joe
 
F

Flash Gordon

Joe Smith wrote:

Thank you for replies. Mr. Thompson establishes that the reason not to swap
an int * and long * is that, as usual, assigning one type to another is
illegal, and that you can kludge away with castes if you so desire. Mr
Kasak and Mr Sosman show examples of bad things that would happen if you
did. What I'm trying to get my head around is how to view the memory with
C. If it is true that memory is a bunch of boxes with numbers on the side
and that different implementations may have differing sizes of pointers,
then the numbers on the sides of those boxes are less homogenous than I
thought. Joe

Don't think of memory as a bunch of boxes with numbers on the side.
Don't think of memory at all. Think instead of arrays, ints and other
objects just floating randomly in space 42 dimensional space (OK, you
don't need to use that many dimensions). This will get rid of lots of
misconceptions about pointers. For example, when objects can be left,
right, above or below each other you start to see why you can't compare
two pointer to see which is larger if they don't point in to the same
object although you can always compare them for equality. Some of the
boxes have names (the ones for variables you declare) and others are
created by calling malloc.
 
E

Eric Sosman

Joe said:
Thank you for replies. Mr. Thompson establishes that the reason not to swap
an int * and long * is that, as usual, assigning one type to another is
illegal, and that you can kludge away with castes if you so desire. Mr
Kasak and Mr Sosman show examples of bad things that would happen if you
did. What I'm trying to get my head around is how to view the memory with
C. If it is true that memory is a bunch of boxes with numbers on the side
and that different implementations may have differing sizes of pointers,
then the numbers on the sides of those boxes are less homogenous than I
thought. Joe

What you're missing, I think, is that a pointer carries
more information than just the "number on the side" of the
box it points to. Specifically, it carries information about
how many adjacent boxes are involved, and how their contents
are to be understood. On many machines, for example, an int*
holds the "number" of a box along with the information that
three additional boxes are involved and that the four boxes
taken together represent an int. A double* might point to the
same box number, but could imply that seven more boxes are to
be considered along with the first, and that the eight taken as
a whole contain a double value. 42 and 42.0 probably don't
look the same.

The "number on the side of a box" is its address. A pointer
denotes not only an address but also a type; a pointer is a
"decorated" address.
 
J

Joe Smith

Eric Sosman said:
What you're missing, I think, is that a pointer carries
more information than just the "number on the side" of the
box it points to. Specifically, it carries information about
how many adjacent boxes are involved, and how their contents
are to be understood. On many machines, for example, an int*
holds the "number" of a box along with the information that
three additional boxes are involved and that the four boxes
taken together represent an int. A double* might point to the
same box number, but could imply that seven more boxes are to
be considered along with the first, and that the eight taken as
a whole contain a double value. 42 and 42.0 probably don't
look the same.

The "number on the side of a box" is its address. A pointer
denotes not only an address but also a type; a pointer is a
"decorated" address.

I'm proud to say that I had quite similar thoughts in the meantime. "A
pointer is a variable that contains the address of a variable." is true but
understated. The type of the pointer indicates what type's in the box.
I've been toying with the illegal and ill-advised counterexamples given
upthread:

#include <stdio.h>
int main(void)
{
long l, *lp;
int i, *ip;
l = 42;
i = 32;
lp = &l;
ip = &i;

printf(" %n %n\n", lp, ip);

return 0;
}
/* end source */
Believe it or not, this compiles sans warning and shows the pointers. Is it
possible that the conversion characters on that printf are correct to print,
respectively, a long * and an int * ? It seems like a practical joke to me.
Joe
 
C

Coos Haak

Op Sun, 14 May 2006 14:49:51 -0400 schreef Joe Smith:
I'm proud to say that I had quite similar thoughts in the meantime. "A
pointer is a variable that contains the address of a variable." is true but
understated. The type of the pointer indicates what type's in the box.
I've been toying with the illegal and ill-advised counterexamples given
upthread:

#include <stdio.h>
int main(void)
{
long l, *lp;
int i, *ip;
l = 42;
i = 32;
lp = &l;
ip = &i;

printf(" %n %n\n", lp, ip);

return 0;
}
/* end source */
Believe it or not, this compiles sans warning and shows the pointers. Is it

No, it doesn't. Turn up the warnings.
And to print pointer, use %p
 
K

Keith Thompson

[...]
#include <stdio.h>
int main(void)
{
long l, *lp;
int i, *ip;
l = 42;
i = 32;
lp = &l;
ip = &i;

printf(" %n %n\n", lp, ip);

return 0;
}
/* end source */
Believe it or not, this compiles sans warning and shows the pointers. Is it
possible that the conversion characters on that printf are correct to print,
respectively, a long * and an int * ? It seems like a practical joke to me.

I'd be very surprised if this showed the values of the pointers (it
didn't when I ran it). Are you sure your actual code uses "%n", not
"%d" or "%i"?

"%n" is a special format specifier that expects a pointer to int. It
doesn't print the value; rather it *writes* the number of characters
printed so far into the pointed-to variable. It's not what you want
here.

Your compiler won't necessarily be able to warn you about incorrect
format strings for printf. It's entirely up to you to get it right.
(Some compilers can do some checking in some cases, but don't count on
it.)

The correct way to print the values of the pointers is:

printf("%p %p\n", (void*)lp, (void*)ip);
 
J

Joe Smith

Keith Thompson said:
[...]
[buggy code snipped]
Believe it or not, this compiles sans warning and shows the pointers. Is
it
possible that the conversion characters on that printf are correct to
print,
respectively, a long * and an int * ? It seems like a practical joke to
me.

I'd be very surprised if this showed the values of the pointers (it
didn't when I ran it). Are you sure your actual code uses "%n", not
"%d" or "%i"?

I saw it with my own eyes, which argues for a visit to the optometrist or
psychiatrist.
"%n" is a special format specifier that expects a pointer to int. It
doesn't print the value; rather it *writes* the number of characters
printed so far into the pointed-to variable. It's not what you want
here.

Your compiler won't necessarily be able to warn you about incorrect
format strings for printf. It's entirely up to you to get it right.
(Some compilers can do some checking in some cases, but don't count on
it.)

The correct way to print the values of the pointers is:

printf("%p %p\n", (void*)lp, (void*)ip);

#include <stdio.h>
#include <stdlib.h>
int main(void)
{
long l, *lp;
int i, *ip, g, h;
l = 42;
i = 32;
lp = &l;
ip = &i;
g = sizeof(lp);
h = sizeof(ip);

printf("long address and size %p %d\n", (void *)lp, g);
printf("int address and size %p %d\n", (void *)ip, h);

return 0;
}
/* end source */
While unable to printf properly until now, I was able in any case to see the
values in the debugger. Apparently in my implementation, these pointers are
both 4 bytes. As I leave the topic of a memory model in C for the day so as
to plan to Take Over Next Week (preselecting), I see the belts I used to
sort on at UPS while I was in college. Boxes, labels, flows, jams, methods,
retapes and getting it done. Thanks for the help. Joe
 
R

RSoIsCaIrLiIoA

Assume sizeof(int) < sizeof(long), and consider

long l = 42;
int *ip = &l; /* illegal, but Let's Pretend */
*ip = 76;

What value is now stored in `l'?

That's why int* and long* aren't interchangeable.

and so where is the problem?
the problem is different cpus store data in different ways

here

#include <stdio.h>

int main ( void )
{int l = 42;
short *ip = &l; /* illegal, but Let's Pretend */

*ip = 76;
printf(" sizeof(short)==%u sizeof(int)==%u \n",
(unsigned) sizeof(short), (unsigned) sizeof(int));
printf("l==%d\n", l);
return 0;
}

sizeof(short)==2 sizeof(int)==4
l==76

all ok

the problem is "it is easy to obfuscate and make difficult
what it is easy" and it is in the cpu design

another example could be why not exchange "str* and sprintf, etc"
with a secure
int s?prinf(char* strig, int size_of_string, char* fmt, ...);?

because it is easier "to do difficult what is easy" then
Bugtraq is full of error for the C language
 
J

Joe Smith

RSoIsCaIrLiIoA said:
Joe said:
[motivation]
Assume sizeof(int) < sizeof(long), and consider

long l = 42;
int *ip = &l; /* illegal, but Let's Pretend */
*ip = 76;

What value is now stored in `l'?

That's why int* and long* aren't interchangeable.

and so where is the problem?
the problem is different cpus store data in different ways

here

#include <stdio.h>

int main ( void )
{int l = 42;
short *ip = &l; /* illegal, but Let's Pretend */

*ip = 76;
printf(" sizeof(short)==%u sizeof(int)==%u \n",
(unsigned) sizeof(short), (unsigned) sizeof(int));
printf("l==%d\n", l);
return 0;
}

sizeof(short)==2 sizeof(int)==4
l==76

all ok

the problem is "it is easy to obfuscate and make difficult
what it is easy" and it is in the cpu design

another example could be why not exchange "str* and sprintf, etc"
with a secure
int s?prinf(char* strig, int size_of_string, char* fmt, ...);?

because it is easier "to do difficult what is easy" then
Bugtraq is full of error for the C language

#include <stdio.h>

int main ( void )
{long l = 420000;
long *lp = &l;

short *sp;
*sp = (short)*lp; /* ill-advised, but Let's Pretend */

printf(" sizeof(short)==%u sizeof(int)==%u \n",
(unsigned) sizeof(short), (unsigned) sizeof(int));
printf("in order, ell then the short %ld %hdh\n", l, *sp);
return 0;
}
/* end source */
Now that you bring this snippet up again, I think this code shows why it's
usually a bad idea to do things along this line. I'm not sure that this is
what Mr. Sosman was getting at. As to the syntax on the printf, I've done
everything short of Dedekind cuts on table B-1 and am still pulling out my
hair. I'm afraid that I don't know what Bugtraq is ... probably at my own
peril. Am I correct to think that a type of masking occurs here? joe
 
F

Flash Gordon

Joe said:
RSoIsCaIrLiIoA said:
Joe Smith wrote:
[motivation]
Assume sizeof(int) < sizeof(long), and consider

long l = 42;
int *ip = &l; /* illegal, but Let's Pretend */
*ip = 76;

What value is now stored in `l'?

That's why int* and long* aren't interchangeable.
and so where is the problem?
the problem is different cpus store data in different ways

here

#include <stdio.h>

int main ( void )
{int l = 42;
short *ip = &l; /* illegal, but Let's Pretend */

*ip = 76;
printf(" sizeof(short)==%u sizeof(int)==%u \n",
(unsigned) sizeof(short), (unsigned) sizeof(int));
printf("l==%d\n", l);
return 0;
}

sizeof(short)==2 sizeof(int)==4
l==76

all ok

On your system, but not on mine. I regularly work on both big and little
endian systems and if you fix the above so it actually compilers you
will get very different results.

It is full of errors for programs written in all sorts of languages.
Part of the reason so many are for programs written in C is because so
many programs are written in C.
#include <stdio.h>

int main ( void )
{long l = 420000;
long *lp = &l;

short *sp;
*sp = (short)*lp; /* ill-advised, but Let's Pretend */

This is very different. If you were trying to fix the code further up so
it would compile what you wanted was:
short *sp = (short*)*lp; /* ill-advised, but Let's Pretend */
printf(" sizeof(short)==%u sizeof(int)==%u \n",
(unsigned) sizeof(short), (unsigned) sizeof(int));
printf("in order, ell then the short %ld %hdh\n", l, *sp);
return 0;
}
/* end source */
Now that you bring this snippet up again, I think this code shows why it's
usually a bad idea to do things along this line. I'm not sure that this is
what Mr. Sosman was getting at.

Try it on both big and little endian systems, you can even do it with a
pencil and paper if you don't have both, you will then see the very
different results.

As a general rule casting is a bad idea. There are a few places where it
is required,
> As to the syntax on the printf, I've done
everything short of Dedekind cuts on table B-1 and am still pulling out my
hair.

printf is relatively simple, it is scanf that is tricky! If you want to
ask specific questions about printf where you can't understand your text
book I'm sure someone will answer them.
> I'm afraid that I don't know what Bugtraq is ... probably at my own
peril.

Basically a database of bugs.
> Am I correct to think that a type of masking occurs here? joe

No, not masking. More a case of only reading part of the data with my
"fix". Or with your code writing to an uninitialised pointer and causing
half of your socks to migrate to Alaska.

BTW, I would not place too much face in anything posted by
RSoIsCaIrLiIoA. A Google search and seeing how often it has posted
assembler will show you why many people probably have it kill filed.
 
R

RSoIsCaIrLiIoA

RSoIsCaIrLiIoA said:
Joe Smith wrote:
[motivation]
Assume sizeof(int) < sizeof(long), and consider

long l = 42;
int *ip = &l; /* illegal, but Let's Pretend */
*ip = 76;

What value is now stored in `l'?

That's why int* and long* aren't interchangeable.

and so where is the problem?
the problem is different cpus store data in different ways

here

#include <stdio.h>

int main ( void )
{int l = 42;
short *ip = &l; /* illegal, but Let's Pretend */

*ip = 76;
printf(" sizeof(short)==%u sizeof(int)==%u \n",
(unsigned) sizeof(short), (unsigned) sizeof(int));
printf("l==%d\n", l);
return 0;
}

sizeof(short)==2 sizeof(int)==4
l==76

all ok

the problem is "it is easy to obfuscate and make difficult
what it is easy" and it is in the cpu design

another example could be why not exchange "str* and sprintf, etc"
with a secure
int s?prinf(char* strig, int size_of_string, char* fmt, ...);?

because it is easier "to do difficult what is easy" then
Bugtraq is full of error for the C language

#include <stdio.h>

int main ( void )
{long l = 420000;
long *lp = &l;

short *sp;
*sp = (short)*lp; /* ill-advised, but Let's Pretend */

printf(" sizeof(short)==%u sizeof(int)==%u \n",
(unsigned) sizeof(short), (unsigned) sizeof(int));
printf("in order, ell then the short %ld %hdh\n", l, *sp);
return 0;
}
/* end source */
Now that you bring this snippet up again, I think this code shows why it's
usually a bad idea to do things along this line. I'm not sure that this is
what Mr. Sosman was getting at. As to the syntax on the printf, I've done
everything short of Dedekind cuts on table B-1 and am still pulling out my
hair. I'm afraid that I don't know what Bugtraq is ... probably at my own
peril. Am I correct to think that a type of masking occurs here? joe
do you happily think i compile yuour shit? :)
 
R

RSoIsCaIrLiIoA

Joe said:
RSoIsCaIrLiIoA said:
[motivation]
Assume sizeof(int) < sizeof(long), and consider

long l = 42;
int *ip = &l; /* illegal, but Let's Pretend */
*ip = 76;

What value is now stored in `l'?

That's why int* and long* aren't interchangeable.
and so where is the problem?
the problem is different cpus store data in different ways

here

#include <stdio.h>

int main ( void )
{int l = 42;
short *ip = &l; /* illegal, but Let's Pretend */

*ip = 76;
printf(" sizeof(short)==%u sizeof(int)==%u \n",
(unsigned) sizeof(short), (unsigned) sizeof(int));
printf("l==%d\n", l);
return 0;
}

sizeof(short)==2 sizeof(int)==4
l==76

all ok

On your system, but not on mine. I regularly work on both big and little
endian systems and if you fix the above so it actually compilers you
will get very different results.

#include <stdio.h>

int main ( void )
{int si=sizeof(int), ss=sizeof(short);
int l = 0x120000;
short *ip = &l; /* illegal, but Let's Pretend */

if(2*ss!=si||si<2) return 0;
if(*ip==0x0012) ip[1]=0x3456;
else *ip =0x3456;
printf(" sizeof(short)==%u sizeof(int)==%u \n",
(unsigned) sizeof(short), (unsigned) sizeof(int));
printf("l==0x%x\n", l);
return 0;
}

has this the same bihaviour for both big and little endian systems?
here it has
sizeof(short)==2 sizeof(int)==4
l==0x123456

this is little of big endian? it would be little right? (because the
little value is near the pointer)
BTW, I would not place too much face in anything posted by
RSoIsCaIrLiIoA. A Google search and seeing how often it has posted
assembler will show you why many people probably have it kill filed.

an this what mean?
 
J

Joe Smith

Flash Gordon said:
Joe said:
[snip]
#include <stdio.h>

int main ( void )
{long l = 420000;
long *lp = &l;

short *sp;
*sp = (short)*lp; /* ill-advised, but Let's Pretend */
This is very different. If you were trying to fix the code further up so
it would compile what you wanted was:
short *sp = (short*)*lp; /* ill-advised, but Let's Pretend */
How thick is my head ^ ?
Try it on both big and little endian systems, you can even do it with a
pencil and paper if you don't have both, you will then see the very
different results.

As a general rule casting is a bad idea. There are a few places where it
is required,
As to the syntax on the printf, I've done
everything short of Dedekind cuts on table B-1 and am still pulling out
my hair.

printf is relatively simple, it is scanf that is tricky! If you want to
ask specific questions about printf where you can't understand your text
book I'm sure someone will answer them.
I sometimes mistake the one table for the other!

Basically a database of bugs.
Sounds like something that, according to fashion, merits a huge investment.
No, not masking. More a case of only reading part of the data with my
"fix". Or with your code writing to an uninitialised pointer and causing
half of your socks to migrate to Alaska.
Am I not reading, with correction, the number that a smaller type thinks a
larger type was? My socks are well accounted for, but Scott Knuds not only
flew out of my hard drive, but is eating my lunch.
BTW, I would not place too much face in anything posted by RSoIsCaIrLiIoA.
A Google search and seeing how often it has posted assembler will show you
why many people probably have it kill filed.
He sounds like a dude, so you can be assured that I won't give him face, but
until otherwise motivated, I'll give him the benefit of the doubt. Thanks
for your reply. Joe
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,731
Messages
2,569,432
Members
44,832
Latest member
GlennSmall

Latest Threads

Top