8

I created a simple program:

#include <stdio.h>

int main()
{
    int s1;
    int s2;
    int s3;
    
    int *p1, *p2, *p3;
    
    p1 = &s1;
    p2 = &s2;
    p3 = &s3;
    
    printf("%d\n%d\n%d", p1, p2, p3);
}

Whenever I run this program, it prints the memory addresses of pointers p1, p2 and p3 and the interesting thing is that these values have differences of 12. I want to know the reason behind this. Why do the addresses differ by 12?

Note: This happens each time I execute the program.

Output:

enter image description here


I tested the same program in many type of variables , the results i gets are ..

When variables are char type. enter image description here


When variables are long type enter image description here


When i declare int array , size each array is 1. enter image description here


When size of second declared array is 2 , it gets extra 4 byte offset. enter image description here

Community
  • 1
  • 1
siddstuff
  • 1,215
  • 4
  • 16
  • 37
  • 1
    Why not use the format specifier designed for printing pointers, or, better yet, `std::cout`? And why not use a valid signature for `main`? – chris May 15 '13 at 21:32
  • A look at the generated code (in a debugger or disassembler) would probably help enlighten you. – cHao May 15 '13 at 21:32
  • 6
    What compiler and platform is this on? – Steve May 15 '13 at 21:32
  • 1
    It depends on the compiler like everyone says. Compiler may have put anything anywhere it wants. You won't see it in release build probably. There could be debug information between those variables, maybe some kind of overflow detection or some feature like on-the-fly compiling while debugging that MSVC has. You can see whatever is in there by looking at disassembly. – Etherealone May 15 '13 at 21:34
  • 3
    What I guess is that, due to the order of assignment, the compiler chose to interleave the `int` and `int*` values, and you are on a 64-bit platform. 4 bytes for each `int`, 8 bytes for each `int*`. But as people say, look at the disassembly. – paddy May 15 '13 at 21:34
  • what is sizeof(int) on your machine? – Christopher Bales May 15 '13 at 21:40
  • 5
    I think you should also read about [correct signatures for `main`](http://faq.cprogramming.com/cgi-bin/smartfaq.cgi?id=1043284376&answer=1044841143) and why [`void main` is bad](http://users.aber.ac.uk/auj/voidmain.cgi). – Iskar Jarak May 15 '13 at 21:42
  • THE SIZE OF int IS 4 BYTE. – siddstuff May 15 '13 at 21:43
  • Alignment on windows... http://msdn.microsoft.com/en-us/library/aa290049(v=vs.71).aspx – 0x90 May 15 '13 at 22:18
  • @siddstuff What now - C or C++? Your title line says C, your tags C and C++... – glglgl May 16 '13 at 07:21
  • Also, Visual Studio should not be used to compile C code, since it doesn't follow any C standard. Use a C compiler instead. – Lundin May 16 '13 at 14:07

2 Answers2

16

I'm guessing this is a debug build. I've tried this program built with Visual Studio 2010. On debug there is a 12 byte difference between addresses. In release mode there is a 4 byte (sizeof(int)) difference.

In debug builds the MSVC compiler adds in extra data to help detect buffer overflows and use of uninitialized memory. If you put a break point on your printf statement and view the memory pointed to by p1 you should see cc in the memory.

There are a number of different magic values that memory is initialized to. cccccccc indicates uninitialzed stack space. For a more detailed list, see the answer to this question: In Visual Studio C++, what are the memory allocation representations?

Community
  • 1
  • 1
Steve
  • 7,171
  • 2
  • 30
  • 52
5

I'm fairly sure that this is a case of "compiler puts extra stuff in to detect when you write to places you shouldn't". Micrsoft does like to do this, so that it can detect when your code is doing bad stuff. Try something like:

void func()
{
  int x = 18;
  int *px = &x;
  px[1] = 4711;
  cout << "px = " << px << " x = " << x << " px[1] = " << px[1] << endl;
}

and see if the compiler doesn't "detect" that this code is doing bad stuff... If it does, it's because it's put "padding" between x and and p, and checks when the function returns that those "padding" areas haven't been touched.

Mats Petersson
  • 126,704
  • 14
  • 140
  • 227
  • `gcc -g -O0 -Wall -fstack-protector-all -Wstack-protector op_code.c -o a.out` does give offset of 4 bytes what protection windows has which gcc doesn't ?? – 0x90 May 15 '13 at 21:53
  • @0x90 (or should I call you NOP?): One of the comments says the OP is using Visual Studio 2008, so not using gcc. – Mats Petersson May 15 '13 at 21:57
  • I know that is why I ask what microsoft's compiler knows to do GCC doesn't ? :) – 0x90 May 15 '13 at 22:01
  • @0x90 AFAIK those are security stack protection flags in gcc (such as stack canaries). In this situation the MSCV compiler is adding information to aid with debugging and error reporting. It only appears in debug builds and not release builds. They are not related to security protections. – Steve May 15 '13 at 22:01
  • @Steve I added the `-g` flag as well – 0x90 May 15 '13 at 22:02
  • @0x90 I don't really know what stack protector does, or how it works, and I don't know the DETAILS of how the MS version works either. But I believe there are similarities in the sense that there is extra padding and those padded fields are checked at certain points in the code to see that they are still OK. If not, some error message is printed and the execution halted. – Mats Petersson May 15 '13 at 22:06
  • 1
    @0x90 My knowledge of `gcc` is limited I'm afraid. But as far as I can tell the `-g` flag adds debugging symbols so you can see some level of code in a debugger, rather than assembler. It does not change the code. http://stackoverflow.com/questions/4884535/does-the-gcc-g-debugging-flag-affect-program-execution – Steve May 15 '13 at 22:06
  • I think the best is to look at the disassembly of the code compiled with visual studio and the one compiled with gcc. thanks – 0x90 May 15 '13 at 22:11