简体   繁体   中英

Printf() printing of arguments and pointers in C

Okay so basically i am trying to understand what is happening here with printf and pointers in various forms

this is the code

#include <stdio.h>
#include <stdlib.h>

typedef struct mine{
   unsigned int  memory;
   struct mine * next;
}mine;


int main(int argc, char *argv[]){

   mine * y;

   y = (struct mine *)malloc(sizeof(struct mine));
   y->memory = 0xBEEFDEAD;

   printf("%x\n",*y);
   printf("%x\n",y[0]);
   printf("%x\n",y->memory);
   printf("%x %x %x\n",y->memory, *y,y[0]);

   return 0;
}

and here is the output

beefdead
beefdead
beefdead
beefdead beefdead 7c00c0

as you can see the same pointers being printed give a different result with printf when they are separated individually and when they are grouped together

is this a problem with the way i am printing the pointers, or is this a problem with printf

also does *y = y[0] = y->memory

from the output i am not sure about the answer to this question

When you do this:

printf("%x\n",*y);

Or this:

printf("%x\n",y[0]);

You're feeding a struct mine to the %x format specifier. This is undefined behavior, which means anything could happen.

In the case of your particular compiler on your particular machine, the %x specifier is probably picking up the first 4 bytes of the struct mine that's being passed in which happens to be the contents of memory . But you can't depend on this behavior. It could very well do something different if you use a different compiler or even run the same executable on a different machine.

In the case of this line:

printf("%x %x %x\n",y->memory, *y,y[0]);

The first parameter is fine and will always print what you expect. The second parameter invokes undefined behavior as mentioned previously. On your particular machine with your particular compiler, it prints the contents of memory for the second %x as in the prior example. In the case of the third %x , it looks for the next 4 bytes on the stack. This is not the y[0] you passed in but the contents of next from when *y was passed in, since a struct mine was passed for the second parameter which contains 8 bytes.

But again, this behavior is undefined. It could print something entirely different if you use a different compiler, change the compiler settings, or run on a different machine. There's no guarantee that what happened for you will always happen.

This is not an issue with printf as you suggested in the comments. This is you invoking undefined behavior.

EDIT:

If you're attempting to view the address of y->memory , *y , and y[0] , you need to pass the address of each of these and use the %p format specifier to output them correctly:

printf("%p %p %p\n", (void *)&y->memory, (void *)y, (void *)&y[0]);

Since y[0] is equivalent to *(y + 0) (ie *y ), and because memory is the first field of the struct, this will output three identical (system dependent) values.

is this a problem with the way i am printing the pointers

Code never attempts to print pointers. Code attempts to print *y , y[0] , y->memory . These are types mine , mine , and unsigned .

To print a pointer like y , use printf specifier "%p" and cast to (void *) if the pointer is not all ready a void * .

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

To print the contents of a structure like struct mine , print the individual sub-fields. See below.

Mis-matched print format specifiers with the passed augments result in behavior that is specified by the C spec to be undefined behavior . The results may be anything? Any explanation of such behavior relies on many assumptions concerning the underlying generate code and frankly is a lot of guess-work.

Use matching printf() format specifiers with values of the matching type.

Many compilers warn of such mis-matches. Insure your compiler's warnings are fully enabled. Saves you time.


"%x" matches an unsigned , not type mine . Result: undefined behavior.

mine * y;
...
// printf("%x\n", *y);
// Instead:
printf("%x %p\n", y->memory, (void *) y->next);

Same for printf("%x\\n", y[0]); Result: undefined behavior.

// printf("%x\n", y[0]);
// Instead:
printf("%x %p\n", y[0].memory, (void *) y[0].next);

Same for printf("%x\\n", y[0]); Result: undefined behavior.

// printf("%x %x %x\n", y->memory, *y, y[0]);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM