Why is each element of an int array separated by (4)?
I watched and read many info on pointers arithmetic, but they don't really explain what happen under the hood, they say " an int is 4 bytes" and then they just add that to the address to get the next value.
But how are we adding a (hexadecimal address) to a (byte) to go from (0x7fff2c70e670 4) to ( 0x7fff2c70e674)
shouldn't 4 bytes be converted first to hexadecimal before adding?
I feel like I am missing something but I can't point to it.
int main(void)
{
int numbers[5] = {1, 3, 5, 7, 9};
for (int i = 0; i < 5; i)
{
printf("%d = %p \n",numbers[i], &numbers[i]);
}
}
Result
1 = 0x7fff2c70e670
3 = 0x7fff2c70e674
5 = 0x7fff2c70e678
7 = 0x7fff2c70e67c
9 = 0x7fff2c70e680
CodePudding user response:
It doesn't have to be this way. But it's the way all "byte addressable" machines work, and those are by far the most popular type today.
The basic idea — and it is a basic idea, there's nothing secret or fancy or obscure about it — is just that you represent the computer's memory as a giant array of bytes. Each byte has an address, from 0 up to however many bytes (or kilobytes, or gigabytes) of memory you have in your computer. Each byte is individually addressable, so the addresses increase by 1 from one byte to the next.
Although, many objects you might want to store in memory are bigger than one byte. For example, a 32-bit integer is going to be four bytes.
This picture may help, taken straight from your program and the result you showed:
address | contents |
---|---|
0x7fff2c70e670 | 1 |
0x7fff2c70e671 | 0 |
0x7fff2c70e672 | 0 |
0x7fff2c70e673 | 0 |
0x7fff2c70e674 | 3 |
0x7fff2c70e675 | 0 |
0x7fff2c70e676 | 0 |
0x7fff2c70e677 | 0 |
0x7fff2c70e678 | 5 |
... | ... |
Or it's much easier to see if we look at it four bytes at a time:
0 | 1 | 2 | 3 | |
---|---|---|---|---|
0x7fff2c70e670 | 1 | 0 | 0 | 0 |
0x7fff2c70e674 | 3 | 0 | 0 | 0 |
0x7fff2c70e678 | 5 | 0 | 0 | 0 |
0x7fff2c70e67c | 7 | 0 | 0 | 0 |
0x7fff2c70e680 | 9 | 0 | 0 | 0 |
When we look at a picture like this we can't ignore the fact that the byte order is little-endian, that is, the least-significant byte of a 4-byte integer is stored at the lowest address. We can see this more clearly if we use some larger numbers:
int numbers2[] = {0x01020304, 0x05060708, 0x090a0b0c};
This might give us
0 | 1 | 2 | 3 | |
---|---|---|---|---|
0x7fff2c70e700 | 0x04 | 0x03 | 0x02 | 0x01 |
0x7fff2c70e704 | 0x08 | 0x07 | 0x06 | 0x05 |
0x7fff2c70e708 | 0x0c | 0x0b | 0x0a | 0x09 |
But at the end of the day, it's the bytes that have addresses, not the individual bits.
CodePudding user response:
shouldn't 4 bytes be converted first to hexadecimal before adding?
Shouldn't 4 apples be converted to hexadecimal before adding?
Doesn't really make sense, does it? Bytes are a thing; a conceptual thing rather than a physical thing like an apple, but still a thing.
Hexadecimal is just a way to represent numbers. 0xFF and 255 are the same number, but one is represented in hex and one in decimal.
If you have 0x1A (or 26) apples and you add 4 apples you have 0x1E (or 30) apples. If you have 0x7fff2c70e670 (or 140733938984560) bytes and you add 4 bytes you have 0x7fff2c70e674 (140733938984564) bytes.
A computer uses neither of these internally, they're just for our convenience. It uses binary. So 0xFF and 255 are 11111111 (sort of, it gets complicated).