Behaviour of sizeof operator in C - c

I am getting unusual behaviour with my code, which is as follows
#include<stdio.h>
struct a
{
int x;
char y;
};
int main()
{
struct a str;
str.x=2;
str.y='s';
printf("%d %d %d",sizeof(int),sizeof(char),sizeof(str));
getch();
return 0;
}
For this piece of code I am getting the output:
4 1 8
As of my knowledge the structure contains an integer variable of size 4 and a char variable of size 1 thus the size of structure a should be 5. But how come the size of structure is 8.
I am using visual C++ compiler.
Why this behaviour?

It is called Structure Padding
Having data structures that start on 4 byte word alignment (on CPUs with 4 byte buses and processors) is far more efficient when moving data around memory, and between RAM and the CPU.
You can generally switch this off with compiler options and/or pragmas, the specifics of doing so will depend on your specific compiler.
Hope this helps.

The compiler inserts padding for optimization and aligment purposes. Here, the compiler inserts 3 dummy bytes between (or after) your both members.
You can handle the alignment with #pragma directive.

Mostly to illustrate how this padding actually works, I've amended your program a little.
#include<stdio.h>
struct a
{
int x;
char y;
int z;
};
int main()
{
struct a str;
str.x=2;
str.y='s';
str.z = 13;
printf ( "sizeof(int) = %lu\n", sizeof(int));
printf ( "sizeof(char) = %lu\n", sizeof(char));
printf ( "sizeof(str) = %lu\n", sizeof(str));
printf ( "address of str.x = %p\n", &str.x );
printf ( "address of str.y = %p\n", &str.y );
printf ( "address of str.z = %p\n", &str.z );
return 0;
}
Note that I added a third element to the structure. When I run this program, I get:
amrith#amrith-vbox:~/so$ ./padding
sizeof(int) = 4
sizeof(char) = 1
sizeof(str) = 12
address of str.x = 0x7fffc962e070
address of str.y = 0x7fffc962e074
address of str.z = 0x7fffc962e078
amrith#amrith-vbox:~/so$
The part of this that illustrates padding is highlighted below.
address of str.y = 0x7fffc962e074
address of str.z = 0x7fffc962e078
While y is only one character, note that z is a full 4 bytes along.

Related

How to extract a pointer size in C

i have code like this:
int main()
{
double *u;
int len;
u=(double *)malloc(sizeof(double)*10);
len = sizeof(u);
printf("Length Of Array = %d\n", len);
return 0;
}
but the length is 4 Not 10.
how can i extract 10 from pointer u?!
please help me
thank you
That's your job. C does not provide a portable way of knowing, given a pointer, how much memory has been allocated.
sizeof will give you sizeof(double*), that's all. That's 4 on your system.
It is not possible. sizeof is giving the size of the object. In your case the object is u which is a pointer. Your system is 32 bits as pointers are 4 bytes.
if you sizeof(*u)- you will get the size of referenced type. In this case it is the double . It will be 8 bytes long at most systems.
using sizeof to get the size of the length of the string is one of the most frequent questions asked here.
A pointer doesn't include information about the size of the memory area. You have to keep track of the size yourself. For instance, you can make a custom type (for example, a struct) that contains both the pointer and the size of the allocation at the same time.
Here's a simple implementation to get you started:
typedef struct {
double* ptr;
size_t len;
} double_arr_t;
// prototype
double_arr_t alloc_double_arr(size_t len);
int main(void) {
// alloc the new array of 10 `double` elements
double_arr_t arr = alloc_double_arr(10);
printf("Length of 'arr' is %zu\n", arr.len); // Length of 'arr' is 10
// assign a value to the first element
arr.ptr[0] = 3.14;
// get the value of the first element
double first_element = arr.ptr[0];
// free the array when you're done using it
free(arr.ptr);
}
double_arr_t alloc_double_arr(size_t len) {
double_arr_t res;
res.ptr = malloc(len * sizeof(double));
res.len = len;
return res;
}

Accessing structure members using base address

