JackSen
JackSen

Reputation: 3

How do bytes and addresses correlate in C?

I have seen that there are many questions related to this topic, but I could not infer an answer, so I decided to ask my first question here on stack overflow. Currently, my question is regarding the bytes and addresses, does each address actually represent one address, meaning that if I would initialize one address e.g. 0x55555555d156 but if I were to initialize an int, it would take 4 addresses, meaning that it will range from e.g. 0x55555555d156 to 0x55555555d160 ? So what confuses me is that, a pointer will hold an address, right?

Let's say the pointer holds the address e.g. 0x55555555d156 and if I were to deference that address I would get the value of that int, right? what about the other 3 addresses, if I deference them? I could not manage to acquire that information by writing a C program.

Upvotes: 0

Views: 106

Answers (3)

M.M
M.M

Reputation: 141598

You can't "dereference an address" -- you can dereference a pointer. A pointer value is an address, but the pointer also has a type. The result of the dereference depends on the pointer's type.

The result of derefencing a pointer is NOT the value stored at the memory location being pointed to. It is an expression that designates an object. This is known as an lvalue in C .

If all of this is unclear; first check that you understand what is happening in the code:

int x = 0;

x = 5;

In the second line, the use of x does not retrieve the value 0. The expression x is an lvalue which means that it designates a region of memory consisting of several bytes. Each byte has its own address. If you output &x you will likely see the same result as if you output the address of the first byte of x (although this is not a Standard requirement), but the types are different.

Whether or not the stored value is retrieved when an lvalue expression appears in the code, depends on the context of the expression. For example if it appears on the left-hand side of the assignment operator, the value is not retrieved.

Once you have understood x = 5; , then *p = 5; behaves identically; the meaning of *p is exactly as if the label x existed for the memory region that p points to.

Upvotes: 0

ForceBru
ForceBru

Reputation: 44838

if I were to deference that address I would get the value of that int, right?

Yes.

what about the other 3 addresses, if I deference them?

If you have int *p = &some_integer;, then *(int *)((char *)p + 1) (dereferencing p "shifted" by one byte) would attempt to read 4 bytes from that new address and interpret them as an integer. Whether your program has permission to read that last byte that's right next to some_integer in memory, is another story: if it doesn't, you'll get a segmentation fault or other memory access issues.

Or you may get no errors and read garbage data.

Example

#include <stdio.h>

int main(void) {
    int my_int = 0x12345678;
    int *ptr = &my_int;

    printf("%x\n", *ptr);
    printf("%x\n", *(int *)((char *)ptr + 1));
}

Output:

~/test $ clang so.c && ./a.out
12345678
80123456
^^
 |-- This "random" byte was read as part of
 --- the "new" int shifted by 1 byte

Upvotes: 1

Lee Daniel Crocker
Lee Daniel Crocker

Reputation: 13171

Different microprocessors have different addressable units of memory. Most, including the x86 series and ARM, are addressable in units of one byte. So, for example, a 32-bit int will be stored in four consecutive memory addresses as you say (LSB first, unless the ARM is set to "Big Endian" mode).

Other processors, like PIC, may have one address point to a 16-bit memory word.

Your C code should probably not make assumptions either way, unless you're sure what the code will be run on.

Upvotes: 0

Related Questions