-2

I declared an integer (32bits) and a char (8), and I know that a computer address is 1 byte at a time, so why is the difference between those two addresses is 16 and not let's say 40? if each memory address is 8 bits and the size of an integer is 32, then the range is expected to be greater than 16, no?

int main(void)
{
    char a = 'g';
    int b = 5;
    printf("%p %p\n", &a, &b);

    return 0;
}
(gdb) p 0x7fffadfcc2c0 (a) - 0x7fffadfcc2b0 (b)
$1 = 16
rikie
  • 1
  • I think what you're seeing here is the effect of memory alignment: https://stackoverflow.com/questions/381244/purpose-of-memory-alignment – Erwin Jun 23 '22 at 19:46
  • 2
    Depends on the compiler. For example GCC12.1 for x86-64 Linux gives either `-1` with optimization or `7` without. https://godbolt.org/z/89rhh4zq4. Or also `-1` with `-O0 -fstack-protector-strong`. Perhaps for Windows x64, your compiler chose to put locals in the shadow space allocated by the caller, and just happened to choose the start of two non-adjacent 8-byte slots? IDK, you didn't say what compiler / version / options / target OS you were using, so it's all just arbitrary chance. But Windows x64 shadow space would make room for a 16B gap without wasting unnecessary stack space. – Peter Cordes Jun 23 '22 at 19:54
  • @PeterCordes I use GCC 9.4.0 on Ubuntu~20.04.1, x86-64 with `-Werror -Wall -fsanitize=address -fno-omit-frame-pointer -g -O1`. How is it possible that the addresses have a range of `-1` between each other? In my case no matter what optimization level I use it still remains the same (16). Thanks – rikie Jun 24 '22 at 05:44
  • The 1-byte `char` is one byte below below the `int`. See prl's answer; x86 is byte-addressable, not bit, so `1` or `-1` means 1 byte apart. Yeah, your options reproduce the 16: https://godbolt.org/z/EWe4GKGzP `-fsanitize=address` uses up a bunch of extra stack space, apparently. (Actually `-16`). I get `-1` because GCC happened to put `b` at a higher address, so the subtraction is negative. – Peter Cordes Jun 24 '22 at 05:51
  • I'm printing `&a - (char*)&b` just like you say you're doing manually in GDB. Even without having to compute the extra arg, GCC lays them out that way. Could be a random difference in compiler internals between slightly different versions or some other option that's on by default in Ubuntu that I didn't enable (besides stack-protector and `-fPIE`). Or maybe you just got them backwards in your GDB subtraction. – Peter Cordes Jun 24 '22 at 05:53
  • In my Godbolt links, look at the optimized asm: you can see the stores to a dword at `[rsp+12]` and a byte at `[rsp+11]` that init those local vars. – Peter Cordes Jun 24 '22 at 05:54
  • @PeterCordes Yeah I know that x86 is byte-addressable, I don't know why you guys assume I don't. Anyway I apologize for the confusion, thank you! – rikie Jun 24 '22 at 06:01
  • 1
    Because you wrote *if each memory address is 8 bits and the size of an integer is 32, then the range is expected to be greater than 16, no?*. You might expect a 1-byte and a 4-byte type to be at least 4 bytes away if you forget about the possibility of the byte being right below the int, but we've been assuming that the expectation of greater than 16 separate actually comes from thinking about bits, not bytes. If not, why do you think the addresses should be more than 16 *bytes* apart? I can't even think of a reason to expect that, and clearly it's not the case in practice. – Peter Cordes Jun 24 '22 at 06:03
  • @PeterCordes Yeah without the additional GCC arguments the difference is indeed 1. Don't you think that 16 bytes is too inefficient for a compiler to pad? – rikie Jun 24 '22 at 06:05
  • @PeterCordes No you are completly right, my bad on that one, I didn't notice I wrote it that way. – rikie Jun 24 '22 at 06:07
  • `-fsanitize=address` is very inefficient because it takes extra bookkeeping to detect errors! It's not intended for release builds. Similar to `-fsanitize=undefined`. Look at Godbolt, you can see how much extra asm it generates, as well as the amount of stack space if uses. – Peter Cordes Jun 24 '22 at 06:24

1 Answers1

1

The difference between memory addresses is in bytes, not bits.

The minimum difference between the addresses of these two variables is 1, if the address of a is less than the address of b, because the size of a is 1 byte.

The minimum difference is 4, if the address of b is less than the address of a, because the size of b is 4 bytes.

prl
  • 11,716
  • 2
  • 13
  • 31