Can you please help explain why following program correctly prints the values of all the structure members?
struct st
{
int i;
char c1;
int j;
char c2;
};
int main()
{
struct st a = {5, 'i', 11, 'H'};
struct st * pa = &a;
int first;
char second;
int third;
char fourth;
first = *((int*)pa);
second = *((char*)pa + 4); /* offset = 4 bytes = sizeof(int) */
third = *((int*)pa + 2); /* why (pa + 2) here? */
fourth = *((char*)pa + 12); /* why (pa + 12) here? */
printf ("first = %d, second = %c, third = %d, fourth = %c\n", first, second, third, fourth);
return 0;
}
Output: first = 5, second = i, third = 11, fourth = H
How can I make above program generalized?
That's because of the padding bytes added to the structure. Three padded bytes will be added after char second;, this is because the char is followed by an int (member with larger alignment) so padding bytes will be inserted to make the alignment multiple of the alignment of larger member.
How can I make above program generalized?
The only way to make it work reliably is by not guessing at the offset. Use the standard offsetof macro, and always do the pointer arithmetic with a character pointer:
first = *(int*)((char*)pa + offsetof(struct st, i));
You don't have to name the field at the point you do the access, but you should definitely use the macro to compute the offest if you intend to pass it into your function.
It is because of structure padding.
After padding your structure will look like below.
struct st
{
int i;
char c1;
char padding[3]; // for alignment of j.
int j;
char c2;
char padding[3]; // for alignment of structure.
};
Hence
first = *((int*)pa);
second = *((char*)pa + 4); /* offset = 4 bytes = sizeof(int) */
third = *((int*)pa + 2); /* offset = 8 bytes(pointer arithmetic) to point to int j*/
fourth = *((char*)pa + 12); /* offset = 12 bytes to point to char c2*/
For more info on structure padding read
Data_structure_alignment
As in another answers - padding.
But some compilers allow you to pack your structures removing (in most cases) the padding.
gcc:
struct __attribute__((packed)) st
{
....
}
The code which access the packed structs may be less efficient and longer.
When creating a struct, all variables occupy the same amount of space (32 bits), the remaining unused bits are padding. So even if you define a char in the struct, this will occupy 4 bytes.
This is due to the fact that your processor addresses data at 32 bits, even if afterwards less bits are used. The memory on the other side stores 1 byte for each address, but when data is fetched by the CPU, data will be adapted to the bus architecture (that depends on the processor).
Also note that the offset depends on the pointer you are using. a char* in this case will increase by 1, while a int* by 4.
This also means that the code is not portable, since, for example, int may not be defined of the same size on different architectures.

can i use "int" as my dynamic array inside a struct?

