Which of the following C data structures uses more memory? - c

struct {char c; int i;} A[100];
struct {char c[100]; int i[100];} B;
I need to minimize the amount of memory used. Which of these uses less and why?

The second one typically uses less.
The first one, due to alignment constraints, is likely to make an eight byte struct, using 800 bytes total for 100 copies of it; one byte for the char, three bytes for padding, four for the int.
The second one doesn't need padding for alignment (the char array ends at a four byte alignment), and just allocates 100 bytes, then four hundred bytes for a total of 500 bytes of memory used.
This assumes int is four bytes, which is by far the most common case; adjust as needed for weirdo systems.

Related

Why difference between structure variable is always giving 16bytes in 64 bit OS?

#include<stdio.h>
struct std
{
char c;
char e;
};
void main()
{
struct std p,q;
int start,last;
last= &q;
start= &p;
printf("Size:%u %u Address_Diff:%d \n",&p, &q,(last-start) );
}
I am learning structure alignment and padding while we executing above program every time difference between two structure variables showing 16 bytes. I am not understanding why the difference is 16 bytes but i'm expecting the difference is 2 bytes.
some examples:
4077309424 4077309440 diff:16
3600238672 3600238688 diff:16
3272011008 3272011024 diff:16
Generally compiler may pad bytes, to keep each structure variable start position to word or double-word alignment. I guess the choice of alignment position may be architecture and compiler dependent.
It seems your compiler is keeping 16-byte alignment for each structure variable. Sometimes compiler may pad bytes to elements of structure to keep word or double-word alignment. You can check where the bytes padding happening, I mean bytes or padded at element level or structure level.
Do print each element address (as below) and see the difference between them.
printf("Size:%u %u Address_Diff:%d \n",&p.c, &p.e);
If difference is just one byte, it means that bytes are padded at structure level i.e., at the end of structure.

C malloc offsets relative to struct definition locations (and padding)

