Struct sizes and address of struct members [duplicate] - c++

This question already has answers here:
Weird Pointer Address for Individual Struct Data Member
(2 answers)
Closed 8 years ago.
2 questions about the below code:
1 Why is the size of struct b 12 bytes (line 2 of output)? I can understand why a is 12 bytes (to align k on the 4 byte boundary), however shouldnt b be 9 bytes and not 12?
2 Why is using the & operator to get the address of the char members not displaying a valid address? (middle output in the last 2 lines)
#include<iostream>
using namespace std;
struct a
{
int i;
char j;
int k;
};
struct b
{
int i;
int k;
char j;
};
int main()
{
a s1;
b s2;
cout<<sizeof(a)<<endl;
cout<<sizeof(b)<<endl;
cout<<sizeof(int)<<endl;
cout<<sizeof(char)<<endl;
cout<<&s1.i<<'\t'<<&s1.j<<'\t'<<&s1.k<<endl;
cout<<&s2.i<<'\t'<<&s2.j<<'\t'<<&s2.k<<endl;
}
Output:
12
12
4
1
0x28ff14 - 0x28ff1c
0x28ff08 4A 0x28ff0c

If b were 9 bytes large and you had an array
b foo[2];
then foo[1].i would not be aligned to four-byte boundaries.
As for the char members, their address is of type char *, and std::ostream has an operator<< for those that interprets them as a C-style string. If you want to see their address, static_cast<void*>(&s1.j) is your friend.
EDIT: Full disclosure of egg on my face: This originally stated that some compilers defined minimum struct alignment sizes; upon investigation, this turns out to be untrue. Well, it could be true, since the size of struct types is not specified in the standard to that extent, but common compilers don't appear to do it. Sorry about that.

Why is the size of struct b 12 bytes (line 2 of output)?
It has int fields, and so has the same alignment requirement as int - four bytes, in your case. Three padding bytes are added at the end, so the size is a multiple of four, to give the required alignment.
This applies even at the end of the structure, so that the next element of an array is properly aligned.
Why is using the & operator to get the address of the char members not displaying a valid address?
Because << interprets a pointer to a character type as a pointer to a C-style string, and prints memory contents until it finds a zero value. To print the address, cast to a non-character pointer type:
cout << (void*)&j;

Related

Why sizeof is printing 12 bytes instead of 9 for object of a class? [duplicate]

This question already has answers here:
Why isn't sizeof for a struct equal to the sum of sizeof of each member?
(13 answers)
Why does sizeof show 4 bytes for a char? [duplicate]
(1 answer)
Closed last year.
Why size of operator is showing 12 bytes instead of 9 for the below code in c++.
As int occupies 4 bytes, float occupies 4 bytes and character occupies 1 byte, then sizeof should give 9 bytes as output instead of 12.
Object stores memory for data members only not member functions (methods).
#include <iostream>
using namespace std;
class Sample{
public :
int i;
float a;
char ch;
public:
Sample(int j, float b, char dh){
i=j; a=b; ch=dh;
}
};
int main(){
Sample s1(10,3.14f, 'A');
Sample s2(20,6.28f,'B');
cout<<sizeof(s1)<<endl;
cout<<sizeof(s2)<<endl;
return 0;
}

how to copy to array inside struct?