In general, i'm trying to allocate values of first.a and first.b
to a array's in struct secon.
typedef struct {
int a;
int b;
} firs;
//secon is my struct which contains dynamic array
//can i use int here ?
typedef struct {
int *aa;
int *bb;
} secon;
//pointer to secon intialised to NULL;
secon* sp=NULL;
int main()
{
firs first;
//plz assume 2 is coming from user ;
sp=malloc(sizeof(secon)*2);
//setting values
first.a=10;
first.b=11;
/* what i'm trying to do is assign values of first.a and first.b to my
dynamically created array*/
/* plz assume first.a and first.b are changing else where .. that means ,not
all arrays will have same values */
/* in general , i'm trying to allocate values of first.a and first.b
to a array's in struct second. */
for(int i=0; i<2; i++) {
*( &(sp->aa ) + (i*4) ) = &first.a;
*( &(sp->bb ) + (i*4) ) = &first.b;
}
for(int i=0; i<2; i++) {
printf("%d %d \n", *((sp->aa) + (i*4) ),*( (sp->bb) +(i*4) ) );
}
return 0;
}
MY output :
10 11
4196048 0
Problems with my code:
1. whats wrong with my code?
2. can i use int inside struct for dynamic array?
3. what are the alternatives?
4. why am i not getting correct answer?
Grigory Rechistov has done a really good job of untangling the code and you should probably accept his answer, but I want to emphasize one particular point.
In C pointer arithmetic, the offsets are always in units of the size of the type pointed to. Unless the type of the pointer is char* or void* if you find yourself multiplying by the size of the type, you are almost certainly doing it wrong.
If I have
int a[10];
int *p = &(a[5]);
int *q = &(a[7]);
Then a[6] is the same as *(p + 1) not *(p + 1 * sizeof(int)). Likewise a[4] is *(p - 1)
Furthermore, you can subtract pointers when they both point to objects in the same array and the same rule applies; the result is in the units of the size of the type pointed to. q - p is 2, not 2 * sizeof(int). Replace the type int in the example with any other type and the p - q will always be 2. For example:
struct Foo { int n ; char x[37] ; };
struct Foo a[10];
struct Foo *p = &(a[5]);
struct Foo *q = &(a[7]);
q - p is still 2. Incidentally, never be tempted to hard code a type's size anywhere. If you are tempted to malloc a struct like this:
struct Foo *r = malloc(41); // int size is 4 + 37 chars
Don't.
Firstly, sizeof(int) is not guaranteed to be 4. Secondly, even if it is, sizeof(struct Foo) is not guaranteed to be 41. Compilers often add padding to struct types to ensure that the members are properly aligned. In this case it is almost a certainty that the compiler will add 3 bytes (or 7 bytes) of padding to the end of struct Foo to ensure that, in arrays, the address of the n member is aligned to the size of an int. always always always use sizeof.
It looks like your understanding how pointer arithmetic works in C is wrong. There is also a problem with data layout assumptions. Finally, there are portability issues and a bad choice of syntax that complicates understanding.
I assume that wit this expression: *( &(sp->aa ) + (i*4) ) you are trying to access the i-th item in the array by taking address of the 0-th item and then adding a byte offset to it. This is wrong of three reasons:
You assume that after sp[0].aa comes sp[1].aa in memory, but you forget that there is sp[0].bb in between.
You assume that size of int is always 4 bytes, which is not true.
You assume that adding an int to secon* will give you a pointer that is offset by specified number of bytes, while in fact it will be offset in specified number of records of size secon.
The second line of output that you see is random junk from unallocated heap memory because when i == 1 your constructions reference memory that is outside of limits allocated for *secon.
To access an i-th item of array referenced by a pointer, use []:
secon[0].aa is the same as (secon +0)->aa, and secon[1].aa is equal to (secon+1)->aa.
This is a complete mess. If you want to access an array of secons, use []
for(int i=0;i<2;i++)
{
sp[i].aa = &first.a; // Same pointer both times
sp[i].bb = &first.b;
}
You have two copies of pointers to the values in first, they point to the same value
for(int i=0;i<2;i++)
{
sp[i].aa = malloc(sizeof(int)); // new pointer each time
*sp[i].aa = first.a; // assigned with the current value
sp[i].bb = malloc(sizeof(int));
*sp[i].bb = first.b;
}
However the compiler is allowed to assume that first does not change, and it is allowed to re-order these expressions, so you are not assured to have different values in your secons
Either way, when you read back the values in second, you can still use []
for(int i=0;i<2;i++)
{
printf("%d %d \n",*sp[i].aa ),*sp[i].bb );
}

malloc-> how much memory is allocated? [duplicate]

