2

If I have for example

typedef struct node
{
    int numbers[5];
} node;

Whenever I create an instance of such a struct there's gonna be allocation of memory in the stack for the array itself, (in our case 20 bytes for 5 ints(considering ints as 32 bits)), and numbers is gonna be a pointer to the first byte of that buffer. So, I thought that since inside an instance of node, there's gonna be a 20 bytes buffer(for the 5 ints) and a 4 bytes pointer(numbers), sizeof(node) should be 24 bytes. But when I actually print it out is says 20 bytes.
Why is this happening? Why is the pointer to the array not taken into account?
I shall be very grateful for any response.

dandan78
  • 13,328
  • 13
  • 64
  • 78
Root149
  • 389
  • 1
  • 3
  • 11
  • 3
    There is no pointer, just an array. – 2501 Dec 23 '14 at 08:51
  • 3
    You are confused with pointers and arrays, there is no pointer involved here. – ouah Dec 23 '14 at 08:52
  • Are not arrays just an illusion? I thought arrays do not exist in C, but just chunks of memory and pointers to those chunks, creating an illusion of an array – Root149 Dec 23 '14 at 08:53
  • The `sizeof (node)` means the sizeof the collection of variables inside the struct. You have but an array. Also, your arrangement of variables inside the node can also dictate what the resulting size is. (as padding will be applied) By choosing different ordering within the scruct, you can change the padding required. – David C. Rankin Dec 23 '14 at 08:55
  • Arrays decay silently to constant pointers, it does not mean they are pointers and do not take in memory space – Vality Dec 23 '14 at 08:56
  • So, is numbers then a name for the first of those ints? Or how are we to consider it? – Root149 Dec 23 '14 at 09:04
  • 1
    @Root149 `numbers` is just a label, it doesn't occupy any memory. – 2501 Dec 23 '14 at 09:05
  • 1
    Not an exact duplicate, but I wrote about arrays and pointers here: http://stackoverflow.com/questions/1641957/is-array-name-a-pointer-in-c/1641963#1641963 – Thomas Padron-McCarthy Dec 23 '14 at 09:10
  • @2501: "*`numbers` is just a label*" What? `numbers` is 5 `int`s and with this (on the OP's platform) 20 bytes! – alk Dec 23 '14 at 09:12
  • 1
    @alk: I assume he means that yes, numbers is an array that occupies 20 bytes of memory, but the _name_ numbers is just a label for that place in memory, not a pointer to it or something else that requires its own memory when the program is executed. – Thomas Padron-McCarthy Dec 23 '14 at 09:16
  • @ThomasPadron-McCarthy Yep. I should have said *identifier* instead of *label* to not confuse them with C goto/switch labels. – 2501 Dec 23 '14 at 09:20
  • Related: http://stackoverflow.com/q/2528318/694576 – alk Dec 23 '14 at 09:21

5 Answers5

4

Arrays are not pointers:


  • int arr[10]:

    • Amount of memory used is sizeof(int)*10 bytes

    • The values of arr and &arr are necessarily identical

    • arr points to a valid memory address, but cannot be set to point to another memory address


  • int* ptr = malloc(sizeof(int)*10):

    • Amount of memory used is sizeof(int*) + sizeof(int)*10 bytes

    • The values of ptr and &ptr are not necessarily identical (in fact, they are mostly different)

    • ptr can be set to point to both valid and invalid memory addresses, as many times as you will

barak manos
  • 29,648
  • 10
  • 62
  • 114
  • But how is arr seen in memory, I mean how the compiler interprets it? Y'all saying it's not a pointer and then you say it 'points' to a valid memory address. But then how can something which takes no space point to something? What I wanna now how is it exactly interpreted by the compiler? Just a name of the first of those ints or what? – Root149 Dec 23 '14 at 09:20
  • @Root149: It's a constant label, which can be resolved into an address during compilation. So the compiler replaces every reference to it (read access or write access) with a constant value - the offset of the array from the beginning of the current stack depth (in the case of a local array) or the absolute virtual address (in the case of a global array). – barak manos Dec 23 '14 at 09:23
  • @Root149: Draw the computer's memory on a piece of paper. Mark the 20 bytes that the array occupies within that memory. Then, _beside_ the memory, you write the label "numbers:". – Thomas Padron-McCarthy Dec 23 '14 at 09:39
  • So we can think of it as follows: when we do something like int arr[10]; we are creating a chunk of memory of size 40 bytes inside the stack frame of the particular function in which we do this, and since its local, it's enough to give it a name, which the compiler will now refer to the first byte of those 40 bytes( I mean arr refers to the first byte of the 40 allocated). But when we do malloc(sizeof(int)*10) we are allocating memory in the heap, and we cannot directly access it from the stuck frame, thus we need a pointer in the stuck frame which'll allow us to access it, or am I wrong? – Root149 Dec 23 '14 at 10:04
  • That's not exactly the point. You can also have a pointer pointing to a variable in the stack. For example, by declaring `int i` and then `int* p = &i`. – barak manos Dec 23 '14 at 10:09
  • I mean stack, a speller can get annoying some times – Root149 Dec 23 '14 at 10:10
  • Yea , of course we can, but since it's something local, there's no need for one, since we can just give a name to the first byte of those allocated, am I right? – Root149 Dec 23 '14 at 10:11
  • "There's no need for one" is definitely not right. Have you never passed the address of a local variable in one function to another function? – barak manos Dec 23 '14 at 10:14
  • You're not fully understanding what I mean, I mean that if we want to create a local array, the compiler allows us to do that without needing to create a direct pointer to it, since it can just give a name to the first byte of the allocate memory, and we can locally refer to it. And of course if you need to have a pointer to it you can do that! – Root149 Dec 23 '14 at 10:17
  • You're right. I don't understand "it can just give a name of the first byte of the allocate memory". – barak manos Dec 23 '14 at 10:22
  • What I mean is that, arr is interpreted as a local reference to the first byte of those allocated(like an alias to the address of the first byte), and so we don't have to create a pointer to access the array(locally) And indeed when we pass arr in another function as argument, we're just passing the address of he first byte of the array, thus allowing the function to which we pass it to create a pointer which'll have that adress, and thus point to our array. – Root149 Dec 23 '14 at 10:27
3

There is no pointer, just an array. Therefore the struct is of size sizeof( int[5] ) ( plus possible padding ).

The struct node and its member numbersshare the address. If you have a variable of type node or a pointer to that variable, you can access its member.

2501
  • 25,460
  • 4
  • 47
  • 87
1

When you have a variable such as int x; space is set aside for the value. Whenever the identifier x is used, the compiler generates code to access the data in that space in the appropriate manner... there's no need to store a pointer to it to do this (and if there were, wouldn't you need a pointer to that pointer? And a pointer to that? etc.).