How to copy to flexible array inside struct in c?
#include <stdio.h>
#include <string.h>
typedef struct
{
int val;
char buf[];
} foo;
int main()
{
foo f;
f.val = 4;
// f.buf = "asd"; -> invalid use of flexible array member
memcpy(f.buf, "asd\0", 4);
printf("%s\n", f.buf);
}
output:
asd
*** stack smashing detected ***: terminated
Aborted (core dumped)
Also, if the struct was declared as:
typedef struct
{
char buf[];
} foo
vscode editor gives error:
incomplete type is not allow
and gcc gives error:
error: flexible array member in a struct with no named members
6 | char buf[];
Why is array in struct now allowed but pointer is? (char *buf).
Also, If a struct has a flexible array, what is its sizeof(struct containsFlexArray)? How can I dynamically resolve its array, when it has no dimension?
EDIT:
if the above works in C++, because the incomplete array "decay" to pointer of known length (8 bytes in x64), why is this not also the case in c? If I peek to asm, I see the program does not allocate enough stack for the struct (it allocates only space for foo.val member, but not bur foo.buf member, in which case the program tries to use override the foo.val member (by using its address instead of foo.buf), which causes the stack smashing detected. But why is it implemented this wrong way? (So I want to know the rationale behind introducing flexible array as well)
You may want to read information on flexible array member here.
It seems as, when using a flexible array in a struct there must be at least one other data member and the flexible array member must be last.
And also you may have an element of clarification concerning the usage of flexible array members in C here
lets use intel/amd architecture here where char => 1 byte int => 4 and long is 8 bytes long.
Struct alignment is an issue here. You see when you declare a struct in c, compiler looks at it as individual block. So if you have a struct like this:
struct a {
long l;
char c1;
char c2;
}
compiler looks at the first type used, and allocates 8 bytes of memory for l, looks at c and determines that c1 is shorter than l and rather than figure out what c1's type is, it allocates 8 bytes of data for c1. It does the same for c2. So you end up with struct that is 24 bytes long and only 10 are used. Where if you use this:
struct b {
char c1;
long l;
char c2;
}
this will allocate 1 byte for c1, 8 byte for l, and 8 bytes for c2. So you end up with 17 bytes and 10 used. Where as if you have this:
struct b {
char c1;
char c2;
long l;
}
well it allocates 1 byte for c1, 1 byte for c2, and 8 bytes for l. In total 10 bytes but all 10 are used.
So what does it have to do with array? You see if you have:
struct aa {
char a;
long b[];
}
This will know to allocate at least one byte for b initially. Where when you do not have char a,
struct aa {
long b[];
}
Compiler might not allocate any memory (allocate 0 bytes), because it simply does not know how much to allocate.
EDIT:
Left my PC and in mean time other answer popped up. The other answer is very good!!! But I hope this helps you understand what is going on.
You did not initialize the buf[] array when you declared an instance in main(). The compiler does not know how much memory to allocate. The stack smashing is a compiler feature that keeps your program from doing... bad things to you computer. Add a number to your array declaration in typedef struct.
Like this:
` #include <stdio.h>
#include <string.h>
typedef struct
{
int val;
char buf[5];
} foo;
int main()
{
foo f;
f.val = 4;
// f.buf = "asd"; -> invalid use of flexible array member
memcpy(f.buf, "asd\0", 4);
printf("%s\n", f.buf);
}`

size of Struct with pointer [duplicate]

This question already has answers here:
Why isn't sizeof for a struct equal to the sum of sizeof of each member?
(13 answers)
Closed 6 years ago.
I compiled this code:
// Example program
#include <iostream>
using namespace std;
struct A
{
char a;
};
struct B
{
char b;
int a;
};
struct C
{
int * a;
unsigned char b;
};
int main()
{
cout<< "size of Strcut A:\t"<< sizeof(A)<<endl;
cout<< "size of Strcut B:\t"<< sizeof(B)<<endl;
cout<< "size of Strcut C:\t"<< sizeof(C)<<endl;
cout<< "size of int* : \t"<< sizeof(int*)<<endl;
return 0;
}
And I got this result:
size of Strcut A: 1
size of Strcut B: 8
size of Strcut C: 16
size of int* : 8
now I want to ask why the size of Strcut B is not 5? why the size of Struct C is not 9?
when the memory is importent in Embedded system how I should save memory in another platforms like ARM?
Can I say to the compiler it's 5 bytes or 9 bytes?
http://cpp.sh/2rv6b
Alignment. The members of your datastructures (and their total sizes) are padded with empty space between in order to speed up access and reduce redundant reads that would be necessary when a larger type spans a boundary.
The compiler decides to add some extra padding bits to allign your struct.
It's much faster to work with power of 8 data then spending time to extract them from memory.

struct hack - zero sized array

#include <iostream>
using namespace std;
struct node1{
char b[3];
int c[0];
};
struct node2{
int c[0];
};
struct node3{
char b[3];
};
int main() {
cout << sizeof(node1) << endl; // prints 4
cout << sizeof(node2) << endl; // prints 0
cout << sizeof(node3) << endl; // prints 3
}
My Question is why does the compiler allocate 0 bytes for int c[0] in node2
but allocate 1 byte for its when part of node1.
I'm assuming that this 1 byte is the reason why sizeof(node1) returns 4 since without it (like in node3) its size is 3 or is that due to padding??
Also trying to understand that shouldn't node2 have enough space to hold a pointer to an array (which will be allocated in the further down in the code as part of the flexible array/struct hack?
Yes, it's about padding/alignment. If you add __attribute__((__packed__)) to the end [useful when writing device drivers], you'll get 3 0 3 for your output.
If node1 had defined c[1], the size is 8 not 7, because the compiler will align c to an int boundary. With packed, sizeof would be 7
Yes, padding makes the difference. The reason why node1 has a padding byte, while node3 doesn't, lies in the typical usage of zero-length arrays.
Zero-length arrays are typically used with casting: You cast a larger, (possibly variable-sized) object to the struct containing the zero-length array. Then you access the "rest" of the large object using the zero-length array, which, for this purpose, has to be aligned properly. The padding byte is inserted before the zero-sized array, such that the ints are aligned. Since you can't do that with node3, no padding is needed.
Example:
struct Message {
char Type[3];
int Data[]; // it compiles without putting 0 explicitly
};
void ReceiveMessage(unsigned char* buffer, size_t length) {
if(length < sizeof(Message))
return;
Message* msg = (Message*)buffer;
if(!memcmp(msg->Type, "GET", 3)) {
HandleGet(msg->Data, (length - sizeof(Message))/sizeof(int));
} else if....
Note: this is rather hackish, but efficient.
c doesn't allocate one byte in node1. Its because of the padding added to b.
For b, to be easily obtainable by a 32-bit CPU, it is four bytes big. 32-bit CPUs can read 4 consecutive bytes from memory at a time. To read three, they have to read four and then remove the one not necessary. Therefore, to optimize this behavior, the compiler padds the struct with some bytes.
You can observe similar compiler optimizations when values are pushed on the stack (that is, arguments or local variables are allocated). The stack is always kept aligned to the CPU's data bus size (commonly 32 or 64 bits).
int main() {
cout << sizeof(node1) << endl; // prints 4
cout << sizeof(node2) << endl; // prints 0
cout << sizeof(node3) << endl; // prints 3
}
the main function queries the the size of the user defined structs, not of the array members. sizeof() will return the number of bytes allocated to the struct, with each character allocated in the character array being allocated 1 byte. A character array is really a C style string which is terminated by the sentinel character '\0'. It is likely to include the byte allocated to hold the sentinel character when evaluating the sizeof(node1) as there is another variable after it so it reads over it, but not include the sentinel in sizeof(node3) where the string and the struct terminates

Why does this yield different values on using sizeof operator? [duplicate]

This question already has answers here:
Why isn't the size of an array parameter the same as within main?
(13 answers)
Closed 7 years ago.
#include <iostream>
using namespace std;
int main (void)
{
int * p = new int(40); // here `p` points to an array having space for 40 ints or space allocated is 40 bytes?
for (int i = 0; i < 2; i++)
cin>>p[i];
cout<<sizeof(p)<<"\n"; // here, the output should be size of array since p points to an array
int arr[5] = {1,2,3,4,5}; // since, here it will output 20 (space allocated for the entire array)
cout<<sizeof(arr)<<"\n";
return 0;
}
So, I have two questions (the first two comments in the program)
Here p points to an array having space for 40 ints or space allocated is 40 bytes?
Here, the output should be size of array since p points to an array because technically speaking, arr is also a pointer and when we do *arr it references to the first element of the array.
In your code, p is defined as a pointer, so sizeof(p) is the same as sizeof(int*), with is 4 on 32bit systems and 8 on 64bit systems.
In the second case, arr is a static array, so sizeof(arr) is the same as sizeof(int[5]) which returns 5*sizeof(int), assuming there's no padding or other complex work happening "under the hood".
Note that when you pass an array name as an argument to a function which accepts a pointer as a formal function parameter, the array "decays" to a pointer, so calling sizeof on an argument yields behavior you likely did not expect. For example:
Code Listing
#include <stdio.h>
void printSize(int* arg);
int main(void)
{
int *p;
int arr[10];
printf("sizeof p:%d\n", sizeof(p));
printf("sizeof arr:%d\n", sizeof(arr));
printSize(p);
printSize(arr);
return 0;
}
void printSize(int* arg)
{
printf("sizeof arg:%d\n", sizeof(arg));
}
Sample Output
sizeof p:8
sizeof arr:40
sizeof arg:8
sizeof arg:8
When you say int *p = new int(40); you are actually allocating space for a single integer and filling that space with the integer 40. If you want an array of 40 integers, you should use square brackets:
int *p = new int[40];
So, to answer question #1: neither. The space allocated is the size of one int on your system.
To answer question #2: the first line of output is the size of a single pointer on your system (because p is just a pointer). This will probably be the same as the size of an int, which is likely 4 bytes. The second line of output will be the total allocation size of your array of integers, so it will be 40*sizeof(int), or 160.
Your two uses of sizeof are querying the size of the types int* and int[5] respectively.
(also, you have a bug and meant new int[40], not new int(40), but that doesn't affect the results of sizeof)