Size of struct that contains two pointers - c

What is the size of this struct? (32 bit system calculation. Not 64 bit.)
struct list_element
{
short data;
struct list_element* next;
struct list_element* prev;
};
I have tried calculating the size with these formulas:
(sizeof(list_element*) + sizeof(short)) + ((sizeof(list_element*) * 2)
(4 + 2) + (4 * 2) = 6 + 8 = 14
(sizeof(short)) + (sizeof(list_element*) * 2)
2 + (4 * 2) = 2 + 8 = 10
(sizeof(list_element*) + sizeof(list_element*) + sizeof(short)) + (sizeof(list_element*) * 2)
(4 + 4 + 2) + (4 * 2) = 10 + 8 = 18
(sizeof(list_element*) + sizeof(list_element*) + sizeof(short))
(4 + 4 + 2) = 10
However, they do not return the correct answer. What formula do you use to calculate the size of this struct?
Update:
My teacher says we a re ignoring data alignment... Hopefully that does not throw anyone off too much since you are used handling data alignment with your code and structs...
Update 2
Thank you for the help and the introduction to data alignment.
The answer was 10 without data alignment... Not sure why I am in such a rush to work with data alignment in C... Is it fun?
Also, the answer with data alignment is 12. As you guys explained, you have to data align the short to match the integers. Therefore, you have (2 + (2 additional bytes)) + 4 + 4 = 12.

The size of the struct is given by:
size_t size = sizeof(struct list_element);
The fact that you have two members that are pointers to the struct just means
you are adding the size of a pointer, twice. On a 32 bit build, sizeof would resolve to an additional 4 bytes per pointer, on a 64 bit build, it would result in an additional 8 bytes per pointer.
Another thing to be aware of is that the size of your struct is likely not simply the sum of the sizeof's of the individual members, as storage in a struct is often padded for alignment purposes. So, between your short, and the next member, the padding will result in additional size.
The reason I used the word likely is that if a pragma pack directive was used in your source, the packing alignment could be changed, resulting in a different value for sizeof.
Two good discussions on struct alignment padding: A general discussion here, and How to reduce memory footprint here. The second link is particularly interesting as it deals with structure alignment, padding and bit fields, and how each can affect memory usage.

Although your teacher asked to ignore data alignment, the size of that struct is 10 bytes assuming short being 2 bytes.. but actually the short size is not fixed, but at least 2 bytes!
Give a look here. Did you correctly reported the teacher question?

This will return the size of the struct:
sizeof(struct list_element);

Related

Does pragmapack() in C programming have any usage apart from structure packing?

While I'm on an interview the interviewer asked me are there any other usage of pragmapack() in C apart from structure packing? So I answered that I don't know apart from structure packing. So are there any other usage of it?
#pragma pack(size)
is a preprocessor directive used for altering structure padding schemes. Usually a structure adds padding bytes between it's members to speed up the memory fetch operations.
the number of padding bytes it used is depends on machine architecture.
for example,
struct sample {
int a;
char b;
int c;
};
When we see the above structure it requires only 9 bytes ( 4 + 1 + 4) to hold members a, b and c, but for a 32 bit architecture, a variable of this structure takes 16 bytes (4 + 4 + 4) of memory. even though char b only requires 1 byte, it takes 4 bytes 1 for storing value of b and other three as padding bytes.
padding_size = (word_size of machine architecture > highest sized structure member datatype's size) ? highest sized structure member datatype's size : word_size of machine architecture;
we can forcefully assign padding size using preprocessor directive #pragma pack(size) , size should be a power of 2 less than the word_size of machine architecture.
If we use like
#pragma pack(1)
for the above structure then the total amount of memory required for holding a variable of type struct sample will be (4 + 1 + 4) 9 bytes.

adjusting memory alignment in a struct

I am aware of the memory alignment in structure but I am stumped at this implementation I came across in a project I am working on.
struct default {
uint8_t variable[((sizeof(struct dummyStructure) + 3) /4)*4] // Align on 32 bit boundary
}
It is more like a black box testing for me at the moment because I dont have access to the functions, but can anyone explain the math used here to cause this alignment to happen.
The answer to your question is that, by adding 3 to the size of dummyStructure and by taking the integer part of the result of the division by 4 to multiply by 4, you will either have:
The exact size of dummyStructure, if it is aligned to 32 bits (or any multiple of it, such as 64 bits).
Or the first multiple of 32 bits greater than the size of dummyStructure.
Therefore it will always yield a 4 bytes divisible number (32 bits alignment).
Example:
If the size of dummyStructure is 8 bytes, the result would be ((8 + 3)/4)*4 = 8.
Now if the size of dummyStructure is, lets say 11, the result would be ((11 + 3)/4)*4 = 12.
I'm just wondering why the developer decided for this, though, since dummyStructure should be always aligned according to the processor architecture.
You can decompose it:
uint8_t variable[((sizeof(struct dummyStructure) + 3) /4)*4]
You have two cases - sizeof dummyStructure is evenly dividable by 4 or not.
Example:
(sizeof(struct dummyStructure) = 12
(12 + 3) / 4 = 15 / 4 = 3
3 * 4 = 12
so return original size
(sizeof(struct dummyStructure) = 13
(13 + 3) / 4 = 16 / 4 = 4
4 * 4 = 16
so return next size evenly dividable by 4
(sizeof(struct dummyStructure) = 15
(15 + 3) / 4 = 18 / 4 = 4
4 * 4 = 16
as above
(sizeof(struct dummyStructure) = 16
(16 + 3) / 4 = 19 / 4 = 4
4 * 4 = 16
so return original size again
(sizeof(struct dummyStructure) = 17
(17 + 3) / 4 = 20 / 4 = 5
5 * 4 = 20
so return next size evenly dividable by 4
In reality this code does not align variable at 32bit address! It only allocates enough space in array to allow put there dummyStructure alligned manually.
This solution is really bad.
IMHO better solutions (of course depends what happens in code):
1) since C11
struct defaultx
{
alignas(4) int variable[sizeof(struct dummyStructure)];
};
2) gcc or clang specific
struct defaultx
{
int variable[sizeof(struct dummyStructure)];
} __attribute__((aligned(4)));
will make sure variable is aligned to 4 bytes;

C code for alignment on Intel Core 2 Duo

I've been given the following c code for alignment
struct s *p, *new_p
p = (struct s*) malloc(sizeof(struct s) + BOUND -1);
new_p = (struct s*) (((int) p+BOUND-1) & ~(BOUND -1);
where BOUND represents 32 bytes. A line of cache is 32 bytes like in Pentium II and III but I cannot figure out the way p and new_p get aligned. Are both aligned or only new_p?
Also, I have this code for a line of cache of 64 B for a set associative cache with 8 blocks in each set and a size of 32 Kb:
int *tempA, *tempB;
...
pA= (int *) malloc (sizeof(int)*N + 63);
tempA = (int *)(((int)pA+63)&~(63));
tempB = (int *)((((int)pA+63)&~(63))+4096+64)
Accompanied with this remark: there will be a penalty if you access more than 8 address with a separation of 4 Kb.
The whole doesn't make much sense to me. Any ideas of what's going on?
Why not use _Alignas() (since C11)?
Casting a pointer to int is an invitation to disaster (aka undefined behaviour). Just think about a 64 bit machine with 32 bit (standard for most x86). If you need arithmetics on pointers, use uintptr_t (I would not recommend using intptr_t, though). However, even here, arithmetic on the value is still undefined (but very likely safe for platforms with single, linear address space).
Standard note: do not cast void * as returned by malloc().
Update:
Ok, lets take the code above and give it a proper formating and typing:
#include <stdint.h>
// align to this boundary (must be power of two!)
#define ALIGN_BOUNDARY 64U
Do not use magic numbers in your code! 2 months later you will wonder what that means.
int *tempA, *tempB;
How are those used?
int *pA = malloc (sizeof(int) * N + ALIGN_BOUNDARY - 1);
uintptr_t adjA = ((uintptr_t)pA + (ALIGN_BOUNDARY - 1)) & ~((uintptr_t) (ALIGN_BOUNDARY - 1);
This just rounds up the address to the next aligned boundary (here: 64 bytes).
tempA = (int *)adjA;
tempB = (int *)(adjA + 4096 + 64)
Not sure what the later is good for, but with the malloc given, that will result in disaster due to accessing beyond the allocated block if used with the same indexes (0..N) as *pA.
In any way, I would be very, very careful with this code. Not only it apparently is badly written/documented, but it seems also to contain errors.

memory allocation for structures elements

Hi I am having difficulties in understanding about how the memory is allocated to the structure elements.
For example if i have the below structure and the size of char is 1 and int is 4 bytes respectively.
struct temp
{
char a;
int b;
};
I am aware that the size of the structure would be 8. Because there will be a padding of 3 bytes after the char, and the next element should be placed in multiple of 4 so the size will be 8.
Now consider the below structure.
struct temp
{
int a; // size is 4
double b; // size is 8
char c; // size is 4
double d; // size is 8
int e; // size is 4
};
This is the o/p i got for the above strucure
size of node is 40
the address of node is 3392515152 ( =: base)
the address of a in node is 3392515152 (base + 0)
the address of b in node is 3392515160 (base + 8)
the address of c in node is 3392515168 (base + 16)
the address of d in node is 3392515176 (base + 24)
the address of e in node is 3392515184 (base + 32)
The total memory sum up to 36 bytes, why does it show as 40 bytes?
If we create an array of such structure also the first element of the next array element can be place in 3392515188 (base + 36) as it is a multiple of 4, but why is it not happening this way?
Can any one plz solve my doubt.
Thanks in advance,
Saravana
It seems that on your system, double has to have the alignment of 8.
struct temp {
int a; // size is 4
// padding 4 bytes
double b; // size is 8
char c; // size is 1
// padding 7 bytes
double d; // size is 8
int e; // size is 4
// padding 4 bytes
};
// Total 4+4+8+1+7+8+4+4 = 40 bytes
Compiler adds an extra 4 bytes to the end of struct to make sure that array[1].b will be properly aligned.
Without end padding (assuming array is at address 0):
&array[0] == 0
&array[1] == 36
&array[1].b == 36 + 8 == 44
44 % 8 == 4 -> ERROR, not aligned!
With end padding (assuming array is at address 0):
&array[0] == 0
&array[1] == 40
&array[1].b == 40 + 8 == 48
48 % 8 == 0 -> OK!
Note that sizes, alignments, and paddings depend on target system and compiler in use.
In your calculation, you ignore the fact that e is subject to be padded as well:
The struct looks like
0 8 16 24 32
AAAAaaaaBBBBBBBBCcccccccDDDDDDDDEEEEeeee
where uppercase is the variable itself, and lowercase is the padding applied to it.
As you see (and as well from the addresses), each field is padded to 8 bytes, which is the largest field in the structure.
As the structure might be used in an array, and all array elements should be well-aligned as well, the padding to e is necessary.
It's heavily dependent on both your processor architecture and compiler. Modern machines and compilers may choose larger or smaller padding to reduce the access cost to data.
Four-byte alignment means that two address lines are unused. Eight, three. A chip can use that to address more memory (coarser grain) with the same amount of hardware.
A compiler might use a similar trick for various reasons, but no compiler is required to do anything but be no less fine-grained than the processor. Often, they'll just take the biggest-size value and use it exclusively for that block. In your case, that's a double, which is eight bytes.
This is a compiler dependent behavior.
Some compiler makes that 'double' to be stored after 8 bit offset.
IF you modify the structure as below you will get different result.
struct temp
{
double b; // size is 8
int a; // size is 4
int e; // size is 4
double d; // size is 8
char c; // size is 4
}
Every programmer should know what padding you compiler is doing.
E.g. If you are working on ARM platform and you set compiler settings to do not pad structure elements[ then accessing structure elements through pointers may generate 'odd' address for which processor generates an exception.
Every structure will also have alignment requirements
for example :
typedef struct structc_tag
{
char c;``
double d;
int s;
} structc_t;
Applying same analysis, structc_t needs sizeof(char) + 7 byte padding + sizeof(double) + sizeof(int) = 1 + 7 + 8 + 4 = 20 bytes. However, the sizeof(structc_t) will be 24 bytes. It is because, along with structure members, structure type variables will also have natural alignment. Let us understand it by an example. Say, we declared an array of structc_t as shown below structc_t structc_array[3];
Assume, the base address of structc_array is 0×0000 for easy calculations. If the structc_t occupies 20 (0×14) bytes as we calculated, the second structc_t array element (indexed at 1) will be at 0×0000 + 0×0014 = 0×0014. It is the start address of index 1 element of array. The double member of this structc_t will be allocated on 0×0014 + 0×1 + 0×7 = 0x001C (decimal 28) which is not multiple of 8 and conflicting with the alignment requirements of double. As we mentioned on the top, the alignment requirement of double is 8 bytes. In order to avoid such misalignment, compiler will introduce alignment requirement to every structure. It will be as that of the largest member of the structure. In our case alignment of structa_t is 2, structb_t is 4 and structc_t is 8. If we need nested structures, the size of largest inner structure will be the alignment of immediate larger structure.
In structc_t of the above program, there will be padding of 4 bytes after int member to make the structure size multiple of its alignment. Thus the sizeof (structc_t) is 24 bytes. It guarantees correct alignment even in arrays. You can cross check
to avoid structure padding!
#pragma pack ( 1 ) directive can be used for arranging memory for structure members very next to the end of other structure members.
#pragma pack(1)
struct temp
{
int a; // size is 4
int b; // size is 4
double s; // size is 8
char ch; //size is 1
};
size of structure would be:17
If we create an array of such structure also the first element of the next array element can be place in 3392515188 (base + 36) as it is a multiple of 4, but why is it not happening this way?
It can't because of the double elements in there.
It's clear that the compiler and architecture you are using requires a double to be eight byte aligned. This is obvious because there is seven bytes of padding after the char c.
This requirement also means that the entire struct must be eight byte aligned. There's no point in carefully making all the doubles aligned to eight bytes relative to the start of the struct if the struct itself is only four byte aligned. Hence the padding after the final int to make sizeof(temp) a multiple of eight.
Note that this alignment requirement need not be a hard requirement. The compiler could choose to do the alignment even if doubles can be four byte aligned on the grounds that it might take more memory cycles to access the double if it's only four byte aligned.

Redis source code, (size&(sizeof(long)-1)) in the zmalloc.c

I am learning the Redis source code , and in the zmalloc.c,
size_t zmalloc_size(void *ptr) {
void *realptr = (char*)ptr-PREFIX_SIZE;
size_t size = *((size_t*)realptr);
/* Assume at least that all the allocations are padded at sizeof(long) by
* the underlying allocator. */
if (size&(sizeof(long)-1)) size += sizeof(long)-(size&(sizeof(long)-1));
return size+PREFIX_SIZE;
}
I am confused with
if (size&(sizeof(long)-1)) size += sizeof(long)-(size&(sizeof(long)-1));
what's the effect of it? Memory padding?Then why sizeof(long)?
Yes, it seems to be to include the memory padding with the assumption that all allocations are padded at the sizeof(long) (as said by the comment).
Pseudo-code example:
size = 6 // as an example
sizeof(long) == 4
size & (sizeof(long) - 1) == 6 & (4 - 1) == 6 & 3 == 2
size += 4 - 2
size == 8 // two bytes of padding included
I'm pretty fresh in C though so you should probably not take my word for it. I'm not sure why one can assume that the underlying allocator will align at the size of long, perhaps it's only a decent approximation that is sufficient for zmalloc_size's use-case.

Resources