C question:
Does malloc'ing a struct always result in linear placement from top to bottom of the data inside? As a second minor question: is there a standard on the padding size, or does it vary between 32 and 64 bit machines?
Using this test code:
#include <stdio.h>
#include <stdlib.h>
struct test
{
char a;
/* char pad[3]; // I'm assuming this happens from the compiler */
int b;
};
int main() {
int size;
char* testarray;
struct test* testarraystruct;
size = sizeof(struct test);
testarray = malloc(size * 4);
testarraystruct = (struct test *)testarray;
testarraystruct[1].a = 123;
printf("test.a = %d\n", testarray[size]); // Will this always be test.a?
free(testarray);
return 0;
}
On my machine, size is always 8. Therefore I check testarray[8] to see if it's the second struct's 'char a' field. In this example, my machine returns 123, but this obviously isn't proof it always is.
Does the C compiler have any guarantees that struct's are created in linear order?
I am not claiming the way this is done is safe or the proper way, this is a curiosity question.
Does this change if this is becomes C++?
Better yet, would my memory look like this if it malloc'd to 0x00001000?
0x00001000 char a // First test struct
0x00001001 char pad[0]
0x00001002 char pad[1]
0x00001003 char pad[2]
0x00001004 int b // Next four belong to byte b
0x00001005
0x00001006
0x00001007
0x00001008 char a // Second test struct
0x00001009 char pad[0]
0x0000100a char pad[1]
0x0000100b char pad[2]
0x0000100c int b // Next four belong to byte b
0x0000100d
0x0000100e
0x0000100f
NOTE: This question assumes int's are 32 bits
As far as I know, malloc for struct is not linear placement of data but it's a linear allocation of memory for the members with in the structure that too when you create an object of it.
This is also necessary for padding.
Padding also depends on the type of machine (i.e 32 bit or 64 bit).
The CPU fetches the memory based on whether it is 32 bit or 64 bit.
For 32 bit machine your structure will be:
struct test
{
char a; /* 3 bytes padding done to a */
int b;
};
Here your CPU fetch cycle is 32 bit i.e 4 bytes
So in this case (for this example) the CPU takes two fetch cycles.
To make it more clear in one fetch cycle CPU allocates 4 bytes of memory. So 3 bytes of padding will be done to "char a".
For 64 bit machine your structure will be:
struct test
{
char a;
int b; /* 3 bytes padding done to b */
}
Here the CPU fetch cycle is 8 bytes.
So in this case (for this example) the CPU takes one fetch cycles. So 3 bytes of padding here must be done to "int b".
However you can avoid the padding you can use #pragma pack 1
But this will not be efficient w.r.t time because here CPU fetch cycles will be more (for this example CPU fetch cycles will be 5).
This is tradeoff between CPU fetch cycles and padding.
For many CPU types, it is most efficient to read an N-byte quantity (where N is a power of 2 — 1, 2, 4, 8, sometimes 16) when it is aligned on an N-byte address boundary. Some CPU types will generate a SIGBUS error if you try to read an incorrectly aligned quantity; others will make extra memory accesses as necessary to retrieve an incorrectly aligned quantity. AFAICR, the DEC Alpha (subsequently Compaq and HP) had a mechanism that effectively used a system call to fix up a misaligned memory access, which was fiendishly expensive. You could control whether that was allowed with a program (uac — unaligned access control) which would stop the kernel from aborting the process and would do the necessary double reads.
C compilers are aware of the benefits and costs of accessing misaligned data, and go to lengths to avoid doing so. In particular, they ensure that data within a structure, or an array of structures, is appropriately aligned for fast access unless you hold them to ransom with quasi-standard #pragma directives like #pragma pack(1).
For your sample data structure, for a machine where sizeof(int) == 4 (most 32-bit and 64-bit systems), then there will indeed be 3 bytes of padding after an initial 1 byte char field and before a 4-byte int. If you use short s; after the single character, there would be just 1 byte of padding. Indeed, the following 3 structures are all the same size on many machines:
struct test_1
{
char a;
/* char pad[3]; // I'm assuming this happens from the compiler */
int b;
};
struct test_2
{
char a;
short s;
int b;
};
struct test_3
{
char a;
char c;
short s;
int b;
};
The C standard mandates that the elements of a structure are laid out in the sequence in which they are defined. That is, in struct test_3, the element a comes first, then c, then s, then b. That is, a is at the lowest address (and the standard mandates that there is no padding before the first element), then c is at an address higher than a (but the standard does not mandate that it will be one byte higher), then s is at an address higher than c, and that b is at an address higher than s. Further, the elements cannot overlap. There may be padding after the last element of a structure. For example in struct test_4, on many computers, there will be 7 bytes of padding between a and d, and there will be 7 bytes of padding after b:
struct test_4
{
char a;
double d;
char b;
};
This ensures that every element of an array of struct test_4 will have the d member properly aligned on an 8-byte boundary for optimal access (but at the cost of space; the size of the structure is often 24 bytes).
As noted in the first comment to the question, the layout and alignment of the structure is independent of whether the space is allocated by malloc() or on the stack or in global variables. Note that malloc() does not know what the pointer it returns will be used for. Its job is simply to ensure that no matter what the pointer is used for, there will be no misaligned access. That often means the pointer returned by malloc() will fall on an 8-byte boundary; on some 64-bit systems, the address is always a multiple of 16 bytes. That means that consecutive malloc() calls each allocating 1 byte will seldom produce addresses 1 byte apart.
For your sample code, I believe that standard does require that testdata[size] does equal 123 after the assignment. At the very least, you would be hard-pressed to find a compiler where it is not the case.
For simple structures containing plain old data (POD — simple C data types), C++ provides the same layout as C. If the structure is a class with virtual functions, etc, then the layout rules depend on the compiler. Virtual bases and the dreaded 'diamond of death' multiple inheritance, etc, also make changes to the layout of structures.

behavior of sizeof operator?