This question already has answers here:
I can use more memory than how much I've allocated with malloc(), why?
(17 answers)
Closed 9 years ago.
As I know that malloc allocate a specific number of bytes in the memory. However I am trying to use it and I allocate 4 bytes but it gives me NO error when I try to store more than 4 (up to 200 integers) elements in the array!! So in my code I don't need to use realloc!! I'm using Linux by the way. Finally I will pleased to hear any advice from you ... thanks in advance.
tmp.h :
#ifndef TMP_H
#define TMP_H
#define MAXLENGTH 4
#define GROWFACTOR 1.5
typedef struct stVector
{
int *vec;
int length;
int maxLength;
}Vector;
Vector newEmptyVector();
void addElement(Vector *vec, int elt);
#endif
tmp.c :
#include "stdio.h"
#include "stdlib.h"
#include "tmp.h"
Vector newEmptyVector()
{
Vector vec;
vec.vec = (int*) malloc(0);
printf("Allocating %d bytes\n", sizeof(int)*MAXLENGTH );
vec.length = 0;
vec.maxLength = MAXLENGTH;
return vec;
}
void addElement(Vector *vec, int elt)
{
/*if(vec->length == vec->maxLength)
{
vec->vec = (int*)realloc(vec->vec,sizeof(int)* vec->maxLength * GROWFACTOR);
vec->maxLength = vec->maxLength * GROWFACTOR;
}*/
vec->vec[vec->length++] = elt;
}
main.c :
#include"tmp.h"
int main(int argc, char const *argv[])
{
Vector vector = newEmptyVector();
printf("The length is %i and maxlength is ` `%i\n",vector.length,vector.maxLength);
addElement(&vector,5);
addElement(&vector,3);
addElement(&vector,1);
addElement(&vector,7);
printf("The length is %i and maxlength is ` `%i\n",vector.length,vector.maxLength);
addElement(&vector,51);
printf("The length is %i and maxlength is %i\n",vector.length,vector.maxLength);
for (int i = 0; i < 200; ++i)
{
addElement(&vector,i);
printf("The length is %i and maxlength is %i\n" ,vector.length, vector.maxLength);
}
return 0;
}
Using memory you haven't allocated invokes undefined behavior. Don't do that. In all likelyhood, Linux has give your program a page of memory, and you haven't overrun that yet. If you touch memory not allocated to your program the OS should cause your program to segfault. But it's possible that any other mallocing you do will also use parts of that page, and you'll end up corrupting your data.
Not having runtime checks for overrunning buffers is part of what makes C fast, but it puts more on the programmer not to do dumb things.
The fact that (simply because there is no bound checking in C) no error is raised does not mean that you can safely use memory outside requested bounds. You were lucky not to cause a segmentation fault, you have just fallen into a memory region that is not claimed by your malloc (let's say, it's not yours).
You can write there, but there is no guarantee that you won't be overwriting memory assigned to another malloc or, conversely, that the "extra" part will not be allocated to some other malloc. In your case, the memory region you are writing into appears not to be claimed (yet).
Regarding your specific issue:, I allocate 4 bytes but it gives me NO error when I try to store more than 4.
Keep in mind, something like:
int *anyVar = (int)malloc(0);
anyVar[0] = 12; //Will eventually invoke undefined behavior.
writing to memory you do not own will eventually invoke undefined behavior. The bad thing is that your results can seem good, and even repeatable for many runs of the code. But at some point, your code will fail.
This is how you should allocate: (by the way)
int numIntsInArray = 100;
int *anyVar = malloc(sizeof(int)*numIntsInArray);//note:do not cast output of malloc
anyVar[0] = 1;//first element of anyVar
anyVar[99] = 1000;//last element of anyVar
Do not forget to free all memory:
free(anyVar);
Other examples of undefined behavior in C & C++:
The examples of bad code below can be done, and you will likely get no compiler warnings, and may even get
expected results during run-time, but with this code, nothing is guaranteed. (exception: good examples)
char * p = "string"; // Badly formed C++11, deprecated C++98/C++03
p[0] = 'X'; // undefined behavior
Create an array instead:
char p[] = "string"; // Good
p[0] = 'X';
C++, you can create/use a standard string like this:
std::string s = "string"; // Good
s[0] = 'X';
Division by zero results in undefined behavior:
int x = 1;
return x / 0; // undefined behavior
Some pointer operations may lead to undefined behavior:
int arr[4] = {0, 1, 2, 3};
int* p = arr + 5; // undefined behavior
Leaving a non-void function without returning a value
int func(void)
{
//undefined behavior
}
Unspecified or implementation-defined behavior:
printf("%d %d\n", ++n, power(2, n)); //Bad
i = ++i + 1; //Bad
i = i + 1; // Okay

How to allocate 16byte memory aligned data

