1

In XCode I've tried to manipulate const int value by using pointer. Here is the code:

const int con = 5;

int *p;
p = &con;

(*p) +=1;

printf("Add of constant:%p\n",&con);
printf("Add of pointer:%p\n",p);

printf("%d - %d",con,*p);

Result is like that on XCode:

Add of constant:0x7fff5fbff79c
Add of pointer:0x7fff5fbff79c
5 - 6

but on linux virtual machine values of con and *p is same 6.

Why there is a difference between values on XCode?

pcbtt
  • 43
  • 5
  • That code shouldn't even compile with clang (what Xcode uses). The error "Assigning to 'int *' from 'const int *' discards qualifiers" should be produced. If it isn't, you're settings are incredibly forgiving. [See this answer](http://stackoverflow.com/a/12245370/1322972). – WhozCraig Feb 08 '17 at 09:42
  • 1
    Did you check the generated code? I could imagine that the compiler doesn't read `con` as it is const and not volatile and immediately puts the value 5 into parameter list for `printf`. You might try to use `volatile const int con = 5;` Or you might stop abusing weird pointers. ;) – Gerhardh Feb 08 '17 at 10:05
  • @Gerhardh yes volatile did work, I got 6 for both value. :) – pcbtt Feb 09 '17 at 07:04

1 Answers1

1

Tried this with VisualStudio, get the same result as with XCode. Assembly listing proved @Gerhardh point:

  • (*p) +=1; successfully increases value of con in RAM
  • printf("Add of constant:%p\n",&con); prints address of this memory correctly
  • printf("%d - %d",con,*p); doesn't read con value from RAM, but passes 5 directly into printf. Optimization threw away unnecessary read for value known at compile time. Here is related assembly listing

printf("%d - %d",con,*p);

mov         eax,dword ptr [p]                   //get p
mov         ecx,dword ptr [eax]                 //get *p
push        ecx                                 //push *p (3rd param)
push        5                                   //push 5 (2nd param). No read of con
push        offset string "%d - %d" (415800h)   //push addr of format string (1st param)
call        dword ptr [__imp__printf (4182BCh)] //call printf()

Obviously, compiler on your VM didn't perform the same optimization.

nnovich-OK
  • 2,900
  • 2
  • 13
  • 16
  • You mean const variable act like a macro? – pcbtt Feb 09 '17 at 07:03
  • No. The compiler knows that you initialzed it with 5. And you are not allowed to modify it. Without volatile keyword the compiler is not forced to read it again for each access. – Gerhardh Feb 09 '17 at 07:13
  • In described case yes. Compiler replaced `printf("%d - %d",con,*p);` with `printf("%d - %d",5,*p);` since con value is expected to be known at compile time. – nnovich-OK Feb 09 '17 at 07:13
  • If you have a register of some clock hardware it would be an option to defibe the variable const volatile. The you mustn't write to it but it can change autonatically. Due to volatile it must be read each time. This is not how a macro works – Gerhardh Feb 09 '17 at 07:15
  • @Gerhardh, Generally speaking, you are totally right. `const` and macro are different approaches and they never meant to be the same thing. But @pcbtt is trying to understand code generated for this particular case with `printf` and indeed it's identical to the following: `#define con 5 printf("%d - %d",con,*p);`. So precise answer should be "const and macro aren't the same thing, but in this particular case they behave identically" – nnovich-OK Feb 09 '17 at 07:21
  • If the mechanism is totally different then I would not emphazise that the result is similar in this case. If you don't point out the differences, @pcbtt might come to the right result for the wrong reasons and will not understand when it is same and when it is not. – Gerhardh Feb 09 '17 at 07:26