Home > Software engineering >  Are the bytes allocated by variables consecutive in memory?
Are the bytes allocated by variables consecutive in memory?

Time:04-23

New to C here, I am studying pointers. So my question "Are the bytes allocated by variables consecutive in memory?" is because I thought that by creating a char pointer from an integer pointer (char *p_c = p_i - (sizeof(char))), the char pointer would point exactly to the second byte of the integer.

E.g.: An integer variable takes 4 bytes and a char variable takes 1 byte.

#include <stdio.h>

int main(){
    int a = 4276545;
    int *p = &a;
    char *p_c1 = p - (1*sizeof(char));
    printf("Value of p_c1 (second byte of a) is %c\n", *p_c1);
}

The ASCII 'A' char in binary is 01000001. 4276545 decimal to binary is 00000000 01000001 01000001 01000001.

Isn't p_c1 pointing to 00000000 01000001 01000001 01000001?

Printing *p_c1, I was expecting it to be 'A', but it prints 'P'. And it's not as it was a random char which always changes in each execution, it always prints 'P'. Why?

CodePudding user response:

sizeof(char) is guaranteed to be 1 (no matter how many bits it is), so you have char *p_c1 = p - 1;

Problem 1:

When you add to or subtract from a pointer, you change the address by sizeof(*p), so you're not changing the address by one byte, but by sizeof(int) bytes. This is necessary because of the a[i] == *(a i) equivalency.

Problem 2:

You are subtracting when you should be adding. The address of something is the address at which it starts, so subtracting would lead to a position outside of a. You want to move into a, so you'd want to add.

Fixed:

int a = 0x41424344;
char *p = (char *)&a;
for ( size_t i=0; i<sizeof(int);   i )
   printf( "%zu %d %c\n", i, *(p i), *(p i) );

The output varies by system, but you should get the following on a little-endian system with an char type which is 8 bits in size and an int type that's 32 bits in size:

0 68 D
1 67 C
2 66 B
3 65 A

CodePudding user response:

An integer variable takes 4 bytes

This is a wrong statement. The correct statement is that an integer takes at least 2 bytes if CHAR_BIT=8 and at least 1 byte if CHAR_BIT>=16. There are systems where CHAR_BIT is 64, and on such systems sizeof(TYPE) = 1 for all the types. The idea is, an int must be at least 16 bits in size. There are systems where one needs to make a few fetches to bring an integer into a register.

char *p_c1 = p - (1*sizeof(char));

You can conceive an integer variable int a like an array of length 1. If you take the address of the integer, it is like taking the address of the first element of an array.

What you try to do is to take the previous integer before the address of a (because (1 times sizeof(char) )= 1) and consider the first byte of that integer. This is not correct, it is undefined behavior accessing an array outside its limits, or accessing an address that was not explicitly allocated for a variable.

  • Related