#include<stdio.h>
struct krishna {
int i,j,k,l,m;
char c;
double d;
char g[48];
};
int main() {
struct krishna *me={0};
printf("%ld %ld\n",sizeof(me),sizeof(*me));//output is 8 80 how??
return 0;
}
Hello everyone I am new here and the compiler I use is gcc compiler in the above code can anyone explain why
1) pointer irrespective of any type is allocated 8 ?
2) sizeof the above struct is 80 ? Can anyone explain to me in general for any structure how can one determine the structure size , I am getting confused each time I expect one value but getting a different answer and I have also read other questions and answers in stack overflow regarding this and I am still not getting it.Please help.
printf("%ld %ld\n",sizeof(me),sizeof(*me));//output is 8 80 how??
Actually that should be:
printf("%zu %zu\n",sizeof(me),sizeof(*me));//output is 8 80 how??
"%zu" is the correct format string for a size_t value, such as the value you get from sizeof. "%ld" may happen to work on some systems (and apparently it does on yours), but you shouldn't count on that.
If your compiler doesn't support "%zu", you can use "%lu" (which expects an unsigned long argument) and explicitly convert the arguments:
printf("%lu %lu\n", (unsigned long)sizeof(me), (unsigned long)sizeof(*me));
You're getting 8 for sizeof(me) because that happens to be the size of a pointer on the compiler you're using (8 bytes, 64 bits). If you compiled and ran your program on a different system, you might get 4, because a lot of systems have 32-bit pointers. (And this assumes a byte is 8 bits, which is true for most systems but not guaranteed by the language.)
Most compilers make all pointers the same size, but that's not guaranteed by the language either. For example, on a word-addressed machine, an int* pointer could be just a machine-level address, but a char* pointer might need additional information to specify which byte within the word it points to. You're not very likely to run into a system with varying pointer sizes, but there's still no point in assuming that all pointers are the same size.
As for the size of the structure, that also can vary from one compiler to another. Here's your structure again:
struct krishna {
int i,j,k,l,m;
char c;
double d;
char g[48];
};
char is always exactly 1 byte, and char[48] is always exactly 48 bytes.
The number of bytes in an int can vary from one system to another; 4 bytes is most common these days.
The size of a double is typically 8 bytes, but this can also vary (though I don't think I've ever seen a system where sizeof (double) isn't 8 bytes.)
Structure members are laid out in the order in which they're declared, so your i will be at the very beginning of the structure, followed by j, k, and so forth.
Finally, the compiler will often insert padding bytes between members, or after the last member, so that each member is properly aligned. For example, on many systems a 4-byte int needs to be aligned at an offset that's a multiple of 4 bytes; if it's misaligned, access to it may be slow and/or very difficult.
The fact that sizeof (struct krishna) happens to be 80 bytes on your system isn't really all that important. It's more important to understand (a) the general rules compilers use to determine how structures are laid out, and (b) the fact that those rules can result in different layouts for different systems.
The language definition and your compiler guarantee that you can have objects of type struct krishna, and that you can access those objects and their members, getting back whatever values you stored in them. If you need to know how big a struct krishna is, the answer is simply sizeof (struct krishna). If, for some reason, you need to know more details than that (say, if you need to match some externally imposed layout), you can do some experiments and/or consult your compiler's documentation -- but be aware that the specifics will apply only to the compiler you're using on the system where you're using it. (Often an ABI for your system will constrain the compiler's choices.)
You can also use sizeof and offsetof (look it up) to find out where each member is allocated.
All pointers are addresses, and all addresses are the same size on a given system, usually 4 bytes on a 32 bit system and 8 bytes on a 64 bit system. Since you are getting 8, you must be on a 64 bit system.
The size of a struct depends on how the compiler "packs" the individual fields of the struct together into a single block of memory to contain the entire struct. In your case, your struct has 5 int fields (4 bytes each), a single char field (1 byte), a single double field (8 bytes), and a 48 character array. Add all that up and you get 20 + 1 + 8 + 48 = 77 bytes to store your data. The actual size is 80 because the compiler is "padding" the 1 byte char field with 3 extra unused bytes in order to keep all fields in the struct aligned to a 4-byte memory address, which is needed for good performance.
Hope that helps!
This is because:
sizeof( me ) // is a pointer.
... me is a pointer. The size of a pointer is a multiple of the word on your environment, hence it's common that on 32-bit environments a pointer is 4 bytes whereas on a 64-bit environment a pointer is 8 bytes (but not written in stone). If you were to go back a couple years, a 16-bit environment would have a 2 byte pointer. Looking at the next sizeof:
sizeof( *me ) // is a struct krishna, hence 80 bytes are needed to store it in memory.
... is a structure and the size of the structure krishna is 80 bytes. If you look at the structure:
struct krishna {
int i,j,k,l,m; // sizeof( int ) * 5
char c; // sizeof( char ) * 1
double d; // sizeof( double ) * 1
char g[48]; // sizeof( char ) * 48
// padding for memory address offset would be here.
};
... if you add up the amount of bytes required for each field and include the appropriate data structure alignment for the memory address offset then it will total 80 bytes (as expected). The reason it adds an extra 3 unused bytes is because to store a structure in memory it must be in a continuous block of memory that is allocated for the structure. For performance reasons, it will pad any size issues to ensure that the memory addresses are always a multiple of the word. The tradeoff of the 3 bytes for performance improvements is worth it, 3 bytes nowadays is not as impactful as the performance improvements the processor has when data alignment is guaranteed.
Just to add to answers of #Jacob Pollack and #ObjetDart, you can find more about structure padding at Structure padding in C.

how to perform data structure alignment with kmalloc?