I am trying to implement SSE vectorization on a piece of code for which I need my 1D array to be 16 byte memory aligned. However, I have tried several ways to allocate 16byte memory aligned data but it ends up being 4byte memory aligned.
I have to work with the Intel icc compiler.
This is a sample code I am testing with:
#include <stdio.h>
#include <stdlib.h>
void error(char *str)
{
printf("Error:%s\n",str);
exit(-1);
}
int main()
{
int i;
//float *A=NULL;
float *A = (float*) memalign(16,20*sizeof(float));
//align
// if (posix_memalign((void **)&A, 16, 20*sizeof(void*)) != 0)
// error("Cannot align");
for(i = 0; i < 20; i++)
printf("&A[%d] = %p\n",i,&A[i]);
free(A);
return 0;
}
This is the output I get:
&A[0] = 0x11fe010
&A[1] = 0x11fe014
&A[2] = 0x11fe018
&A[3] = 0x11fe01c
&A[4] = 0x11fe020
&A[5] = 0x11fe024
&A[6] = 0x11fe028
&A[7] = 0x11fe02c
&A[8] = 0x11fe030
&A[9] = 0x11fe034
&A[10] = 0x11fe038
&A[11] = 0x11fe03c
&A[12] = 0x11fe040
&A[13] = 0x11fe044
&A[14] = 0x11fe048
&A[15] = 0x11fe04c
&A[16] = 0x11fe050
&A[17] = 0x11fe054
&A[18] = 0x11fe058
&A[19] = 0x11fe05c
It is 4byte aligned everytime, i have used both memalign, posix memalign. Since I am working on Linux, I cannot use _mm_malloc neither can I use _aligned_malloc.
I get a memory corruption error when I try to use _aligned_attribute (which is suitable for gcc alone I think).
Can anyone assist me in accurately generating 16byte memory aligned data for icc on linux platform.
The memory you allocate is 16-byte aligned. See:
&A[0] = 0x11fe010
But in an array of float, each element is 4 bytes, so the second is 4-byte aligned.
You can use an array of structures, each containing a single float, with the aligned attribute:
struct x {
float y;
} __attribute__((aligned(16)));
struct x *A = memalign(...);
The address returned by memalign function is 0x11fe010, which is a multiple of 0x10. So the function is doing a right thing. This also means that your array is properly aligned on a 16-byte boundary. What you are doing later is printing an address of every next element of type float in your array. Since float size is exactly 4 bytes in your case, every next address will be equal to the previous one +4. For instance, 0x11fe010 + 0x4 = 0x11FE014. Of course, address 0x11FE014 is not a multiple of 0x10. If you were to align all floats on 16 byte boundary, then you will have to waste 16 / 4 - 1 bytes per element. Double-check the requirements for the intrinsics that you are using.
AFAIK, both memalign and posix_memalign are doing their job.
&A[0] = 0x11fe010
This is aligned to 16 byte.
&A[1] = 0x11fe014
When you do &A[1] you are telling the compiller to add one position to a float pointer. It will unavoidably lead to:
&A[0] + sizeof( float ) = 0x11fe010 + 4 = 0x11fe014
If you intend to have every element inside your vector aligned to 16 bytes, you should consider declaring an array of structures that are 16 byte wide.
struct float_16byte
{
float data;
float padding[ 3 ];
}
A[ ELEMENT_COUNT ];
Then you must allocate memory for ELEMENT_COUNT (20, in your example) variables:
struct float_16byte *A = ( struct float_16byte * )memalign( 16, ELEMENT_COUNT * sizeof( struct float_16byte ) );
I found this code on Wikipedia:
Example: get a 12bit aligned 4KBytes buffer with malloc()
// unaligned pointer to large area
void *up=malloc((1<<13)-1);
// well aligned pointer to 4KBytes
void *ap=aligntonext(up,12);
where aligntonext() is meant as:
move p to the right until next well aligned address if
not correct already. A possible implementation is
// PSEUDOCODE assumes uint32_t p,bits; for readability
// --- not typesafe, not side-effect safe
#define alignto(p,bits) (p>>bits<<bits)
#define aligntonext(p,bits) alignto((p+(1<<bits)-1),bits)
I personally believe your code is correct and is suitable for Intel SSE code. When you load data into an XMM register, I believe the processor can only load 4 contiguous float data from main memory with the first one aligned by 16 byte.
In short, I believe what you have done is exactly what you want.
you could also used this in VS.
__declspec(align(16)) struct x {
long long a;
long long b;
char c;
};
instead of this
struct x {
float y;
} __attribute__((aligned(16)));

Resources