int *p=7

N

niklaus

int *p=3;

int main()
{
int *p=0;
printf("%x\n",p);
return 0;
}
prints 0 on all the platforms i test or i set a breakpoint at printf
and then print the value of
p just after int *p=0, i get 0.

the behaviour is implementation defined according to
http://www.vmunix.com/~gabor/c/draft.html#6.2.2.3

Can someone tell me why it s implementation defined and where it
differs ,
can't i say value of p after int *p=0 or int *p=3 is 0 or 3
 
R

Richard Heathfield

(e-mail address removed) said:
int *p=3;

int main()
{
int *p=0;
printf("%x\n",p);
return 0;
}

foo.c:1: warning: initialization makes pointer from integer without a cast
foo.c:4: warning: function declaration isn't a prototype
foo.c: In function `main':
foo.c:5: warning: declaration of `p' shadows global declaration
foo.c:6: warning: implicit declaration of function `printf'
foo.c:6: warning: unsigned int format, pointer arg (arg 2)

The program contains at least three serious problems, which are indicated by
the first, fourth, and fifth warnings above.

The third warning answers your actual question.
 
N

niklaus

Richard said:
(e-mail address removed) said:


foo.c:1: warning: initialization makes pointer from integer without a cast
foo.c:4: warning: function declaration isn't a prototype
foo.c: In function `main':
foo.c:5: warning: declaration of `p' shadows global declaration
foo.c:6: warning: implicit declaration of function `printf'
foo.c:6: warning: unsigned int format, pointer arg (arg 2)

The program contains at least three serious problems, which are indicated by
the first, fourth, and fifth warnings above.

The third warning answers your actual question.

#include<stdio.h>
int
main ()
{
int *p =0;
printf ("%x\n", p);
return 0;
}
i get a warning tt.c:6: warning: unsigned int format, pointer arg (arg
2)


#include<stdio.h>
int
main ()
{
int *p =0;
printf ("%p\n", p);
return 0;
}
i get a warning tt.c:6: warning: void format, different type arg (arg
2)

#include<stdio.h>
int
main ()
{
int *p =0;
printf ("%p\n", (void *)p);
return 0;
}

no warning i get 0 , i the original answer i don't understand clearly.
Can you throw some light on it Richard.
 
V

valis.eric.ykchan

6 Any pointer type may be converted to an integer type. Except as
previously specified, the
result is implementation-defined. If the result cannot be represented
in the integer type,
the behavior is undefined. The result need not be in the range of
values of any integer
type.

ISO/IEC 9899:1999 (E)

Maybe you can implement pointer that cannot be represented in 32-bit
integer, although almost all implementations allows.
 
C

Chris Dollin

int *p=3;

