The output of this program is 28. I don't understand how?
According to me this should be 32(4+4+4+4+12)+4(to maintain the alignment)=32.
Please explain the reason for displaying the output 28??
struct test{
char c;
int d;
int x;
int y;
long double p;
}t1;
printf("%d",sizeof(t1));
Maybe your "long double" is actually the same as a double (8 bytes), and if you're on a 32bit processor the alignment is 4-byte.
4+4+4+4+8 = 24
What is sizeof(long double)?
EDIT:
I used GCC's __builtin_offset_of() and __alignof__ to investigate. The actual answer that explains the size of the struct is:
4+4+4+4+12 = 28
sizeof(long double) is 12.
No padding is necessary because __alignof__(long double) is 4 and. Interestingly, __alignof__(double) is 8.
According to this, long doubles in gcc 32-bit mode (using gcc -m32 or with a gcc that was built to produce 32-bit output, regardless of what your platform actually is) are only 4-byte aligned. Might be good to consult the gcc manual to verify that, though.
On a 64 bit system sizes are
char - 1 byte(its not 4 bytes)
int - 4 bytes
long double - 12 bytes
so total is 1+4+4+4+12+padding = 28 bytes!!
That seems right to me. A field immediately following p would be 4-byte aligned, so there's no need for padding at the end of the structure.
4+4+4+4+12=28
On my system, the output is 32, but on my system, sizeof(long double) is 16. (x86_64, LLVM3).
The 28 sizeof output is of course correct = 1 byte for char, 3 bytes padding, 3 x 4 int and 12 bytes for long double (96 bits size but 80 bit precision), which makes in total 28 bytes.
Remember that even tho you compile on x86-64 machine, you probably compile for x86-32 machine using mingw32 and that makes a difference.
Mingw32 uses 4 byte allignement for long double.
Related
I have following code snippet.
#include<stdio.h>
int main(){
typedef struct{
int a;
int b;
int c;
char ch1;
int d;
} str;
printf("Size: %d \n",sizeof(str));
return 0;
}
Which is giving output as follows
Size: 20
I know that size of the structure is greater than the summation of the sizes of components of the structure because of padding added to satisfy memeory alignment constraints.
I want to know how it is decided that how many bytes of padding have to be added. On what does it depend ? Does it depends on CPU architecture ? And does it depends on compiler also ? I am using here 64bit CPU and gcc compiler. How will the output change if these parameters change.
I know there are similar questions on StackOverflow, but they do not explain this memory alignment constraints thoroughly.
It in general depends on the requirements of the architecture. There's loads over here, but it can be summarized as follows:
Storage for the basic C datatypes on an x86 or ARM processor doesn’t
normally start at arbitrary byte addresses in memory. Rather, each
type except char has an alignment requirement; chars can start on any
byte address, but 2-byte shorts must start on an even address, 4-byte
ints or floats must start on an address divisible by 4, and 8-byte
longs or doubles must start on an address divisible by 8. Signed or
unsigned makes no difference.
In your case the following is probably taking place: sizeof(str) = 4 (4 bytes for int) + 4 (4 bytes for int) + 1 ( 1 byte for char) + 7 (3 bytes padding + 4 bytes for int) = 20
The padding is there so that int is at an address that's a multiple of 4 bytes. This requirement comes from the fact that int is 4 bytes long (my assumption regarding the architecture you're using). But this will vary from one architecture to another.
On what does it depend ? Does it depends on CPU architecture ? And does it depends on compiler also ?
CPU, operating system, and compiler at least.
I know that it depends on the CPU architecture, I think you can find some interesting articles that talks about this on the net, wikipedia is not bad in my opinion.
For me I am using a 64 bit linux machine, and what I can say is that, every field is aligned so that it would be on a memory address divisible by its size (for basic types), for example :
int and float are aligned by 4 (must be in a memory adress divisible by 4)
char and bool by 1 ( which means no padding)
double and pointers are aligned by 8
Best way to avoid padding is to put your fields from largest size to smallest (when there is only basic fields)
When there is composed fields, it a little more difficult for me to explain here, but I think you can figure it out yourself in a paper
Code 1:-
struct emp
{
char a;
double b;
};
int main()
{
struct emp e;
printf("%p %p", (void*)&e.a, (void*)&e.b);
}
Output on my computer:-
OO28FF00 0028FF08
As the size of char and double is '1' and '8' respectively and hence the 0028FF00 and 0028FF08 are multiples of '1' and '8' respectively.
Code 2:-
struct emp
{
char a;
long double b;
};
int main()
{
struct emp e;
printf("%p %p \n", (void*)&e.a,(void*)&e.b);
}
The output is :-
0028FF00 0028FF04
As the size of char and long double is '1' and '12' respectively but 0028FF04 is not a multiple of '12'.
Why padding is not applied in this case?
A long double is an 80 bit floating point so you need 10 bytes. 10 is really not a very good size though, thus Intel 32 bit processors decided on 12 bytes. 12 is a multiple of 4 which represents 32 bits (3 x 32 bits). This is considered aligned because a 32 bit processor only needs 4 bytes alignment, so the 12 bytes is aligned at any 4 bytes boundary. Obviously, the compiler knows what it's doing and it always tries to generate the smallest possible structure.
This being said, this is where you see that you cannot use a struct declaration and hope to save it as is in a file... at least not with the default C types (you can use int32_t, uint64_t, etc. to get exactly what you want, but there is no equivalent for floating point numbers...)
As someone commented, on a 64 bit architecture, long double is 16 bytes. A waste of 6 bytes... but it makes the type 64 bit aligned all the time.
Wikipedia has a table of typical alignments:
http://en.wikipedia.org/wiki/Data_structure_alignment#Typical_alignment_of_C_structs_on_x86
x86 has flexible memory access instructions, so there rules are up to the compiler designers' decision. We can only imagine why they thought there are the most reasonable.
I found #LưuVĩnhPhúc 's comment very educative. Although long double is 12 bytes on your platform (GCC?) it was 4 bytes aligned by the same reason why a 512 bytes struct will not be 512 bytes aligned; there will be too much waste in space. I guess the designers of GCC thought accessing double variables should be done in the least possible latency at the cost of some space (up to 7 bytes.)
Well, as far as I know padding and data alignment heavily depend on the target architecture, compiler optimization options and overall quality of the optimizator. Thus if you don't specifically care about alignment, you get a "quazi-optimal" structures and the compiler is free to decide what is better for this particular set of optimization options (whether -Os or -O is used and so on). If you wish to have a specific alignment, you should use compiler-specific options to tune the things. For GCC and CLang use __packed__ attribute, for MSVC use #pragma pack. See pragma pack(1) nor __attribute__ ((aligned (1))) works for more info
struct tag_t_ {
u_int8_t op;
u_int8_t num;
u_int32_t labels[5];
};
In the above structure where will be pad bytes added by 64-bit compiler?
Is it before the first label or at the end of first label?
If the padding is at end of the first label, Will it cause any erroneous result while accessing (reading) the first label in 32 bit archs?
I'm running this in 64-bit system -- the memory map of the struct is
offset: variable
0: op num
2: 00 00 // only 2 paddings
4: label0
8: label1
...
20: label5
sizeof(struct) == 24
// here one could fit an unsigned short between the chars and the first 32-bit integer without affecting the size of the struct.
The rule for struct padding is that any basic variable of width W, will be aligned to that width. Double as second parameter would cause 7 padding bytes after op and only 3 padding bytes after num, as labels[0] would then start at an offset divisible by 4.
There's a difference between 32/64 bit systems: 32-bit systems will still align 8-byte variables to 32-bit boundaries. 64-bit systems will align long int and double to 8-byte boundaries.
This would make it safe to use that struct in 32-bit system. If there were doubles in the struct, one could still make the structs compatible with careful planning of the variables.
It depends on the compiler, there's no universal rule that can be applied and guaranteed to hold.
I'm not sure about the second half of the question, since on the 32-bit architecture the compiler will be different, of course. It's never a good idea to transfer structures directly.
Because of the padding, if you write sizeof (tag_t_) bytes to some external media on the 64-bit machine, transfer the media and and then try to read sizeof (tag_t_) on the 32-bit machine, it will fail. So don't do that. Serialize structures field-by-field, and de-serialize them the same way.
padding is usually applied at the end of each field. And no, a 64bit compiled binary is incompatible with a 32bit binary. So you might have to re-compile everything for 32 bit architecture.
The alignment then will be taken care of, by the 32 bit compiler and addresses will be generated accordingly.
The title is actually a bit misleading, but I wanted to keep it short. I've read about why I should use size_t and I often found statements like this:
size_t is guaranteed to be able to express the maximum size of any object, including any array
I don't really understand what that means. Is there some kind of cap on how much memory you can allocate at once and size_t is guaranteed to be large enough to count every byte in that memory block?
Follow-up question:
What determines how much memory can be allocated?
Let's say the biggest object your compiler/platform can have is 4 gb. size_t then is 32 bit. Now let's say you recompile your program on a 64 bit platform able to support objects of size 2^43 - 1. size_t will be at least 43 bit long (but normally it will be 64 bit at this point). The point is that you only have to recompile the program. You don't have to change all your ints to long (if int is 32 bit and long is 64 bit) or from int32_t to int64_t.
(if you are asking yourself why 43 bit, let's say that Windows Server 2008 R2 64bit doesn't support objects of size 2^63 nor objects of size 2^62... It supports 8 TB of addressable space... So 43 bit!)
Many programs written for Windows considered a pointer to be as much big as a DWORD (a 32 bit unsigned integer). These programs can't be recompiled on 64 bit without rewriting large swats of code. Had they used DWORD_PTR (an unsigned value guaranteed to be as much big as necessary to contain a pointer) they wouldn't have had this problem.
The size_t "point" is the similar. but different!
size_t isn't guaranteed to be able to contain a pointer!!
(the DWORD_PTR of Microsoft Windows is)
This, in general, is illegal:
void *p = ...
size_t p2 = (size_t)p;
For example, on the old DOS "platform", the maximum size of an object was 64k, so size_t needed to be 16 bit BUT a far pointer needed to be at least 20 bit, because the 8086 had a memory space of 1 mb (in the end a far pointer was 16 + 16 bit, because the memory of an 8086 was segmented)
Basically it means that size_t, is guaranteed to be large enough to index any array and get the size of any data type.
It is preferred over using just int, because the size of int and other integer types can be smaller than what can be indexed. For example int is usually 32-bits long which is not enough to index large arrays on 64-bit machines. (This is actually a very common problem when porting programs to 64-bit.)
That is exactly the reason.
The maximum size of any object in a given programming language is determined by a combination of the OS, the CPU architecture and the compiler/linker in use.
size_t is defined to be big enough to hold the size value of the largest possible object.
This usually means that size_t is typedef'ed to be the same as the largest int type available.
So on a 32 bit environment it would typically be 4 bytes and in a 64 bit system 8 bytes.
size_t is defined for the platform that you are compiling for. Hence it can represent the maximum for that platform.
size_t is the return of the sizeof operator (see 7.17 c99) therefore it must describe the largest possible object the system can represent.
Have a look at
http://en.wikipedia.org/wiki/Size_t
Are pointers on a 64-bit system still 4 byte aligned (similar to a double on a 32 bit system)? Or are they note 8 byte aligned?
For example, on a 64-bit system how big is the following data structure:
struct a {
void* ptr;
char myChar;
}
Would the pointer by 8 byte aligned, causing 7 bytes of padding for the character (total = 8 + 8 = 16)? Or would the pointer be 4 byte aligned (4 bytes + 4 bytes) causing 3 bytes of padding (total = 4 + 4 + 4 = 12)?
Thanks,
Ryan
Data alignment and packing are implementation specific, and can be usually changed from compiler settings (or even with pragmas).
However assuming you're using default settings, on most (if not all) compilers the structure should end up being 16 bytes total. The reason is because computers reads a data chunk with size of its native word size (which is 8 bytes in 64-bit system). If it were to pad it to 4 byte offsets, the next structure would not be properly padded to 64-bit boundary. For example in case of a arr[2], the second element of the array would start at 12-byte offset, which isn't at the native byte boundary of the machine.
I don't think you can rely on any hard-and-fast rules. I think it's a function of the compiler you use and the compilation options you choose.
Your best bet is to write a program that tests this and spits out a header file that codifies the alignment rules as #defines. You might also be able to just calculate what you're interested in right in the macros, too.
Generally on a 64-bit system:
struct a {
void* ptr; // size is 8 bytes, alignment is 8
char myChar; // size is 1 byte, alignment is 1
// padding of 7 bytes so array elements will be properly aligned
}
For a total size of 16 bytes.
But this is all implementation defined - I'm just giving an example that likely to be true for many (most?) 64-bit systems.
You would need to consult the documentation for the particular ABI you are interested in. For example, here is the System V ABI x86-64 architeture supplement - you can see on page 12 that pointers on this ABI are 8-byte aligned (so yes, the structure you show would be padded out to 16 bytes).
The language standard makes no statements about padding. The alignment rules are platform-specific (i.e., you have to align differently on e.g. a PowerPC CPU than on a x86_64 CPU), and they are implementation-defined, meaning your compiler can do whatever works (and might change that behaviour with different command-line options or after a version update).
I strongly believe that any recommendation along the lines of "this is usually this or that" is misleading, and possibly dangerous.
You could write a test program that executes a couple of sizeof() and/or offsetof()statements and writes a header for you containing some #defines stating the paddings used.
You can use autoconf to do that for you.
In the very least, you should add assert( sizeof( ... ) ) statements at the beginning of your main() function so you get informed when your assumptions are wrong.