Reputation: 1998
I read that functions in C may use local stack-based variables, and they are allocated simply by decrementing the stack pointer by the amount of space required. This is always done in four-byte chunks (if I am not mistaken). But, what if run code like following:
void foo(void)
{
char str[6];
......
}
What size does var str
occupy? 6
bytes or 6 × 4
bytes as per the four-byte chunks.
Upvotes: 4
Views: 435
Reputation: 8195
If you have:
char str[6];
int a;
char b;
char c;
The stack will be of sufficient size to contain all these variables and be divisible by 4 (or whatever alignment is required). But each variable does not need to be aligned on the same boundary (though there may be hardware requirements).
On my system, compiling the above and printing out the addresses of the stack variables (leading digits removed for brevity):
&str -- 18
&a -- 12
&b -- 10
&c -- 11
i.e the compiler will arrange for the stack to be aligned, but the variables do not need to be padded.
Upvotes: 0
Reputation: 5533
Data alignment is a CPU requirement which means that the alignment amount changes from a CPU to another, keep that in mind.
Speaking about stack data-alignment, gcc
for example keeps the data aligned using an option called -mpreferred-stack-boundary=n
where the data will be aligned to 2^n
.
By default, the value of n
is 4 which makes the stack-alignment 16-bytes.
What this means is that you'll find yourself allocating 16 bytes in stack memory although what you explictly allocated was just an integer.
int main()
{
char ar[6] = {1,2,3,4,5,6};
int x = 10;
int y = 12 + (int) ar[1] + x;
return y;
}
Compiling this code with gcc on my CPU produces the following assembly(posting only the stack-allocation instruction):
subl $32, %esp
But why 32? we're allocating data that fits exactly in 16 bytes.
Well, there are 8 bytes gcc needs to keep saved for the leave
and ret
which makes the total needed memory 24.
BUT, the alignment requirement is 16-bytes and thus gcc needs to allocate stack-space so that it's made up of 16-bytes chunks; making that 24 bytes to 32 solves the problem.
You'll have enough space for your variables, for the ret
and leave
and it's made of two 16-bytes chunks.
Upvotes: 2
Reputation: 23699
I guess you are getting confused between data size and data alignment. There is no general rule, but, on modern computers, your variable will be stored in 6 bytes. On the other side, the next element won't necessarily be stored at the next byte. This is known as data structure padding.
The word-aligned architectures, where every variable must begin on an address which is a multiple of the word size, are becoming rare. With new processors such as SPARC or x86, variables are self-aligned. It means that they have to begin on an address which is a multiple of its type size.
Therefore, there is no "four-bytes chuck rule" on non-exotic computers. In your example, str
will be stored with 6 bytes. If you declare a variable with an alignment of 8 bytes for instance (such as double
on x86), there will be 2 padding bytes inserted by your compiler.
Alignment is fixed by the compiler, according to your architecture. So the standard doesn't define anything about it. You may find further informations on Wikipedia.
Upvotes: 0
Reputation: 5163
The rule of allocating in 4-byte chunks is not valid in all cases. For example, ARM eabi requires aligment of 64-bit integers and doubles on 8-byte boundaries.
Usually the allocated space matches the rules of data packing into structures. So char[6]
would actually take 6 bytes (usually), but the padding of the data (for the next field) can use few bytes more.
Example:
struct X
{
char field1[6];
};
So the structure X size would be 8
structure Y
{
char field1[2];
double field2;
};
Structure Y is usually something like 8
, 12
or 16
bytes depending on architecture.
Same rules are applied to automatic stack variables: usually the padding is dictated not by type you are using, but by the next type you are going to use. And rules sometimes are a bit vague.
Upvotes: 0
Reputation: 531175
The four-byte-chunk rule just means that the stack pointer must point to an address that is a multiple of four. In this case, allocating 8 bytes satisfies that rule, and such a block is large enough to hold a 6-character array with only 2 bytes of padding.
Upvotes: 2