2

I just write a simple program in C as shown below:

#include <stdio.h>
void main()
{
  int *pointer;
  int number = 4;
  printf("number = %d\n",number);
  pointer = &number;
  printf("number = %d and pointer = %d\n",number,pointer);
  printf("pointer = %d and number = %d",pointer,number);
}

and afer execution it prints the output like:

number = 4 and pointer = 8724
pointer = 8724 and number = 9415

So, why is the value changing only for orientation change of printing. I can't justify the rule.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
user2845121
  • 103
  • 3
  • 9
  • 1
    It's because of Heisenberg. – Crowman Oct 04 '13 at 04:14
  • [Huh, can't reproduce that.](http://ideone.com/4VuSHr) – Passerby Oct 04 '13 at 04:14
  • 1
    Your code and output don't match - the first `printf()` doesn't seem to be printed. Make sure you show your actual code and a real execution's output. – mgarciaisaia Oct 04 '13 at 04:22
  • 2
    This is undefined behavior. Why you people always assume that a pointer is an `int`? I mean, how come? It isn't. It **obviously** isn't. Never try to treat it as one. It's undefined behavior. –  Oct 04 '13 at 04:29
  • @H2CO3 some local books (specially DOS) give this wrong information. – Grijesh Chauhan Oct 04 '13 at 04:37
  • 1
    @GrijeshChauhan Aw, that's sad. Very sad. –  Oct 04 '13 at 04:38
  • 1
    The important point here from what @H2CO3 said is that the actual value of the variable `number` is unchanged — it remains 4. It's just that `printf` is printing it incorrectly because it probably only got halfway through printing a (64-bit, probably) pointer. – Matt Patenaude Oct 04 '13 at 04:58

4 Answers4

5

Are you using a 64-bit compilation?

int number = 4;
int *pointer = &number;
printf("number = %d and pointer = %d\n", number, pointer);
printf("pointer = %d and number = %d\n", pointer, number);

If so, the first printf() call in the code above pushes a 4-byte int value and an 8-byte int * value onto the stack, and tells printf() to print two 4-byte quantities. These are apparently the 4-byte int and 4 bytes of the 8-byte address. The second printf() call pushes an 8-byte int * and a 4-byte int onto the stack, and tells printf() to print two 4-byte quantities again. This time, though, they are the two halves of the 8-byte int * value printed separately. This is strictly invoking undefined behaviour, but it is one plausible possibility and would explain the result you saw.

(There are some caveats lurking around. I'm assuming that for a 64-bit compilation, CHAR_BIT == 8, sizeof(int) == 4, and sizeof(int *) == 8; also that the implementation passes arguments on the stack, and possibly some related assumptions that are not strictly guaranteed by the C standard but that do typically apply to 64-bit compilers.)

You should decide what you're trying to do. If you want to see 4 twice, then:

int number = 4;
int *pointer = &number;
printf("number = %d and pointer = %d\n", number, *pointer);
printf("pointer = %d and number = %d\n", *pointer, number);

If you want to see the address, then you should use %p for the address (and strictly cast to void *):

int number = 4;
int *pointer = &number;
printf("number = %d and pointer = %p\n", number, (void *)pointer);
printf("pointer = %p and number = %d\n", (void *)pointer, number);

If you want to control the format for the pointer, then you need C99 #include <inttypes.h> and:

int number = 4;
int *pointer = &number;
printf("number = %d and pointer = 0x%.16" PRIXPTR "\n", number, (uintptr_t)pointer);
printf("pointer = 0x%.16" PRIXPTR " and number = %d\n", (uintptr_t)pointer, number);

Example code

#include <stdio.h>
#include <inttypes.h>

int main(void)
{
    int number = 4;
    int *pointer = &number;
    printf("number = %d and pointer = %d\n", number, pointer);
    printf("pointer = %d and number = %d\n", pointer, number);

    printf("number = %d and pointer = %d\n", number, *pointer);
    printf("pointer = %d and number = %d\n", *pointer, number);

    printf("number = %d and pointer = %p\n", number, (void *)pointer);
    printf("pointer = %p and number = %d\n", (void *)pointer, number);

    printf("number = %d and pointer = 0x%.16" PRIXPTR "\n", number, (uintptr_t)pointer);
    printf("pointer = 0x%.16" PRIXPTR " and number = %d\n", (uintptr_t)pointer, number);

    return 0;
}

Compilation with warnings

GCC 4.8.1 on Mac OS X 10.8.5. Similar warnings are given by clang too.

gcc -O3 -g -std=c11 -Wall -Wextra -Wmissing-prototypes -Wstrict-prototypes -Wold-style-definition   it.c -o it
it.c: In function ‘main’:
it.c:8:5: warning: format ‘%d’ expects argument of type ‘int’, but argument 3 has type ‘int *’ [-Wformat=]
     printf("number = %d and pointer = %d\n", number, pointer);
     ^
it.c:9:5: warning: format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘int *’ [-Wformat=]
     printf("pointer = %d and number = %d\n", pointer, number);
     ^

Example output

number = 4 and pointer = 1417245952
pointer = 1417245952 and number = 4
number = 4 and pointer = 4
pointer = 4 and number = 4
number = 4 and pointer = 0x7fff54797500
pointer = 0x7fff54797500 and number = 4
number = 4 and pointer = 0x00007FFF54797500
pointer = 0x00007FFF54797500 and number = 4

Interestingly, the system manages to print 4 for the number both times in the first two lines of output. I've not studied the assembler to see how that works — but one of the beauties of invoking 'undefined behaviour' is that you cannot complain about the results; any result is valid precisely because the required behaviour is undefined.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
  • 1
    What is `PRIXPTR` ?? I don't know. Is it macro like `PRIu32` ? – Grijesh Chauhan Oct 04 '13 at 04:28
  • 2
    @GrijeshChauhan yes it is. –  Oct 04 '13 at 04:28
  • 2
    @GrijeshChauhan: `PRIXPTR` is the macro that defines the correct conversion specifier for a `uintptr_t` to be printed in upper-case hex. It is related to `PRIu32` in that it comes from ``. – Jonathan Leffler Oct 04 '13 at 04:30
  • @JonathanLeffler Thanks! Very interesting. One more question you uses `0x%.16" PRIXPTR` ? it means whether it is 32-bit or 64-bit machine you wants to print in `16` hex number prefixed by `0x`. – Grijesh Chauhan Oct 04 '13 at 04:35
  • 1
    @GrijeshChauhan: My whole answer is predicated on '64-bit', but yes, the `0x%.16" PRIXPTR` format does mean 16 hex digits, even though the 64-bit addresses only use 12 non-zero hex digits on my Mac (and it would mean 8 leading zeros if it were compiled in 32-bit). See the recently added example output. – Jonathan Leffler Oct 04 '13 at 04:47
2

It is probably due to undefined behavior! As you are passing incorrect format string for address.

Use %p to print address and typecase it to void*.

printf("number = %d and pointer = %p\n",number, (void*)pointer);
printf("pointer = %p and number = %d", (void*)pointer, number);

The fprintf function which printf's section refers back to for the format string paragraph:

If a conversion specification is invalid, the behavior is undefined.[...]

text taken from @Shafik Yaghmour' answer

Community
  • 1
  • 1
Grijesh Chauhan
  • 57,103
  • 20
  • 141
  • 208
1

Use *pointer instead of pointer.

Pointer prints address and *pointer prints value.

printf("number = %d and pointer = %d\n",number, *pointer);  
                                                ^ 
printf("pointer = %d and number = %d",*pointer,number);
                                      ^
Gangadhar
  • 10,248
  • 3
  • 31
  • 50
1

It appears you are using a platform where the size of an int and the size of a pointer are different, or perhaps less likely the parameter passing is different for pointers and ints. There's a mismatch between the type you are trying to print (%d) and the type you are passing (int/pointer in the first case and pointer/int in the second).

Mark Ransom
  • 299,747
  • 42
  • 398
  • 622