Illegal declaration: `3` isn't a pointer. Your compiler
should say "NO".
int main()
{
int *p=0;

A new and different `p`, legally initialised to the null pointer.
printf("%x\n",p);

Undefined behaviour, since `%x` is for printing integers not
pointers (and you haven't #included <stdio.h>. A good compiler
will say "OI". Sadly, on many machines this will just print `0`
without warning.
return 0;
}
prints 0 on all the platforms i test or i set a breakpoint at printf
and then print the value of
p just after int *p=0, i get 0.

Why are you surprised?
 
B

bert

#include<stdio.h>
int
main ()
{
int *p =0;
printf ("%x\n", p);
return 0;
}
i get a warning tt.c:6: warning: unsigned int format, pointer arg (arg
2)


#include<stdio.h>
int
main ()
{
int *p =0;
printf ("%p\n", p);
return 0;
}
i get a warning tt.c:6: warning: void format, different type arg (arg
2)

#include<stdio.h>
int
main ()
{
int *p =0;
printf ("%p\n", (void *)p);
return 0;
}

no warning i get 0 , i the original answer i don't understand clearly.
Can you throw some light on it Richard.

Richard contributes a lot to this group, always excellent,
and if he gets a bit concise when he is repeating it, then
that's neither his fault nor yours.

You have two variables "p" in your program, and they
are just as distinct TO THE COMPILER as if their
names were distinct. The compiler has rules to decide
which one you mean, each time you use "p". It is clever
enough to warn you that you have made the outer "p"
unusable in the part of your program where the inner "p"
is usable. It is not quite clever enough to explain that
"shadowing" is the jargon term for this, nor to see that
there is nowhere in your program that tries to use the
outer "p" anyway - but, if there was, you would probably
have been glad of the warning.
--
 
L

Lew Pitcher

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1


#include<stdio.h>
int
main ()
{
int *p =0;
printf ("%p\n", (void *)p);
return 0;
}

no warning i get 0 , i the original answer i don't understand clearly.
Can you throw some light on it Richard.

Your use of pointers is confusing the issue. Your original problem
(which Richard answered in a round about way) has nothing to do with
pointers.

Try this code...
#include <stdio.h>

int p=3;

int main(void)
{
int p=0;
printf("%d\n",p);
return 0;
}

It still exhibits your initial problem.

Now, to answer your question...

objects declared within a function override, for the duration of the
function, objects declared outside of the function. Thus, while in
main(), there are /two/ variables called p: one at a "global" level,
and one at a "local" level within function main(). The one that main()
will use is the "local" level, unless otherwise instructed.

HTH
- --
Lew Pitcher



-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.3 (MingW32) - WinPT 0.11.12

iD8DBQFFDq6wagVFX4UWr64RAqabAKDFGwOfda0pphGTyX2IBVCaea2iHQCfezhf
+mjtHiKWuVWGv5NJfgJq/f0=
=KWES
-----END PGP SIGNATURE-----
 
R

Richard Heathfield

(e-mail address removed) said:
#include<stdio.h>
int
main ()
{
int *p =0;
printf ("%x\n", p);
return 0;
}
i get a warning tt.c:6: warning: unsigned int format, pointer arg (arg
2)


#include<stdio.h>
int
main ()
{
int *p =0;
printf ("%p\n", p);
return 0;
}
i get a warning tt.c:6: warning: void format, different type arg (arg
2)

Yes, %p is the format specifier for "void pointer". This is one of the very,
very, very few times when a cast is required:

printf("%p\n", (void *)p);
#include<stdio.h>
int
main ()
{
int *p =0;
printf ("%p\n", (void *)p);
return 0;
}
Right.


no warning i get 0 , i the original answer i don't understand clearly.

Your original program had two p pointers. Same name, but different objects
at different scopes. The one in main() "shadowed" (obscured) the one at
file scope.

Here's your original program, but fixed up to be correct and explanatory:

#include <stdio.h>

int someinteger;
int *p = &someinteger; /* this p is at file scope */

void foo(void)
{
printf("p in foo: %p\n", (void *)p);
}

int main(void)
{
int *p = 0; /* this p is local to main */

printf("&someinteger: %p\n", (void *)&someinteger);

printf("p in main: %p\n", (void *)p);
foo();
printf("p in main: %p\n", (void *)p);
return 0;
}

and here's the output on my system:

&someinteger: 0x8049824
p in main: (nil)
p in foo: 0x8049824
p in main: (nil)

Let's look at the output line by line:

&someinteger: 0x8049824

This tells us the address of someinteger, which is an int object with file
scope. The p at file scope is given this object's address as its value.

p in main: (nil)

This tells us the value of the p that is local to main. In this case, it's a
null pointer, so gcc tells me "(nil)", which is a fair enough way to
represent it, although personally I'd prefer "0x00000000".

p in foo: 0x8049824

This tells us that, when we get out from under the shadow of the local
pointer defined in main(), we can still have access to the file scope
pointer. And as you can see, it's still pointing at someinteger.

p in main: (nil)

This again tells us the value of the p that is local to main. And it's still
a null pointer. It hasn't changed, and it's still "shadowing" (obscuring)
the p at file scope.

I hope that clears up your confusion. If not, please explain what is still
confusing you.
 
R

Rod Pemberton

int *p=3;

int main()
{
int *p=0;
printf("%x\n",p);
return 0;
}


Your pointer address(es) need to be cast. 0 and 3 are 'int', but p is 'int
*':

int *p=(int *)3;

int main()
{
int *p=(int *)0;
printf("%x\n",(unsigned int)p); /* 0 */

return 0;
}


Also, try it this way without the second declaration. This shows that p is
being set to three prior to the second declaration:

int *p=(int *)3;

int main()
{
/* int *p=(int *)0; */
printf("%x\n",(unsigned int)p); /* 3 */

return 0;
}


Some compilers don't like this, but for those that do, you should get 3 and
0 respectively. This demonstrates the scope of p or the range over which p
is 3 and 0 respectively:

int *p=(int *)3;

int main()
{
printf("%x\n",(unsigned int)p); /* 3 */

int *p=(int *)0;
printf("%x\n",(unsigned int)p); /* 0 */

return 0;
}
Can someone tell me why it s implementation defined and where it
differs ,
can't i say value of p after int *p=0 or int *p=3 is 0 or 3

The value of p when cast properly is either 0 or 3.


Rod Pemberton
 
K

Keith Thompson

Rod Pemberton said:
Your pointer address(es) need to be cast. 0 and 3 are 'int', but p is 'int
*':

But 0 is a null pointer constant, which can legally be used to
initialize a pointer variable (it's implicitly converted to a null
pointer value). See section 5 of the comp.lang.c FAQ,
int *p=(int *)3;

This initializes p to the value 3 converted to int*. It's very
unlikely that this will be meaningful. (If you happen to know that
there's some int object at address 3 you can do this.)
int main()
{
int *p=(int *)0;

The cast is unnecessary.
printf("%x\n",(unsigned int)p); /* 0 */

This converts x from int* to unsigned int. The result of such a
conversion is implementation-defined, and may not be meaningful. An
unsigned int may not even be big enough to hold the value of a
pointer.

If you want to print the value of a pointer, cast it to void* and use
"%p".
 
R

Rod Pemberton

Keith Thompson said:
But 0 is a null pointer constant, which can legally be used to
initialize a pointer variable (it's implicitly converted to a null
pointer value). See section 5 of the comp.lang.c FAQ,
<http://www.c-faq.com/>, for more information on null pointers.

And, it may or may not actually point to physical address zero due to
segmentation or it may be non-zero NULL if an object or function uses that
address. What does this have to do with the OP's problem of not casting
addresses or, perhaps, declaring his variables improperly? (nothing) You act
as if I wrote the code instead of correcting it in a manner which would I
believe will benefit the OP.
This initializes p to the value 3 converted to int*. It's very
unlikely that this will be meaningful. (If you happen to know that
there's some int object at address 3 you can do this.)

Whether it is useful or not is up to him. I believe to be more inline with
what the OP was _trying_ to do than the other posts.
The cast is unnecessary.

The point was to teach him about casting addresses, and being aware of type
differences. But, once again, you seem lost... Did you understand that
this is a beginner in C? Why do you intend to confuse him with advanced
topics such as how NULL is implemented and whether it corresponds to
physical address and what value it may be? You ripped me to shreds over
teaching a new programmer the truth about the advanced topic of arrays being
pointers... Now you turn around and do the same... Pick one side and stay
there.
This converts x from int* to unsigned int. The result of such a
conversion is implementation-defined, and may not be meaningful. An
unsigned int may not even be big enough to hold the value of a
pointer.

If you want to print the value of a pointer, cast it to void* and use
"%p".

I simply corrected the OP's code keeping his preferred conversion. If I had
written it, I'd have used '%08lx' and '(unsigned long)' since it works where
I need it.

First, %p also prints in an "implementation-defined" manner which may be
just as useless. (ISO C 7.19.6.1)

Second, all pointer conversions are capable of producing UB. (ISO C 6.3.2.3
sub 7)

Third, the conversion from an 'int *' to a 'void *' is also
"implementation-defined, and may not be meaningful." It is only required
that conversion of a type such as an 'int *' to 'void *' and _back_ to the
original type, 'int *', from the intermediate 'void *' be lossless. (ISO C
6.3.2.3) The resulting 'void *' is required to be the functionally the same
as a 'char *' (ISO C 6.2.5 s 26). But, only explicit conversions to 'char
*', i.e., not 'void *', are required to be "meaningful" by pointing to the
lowest byte of the object. (ISO C 6.3.2.3 sub 7) Other than being required
to be functionally equivalent to a valid pointer to char, I don't see
anything requiring the intermediate 'void *' to be a "meaningful"
representation of the 'int *'.

However, all of the "not meaningful" argument is based entirely on the
abstraction of C from assembly and not valid in reality. In reality, all
addressing is based on the underlying cpu and assembly which is usually
ordered thereby making the intermediate 'void *' "meaningful."


Rod Pemberton
 
K

Keith Thompson

Rod Pemberton said:
And, it may or may not actually point to physical address zero due to
segmentation or it may be non-zero NULL if an object or function uses that
address.

Of course. All of this is covered in section 5 of the FAQ, which I
referred to above.
What does this have to do with the OP's problem of not casting
addresses or, perhaps, declaring his variables improperly? (nothing) You act
as if I wrote the code instead of correcting it in a manner which would I
believe will benefit the OP.


Whether it is useful or not is up to him. I believe to be more inline with
what the OP was _trying_ to do than the other posts.

I don't know what the OP was trying to do.

int *p = 3;
is a constraint violation; even if that's corrected, it's still not
likely to be useful. Both of these things are worth knowing.

If somebody posted something like this:

My function call:

Shoot_Myself_In_The_Foot;

isn't working; the function is never called.

it would be worth pointing out that the function call requires
parentheses, but I would *also* point out that shooting yourself in
the foot probably isn't a good thing to do. (A silly example, but I
think it makes the point.)

[snip]
You ripped me to shreds over
teaching a new programmer the truth about the advanced topic of arrays being
pointers... Now you turn around and do the same... Pick one side and stay
there.

I'm not sure what you're referring to here. When did I rip you to
shreds over that issue? (If you claimed that arrays are really
pointers, I probably corrected you, because they really aren't, but I
don't remember the discussion.)
I simply corrected the OP's code keeping his preferred conversion. If I had
written it, I'd have used '%08lx' and '(unsigned long)' since it works where
I need it.

And "%p" works everywhere. My advice to the OP stands: don't try to
use integer format strings to print pointer values. Use "%p"; that's
what it's for. I offer exactly the same advice to you. I don't know
why you'd want to print a pointer value using "%08lx" when "%p" is
available.
First, %p also prints in an "implementation-defined" manner which may be
just as useless. (ISO C 7.19.6.1)

Of course, it has to be implementation-defined because the standard
(quite rightly) imposes no universal requirements for how pointers are
represented. But "%p" has the virtue of not invoking undefined
behavior.

You just have to depend on the implementation to define its "%p"
conversion in some meaningful way. I've never seen an implementation
that fails to do so. If I had to work with such an implementation I
might consider using "%x" or "%lx" or something similar (or I might
write a routine that decomposes the pointer value into bytes and
prints them in hexadecimal).
Second, all pointer conversions are capable of producing UB. (ISO C 6.3.2.3
sub 7)

A pointer conversion invokes UB only if the resulting pointer is not
correctly aligned for the pointed-to type. If you're converting to
void* or char*, no such misalignment is possible.

[snip]
However, all of the "not meaningful" argument is based entirely on the
abstraction of C from assembly and not valid in reality. In reality, all
addressing is based on the underlying cpu and assembly which is usually
ordered thereby making the intermediate 'void *' "meaningful."

You're willing to settle for something that usually works. I prefer
to use something that always works.
 
O

Old Wolf

Rod said:
The point was to teach him about casting addresses, and being
aware of type differences.

Well, you failed. This code doesn't cast any addresses.

Even worse, your code looks as if it is an attempt to cast
address 0 to a pointer (which is NOT the effect that this code has).
Did you understand that this is a beginner in C?

Some people (myself included) believe that teaching beginners
rubbish in order to make a point, is actually counter-productive
to actual learning. Learning involves the learner making mental
connections on his own, and if you put garbage in you get
garbage out.

I call your code "rubbish" because no competent C programmer
would ever write that code. Its effect is exactly equivalent to the
code without the cast; and the cast only serves to cause
obfuscation by making it look like code to try and generate a
pointer to address 0.
Why do you intend to confuse him with advanced topics such
as how NULL is implemented and whether it corresponds to
physical address and what value it may be?

It was you who introduced the topics of how NULL is implemented
and what physical address it corresponds to. Check the thread
history.

Anyway, the OP wrote code that creates a null pointer. I think
it is better to point this out (which is exactly what Keith did,
and no more), than to pretend the code does something else.
You ripped me to shreds over teaching a new programmer the truth
about the advanced topic of arrays being pointers...

Arrays are NOT pointers. If you got ripped to shreds, it was most
likely because you tried to lecture on a topic where you didn't
actually have a clue.... like you are doing here.

Can you provide a message ID for this other thread you refer to?
 

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

No members online now.

Forum statistics

Threads
473,770
Messages
2,569,584
Members
45,075
Latest member
MakersCBDBloodSupport

Latest Threads

Top