0

I am relatively new to C and am just learning about ways that memory is stored during a program. Can someone please explain why the following code:

int main(int argc, char** argv){
    float x[3][4];
    printf("%p\n%p\n%p\n%p\n", &(x[0][0]), &(x[2][0]), &(x[2][4]), &(x[3][0]));
    return 0;
}

outputs this:

0x7fff5386fc40
0x7fff5386fc60
0x7fff5386fc70
0x7fff5386fc70

Why would the first 3 be different places in memory but the last be the same as the third? Why is there a gap the size of 20 between the first two, but a gap the size of 10 between the second and third? The distance between &(x[2][0]) and &(x[2][4]) doesn't seem like half the distance between &(x[0][0])and &(x[2][0]). Thanks in advance.

4 Answers 4

1

When you declare an array of size n, the indices range from 0 to n - 1. So x[2][4] and x[3][0] are actually stepping outside the bounds of your arrays.

If you weren't already aware, the multidimensional array you declared is actually an array of arrays.

Your compiler is laying out each array one after the other in memory. So, in memory, your elements are laid out in this order: x[0][0], x[0][1], x[0][2], x[0][3], x[1][0], x[1][1], and so on.

It looks like you already understand how pointers work, so I'll gloss over that. The reason the last two elements are the same is because x[2][4] is out of bounds, so it's referring to the next slot in memory after the end of the x[2] array. That would be the first element of the x[3] array, if there was one, which would be x[3][0].

Now, since x[3][0] refers to an address that you don't have a variable mapping to, it's entirely possible that dereferencing it could cause a segmentation fault. In the context of your program, there just happens to be something stored at 0x7fff5386fc70; in other words, you got lucky.

Sign up to request clarification or add additional context in comments.

Comments

0

This is due to pointer arithmetic.

Your array is flat, which means that data are stored in a linear way, each one after the other in memory. First [0][0] then [0][1], etc.

The address of [x][y] is calculated as (x*4+y)*float_size+starting_address.

So the gap between the two first [0][0] and [2][0] is 8*float_size. The difference is 20 in hexadecimal, which is 32 in decimal, float_size is then 4.

In between the second and third you have (2*4+4)-(2*4)*float_size which is 16 in decimal, so 10 in hexadecimal. This is exactly half the size of the previous because it is the size of one row (the size of 4 elements in the third row), and the previous is the size of two rows (the size of 8 elements in the first and second rows).

Comments

0

Arrays are linear data structures. Irrespective of their dimension, say 1-dimensional or 2-dimensional or 3-dimensional, they are linearlly arranged.

Your x[3][4] will be stored in memory as consecutive fixed sized cells like :

| (0,0) | (0, 1) | (0,2) | (0,3) | (1,0) | (1,1) | (1,2) | (1,3) | (2,0) | (2,1) | (2,2) | (2,3) |

This x[0][0] notation is matrix notation. On compile time, it is converted to pointer notation. The calculation is like:

x[i][j] = y * i + j  where y in your case is 4.

So on calculating by this way the outputs are perfect.

Comments

0

Array elements in C are stored contiguously, in row-major order. So, in your example, &x[row][column] is exactly equal to &x[0][0]+((row*4)+column))*sizeof(float) (when those addresses are converted to number of bytes, which is what you're outputting).

The third address you're printing has the second index out of bounds (valid values 0 to 3), and the fourth has the first index out of bounds (valid values 0 to 2). It just happens that the values you've chosen work out to the same location in memory, because the rows are laid out in memory end-to-end.

There are 8 elements between &(x[0][0]) and &(x[2][0]). The actual difference in memory is multiplied by sizeof(float) which, for your compiler, is 4. 4*8 is 32 which, when printed as hex, is 0x20, is the difference you're seeing.

If you picked a value of row and column where ((row*4)+column)) was 12(=3*4) or more, your code would be computing the address of something outside the array. Attempting to use such a pointer pointer (e.g. setting the value at that address) would give undefined behaviour. You just got lucky that the indices you picked happen to be within the array.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.