I have been reading data structure alignment articles but I'm getting nowhere. Perhaps things are just too complicated for me to understand. I also came across data structure padding which is also necessary to align data. How do I add a data structure padding to struct usb_ep? Also how do I make sure that whenever I perform kmalloc the data to be read should be at a memory offset which is some multiple of 4?
Regarding alignment, kmalloc will align the structures properly. If you have an 4byte variable, it will be 4bytes aligned, if you have an 8byte vaiable, it will be 8bytes aligned. Understanding alignment is the reason why padding is needed.
What you dont want to get is garbade padding between the variables in your struct. You can do that with the pragma pack directive (probably easiest) or by adding the padding manually.
Example
struct usb_ep
{
short a; /* 2 bytes*/
int b; /* 4 bytes*/
short c; /* 2 bytes*/
};
The size of all the elements is 8bytes, but due to alignment requirements, the size will be 12bytes. Memory layout would be like this:
short a - 2 bytes
char pad[2] - 2 bytes of padding
int b - 4 bytes
short c - 2 bytes
char pad[2] - 2 bytes of padding
In order to not get any padding, or increasing the size of the struct, you can rearrange elements in order to satisfy the alignment requirements.
That is having a struct:
struct usb_ep
{
short a; /* 2 bytes*/
short c; /* 2 bytes*/
int b; /* 4 bytes*/
};
Will have the size of 8bytes, and no requirement for adding padding.
This comes from http://minirighi.sourceforge.net/html/kmalloc_8c.html
void * kmemalign (size_t alignment, size_t size)
Allocate some memory aligned to a boundary.
Parameters:
alignment The boundary.
size The size you want to allocate.
Exceptions:
NULL Out-of-memory.
Returns:
A pointer to a memory area aligned to the boundary. The pointer is a aligned_mem_block_t pointer, so if you want to access to the data area of this pointer you must specify the p->start filed.
Note:
Use kfree(void *ptr) to free the allocated block.
The best way to pad fields in a structure is to declare your variables in descending size. So your largest ones first, then down to the smallest.
struct example {
double amount;
char *name;
int cnt;
char is_valid;
};
This doesn't always end up with logically connected items in the structure, but will typically give the most compact and easily accessible memory usage.
You can use use padding bytes in your struct declarations, but they clutter up the code, and do not guarantee compact structures. A compiler may align every byte on a 4 byte boundary, so you might end up with
struct example2 {
char a;
char padding1[3];
char b;
char padding2[3];
};
taking 4 bytes for a, 4 bytes for padding1, 4 bytes for b, and 4 bytes for padding2. Some compilers allow you to specify packed structures which would yield the correct result in this case. Usually I just declare the fields from largest to smallest types and leave it at that. If you need to share memory between two langages/compilers, then you need to make sure the structs align identically in memory.

Questions about C bitfields

Is bitfield a C concept or C++?
Can it be used only within a structure? What are the other places we can use them?
AFAIK, bitfields are special structure variables that occupy the memory only for specified no. of bits. It is useful in saving memory and nothing else. Am I correct?
I coded a small program to understand the usage of bitfields - But, I think it is not working as expected. I expect the size of the below structure to be 1+4+2 = 7 bytes (considering the size of unsigned int is 4 bytes on my machine), But to my surprise it turns out to be 12 bytes (4+4+4). Can anyone let me know why?
#include <stdio.h>
struct s{
unsigned int a:1;
unsigned int b;
unsigned int c:2;
};
int main()
{
printf("sizeof struct s = %d bytes \n",sizeof(struct s));
return 0;
}
OUTPUT:
sizeof struct s = 12 bytes
Because a and c are not contiguous, they each reserve a full int's worth of memory space. If you move a and c together, the size of the struct becomes 8 bytes.
Moreover, you are telling the compiler that you want a to occupy only 1 bit, not 1 byte. So even though a and c next to each other should occupy only 3 bits total (still under a single byte), the combination of a and c still become word-aligned in memory on your 32-bit machine, hence occupying a full 4 bytes in addition to the int b.
Similarly, you would find that
struct s{
unsigned int b;
short s1;
short s2;
};
occupies 8 bytes, while
struct s{
short s1;
unsigned int b;
short s2;
};
occupies 12 bytes because in the latter case, the two shorts each sit in their own 32-bit alignment.
1) They originated in C, but are part of C++ too, unfortunately.
2) Yes, or within a class in C++.
3) As well as saving memory, they can be used for some forms of bit twiddling. However, both memory saving and twiddling are inherently implementation dependent - if you want to write portable software, avoid bit fields.
Its C.
Your comiler has rounded the memory allocation to 12 bytes for alignment purposes. Most computer memory syubsystems can't handle byte addressing.
Your program is working exactly as I'd expect. The compiler allocates adjacent bitfields into the same memory word, but yours are separated by a non-bitfield.
Move the bitfields next to each other and you'll probably get 8, which is the size of two ints on your machine. The bitfields would be packed into one int. This is compiler specific, however.
Bitfields are useful for saving space, but not much else.
Bitfields are widely used in firmware to map different fields in registers. This save a lot of manual bitwise operations which would have been necessary to read / write fields without it.
One disadvantage is you can't take address of bitfields.

Resources