When you have an array like int arr[5];, space is set aside the same way, but for 5 ints. When the identifier arr is used, the compiler generates code to access either the relevant array element or give the address of the array (depending on how it's used). The array is not a pointer, and doesn't contain one... but the compiler may use its address instead of its contents in some situations.

An array is said to decay to a pointer to its first element in many situations, but that just means that in those situations the identifier will give its address instead of its contents, much like when you use the address-of operator with a non-array variable. The fact that you can get the address of the int x with &x doesn't mean x contains the address of an int... just that the compiler knows how to figure it out.

Dmitri
  • 9,175
  • 2
  • 27
  • 34
0

Arrays don't work like that. They only allocate space for their elements, but not for a pointer. The "pointer" you are talking about (numbers) is just a placeholder for the address of the array's first element; think of it as a literal, instead of a variable. Therefore, you can not assign a value to it.

int myint;
numbers = &myint;

This won't work, since there is no memory where you could store &myint. numbers will just be converted to an address at compile time.

Philipp Murry
  • 1,660
  • 9
  • 13
  • So it's just a name for the first 4 bytes of the buffer? – Root149 Dec 23 '14 at 09:07
  • 1
    @Root149 The important fact is that `numbers` is most definitely not a pointer. I don't think this answer makes that clear enough. – juanchopanza Dec 23 '14 at 09:10
  • I'm asking indeed, when we allocate memory for 5 ints is such a way, will numbers be just the name of the first of those ints(a name for the first 4 bytes 'box')? – Root149 Dec 23 '14 at 09:14
  • @Root149: No, numbers is not a name for the first element in the array. numbers is the name of the entire array. Also, numbers is not a pointer, but in many cases when you use it in your program it will be _converted_ to a pointer to the first element. That can make it seem like it is a pointer to, or name for, the first element. – Thomas Padron-McCarthy Dec 23 '14 at 09:23
  • @Root149: I got my head wrapped around this concept when I started to think of array names as address literals. So `numbers` stands for an address (the address of the first element), but it doesn't have any place in memory. This is the practical implication when you use the symbol `numbers` in your code, and this is why it behaves like a pointer (such as 7 would behave like an `int`, but you cannot do `7 = some_int;`). – Philipp Murry Dec 23 '14 at 09:27
  • Thomas, but since the entire array is made up of 5 ints(20 bytes) and numbers is a name for the entire chunk of memory, is then numbers similar to a struct which is made up of 5 ints? Like struct n{ int i; int b; int c; int d; int e;} ? – Root149 Dec 23 '14 at 09:33
  • @Root149: They are a bit similar. sizeof will give 20 for both. But there are differences too, for example that you can have struct n n1, n2; and then do n1 = n2; – Thomas Padron-McCarthy Dec 23 '14 at 09:36
  • @Root149 Another difference is that an implementation may place padding between the elements of a struct, but not between the elements of an array. – juanchopanza Dec 23 '14 at 09:43
  • It's a bit confusing for me right now, considering numbers as a name for a chunk of memory and then be able to do stuff like *(numbers + 5), ie accessing elements beyond the array. – Root149 Dec 23 '14 at 09:47
0

Size of structure is always defined by the size of its members. So its really doesn't matter whether members are simply int, char, float or arrary or even structure itself.

dcds
  • 437
  • 2
  • 9
  • 20