how to write 8 bytes to a void * address? - c++

So I have a defined a 8 bytes data structure
typedef struct __attribute__((__packed__)) entry{
// something here total 64 bits;
}entry_t;
and I have a void* basewhich is a pointer pointing to the base of where I want to put the entry.
Will
entry_t a;
*base = a;
do the job?
or I have to cast base to pointer to entry_t?
UPDATE
Sorry I didn't mention I can't use memcpy, because the kernel I am using doesn't implement memcpy yet.

Either:
*((entry_t *)base) = a;
or
memcpy(base, &a, sizeof a);
Of course, make sure that there are in fact 8 bytes there to copy into.

Convert the pointer to unsigned char * and write the 8 bytes with 8 uses of the assignment operator (either in a loop, or unrolled).

Related

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);
}`

Why is there a difference in the size of pointer to the struct variable when used with and without * operator in the sizeof() function?

using namespace std;
#include<iostream>
int main()
{
struct node
{
int data;
struct node *next;
};
struct node *node1;
node1 = (struct node*)malloc(sizeof(node));
node1->data = 5;
node1->next = NULL;
cout<<"node data value "<<node1->data<<endl;
int *vara;
cout<<"size of struct node pointer with * "<<sizeof(*node1)<<endl; // size is 8
cout<<"size of struct node pointer without * "<<sizeof(node1)<<endl; // size is 4
cout<<"size of integer pointer variable with * "<<sizeof(*vara)<<endl; // size is 4
cout<<"size of integer pointer variable with * "<<sizeof(*vara)<<endl; // size is 4 in this case as well
}
Why is there some difference in the size when used with * operator and without * operator for a pointer pointing to a struct variable ?
Executed the above code in CodeBlocks, Language C++.
Short answer: because node1 is a pointer and *node1 is a node, and these have different sizes.
Longer answer:
Let's examine the type of each of the expressions you are passing to the sizeof operator:
*node1 has type node, which consists of an int and a node*, both of which has size 4 bytes on your platform, hence making the total size 8 bytes.
node1 has type node*, which is a pointer. On your platform, pointers are 4 bytes long.
*vara has type int, which is an integer. On your platform, integers are 4 bytes long.
vara has type int*, which is a pointer. On your platform, pointers are 4 bytes long.
The first sizeof returns the size of the struct (the size of an int + the size of a pointer) , the second one the size of a pointer to a struct (4 bytes on your machine) the third one the size of an integer.
Why is there some difference in the size when used with "" operator and without "" operator for a pointer pointing to a struct variable ?
Because they are different types. In this declaration:
node *ptr;
ptr has type pointer to node, while *ptr has type node. In your third and forth example looks like you wanted to compare int vs int *. The fact that you get the same size for int * and int is just a coincidence and happened to be the same on your platform. You cannot either rely on that nor deduce any rules from that fact.
It is because a pointer, in this case, has the same size (4 bytes) than an integer, but your node structure's size is 8 bytes.
When you ask for sizeof(a) when a is a pointer, you ask for the size of the pointer. When you ask for sizeof(*a), you ask for the size of what is pointed by a.

Struct sizes and address of struct members [duplicate]

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;

Struct to string and vice versa

I would like to take the memory generated from my struct and push it into a byte array (char array) as well as the other way around (push the byte array back into a struct). It would be even better if I could skip the string generation step and go directly to writing memory into the EEPROM. (Do not worry about the eeprom bit, I can handle that by reading & writing individual bytes)
// These are just example structs (I will be using B)
typedef struct {int a,b,c;} A;
typedef struct {A q,w,e;} B;
#define OFFSET 0 // For now
void write(B input)
{
for (int i=0;i<sizeof(B);i++)
{
eepromWrite(i+OFFSET,memof(input,i));
}
}
B read()
{
B temp;
for (int i=0;i<sizeof(B);i++)
{
setmemof(temp,i,eepromRead(i+OFFSET));
}
return temp;
}
This example I wrote is not supposed to compile, it was meant to explain my ideas in a platform independent environment.
PLEASE NOTE: memof and setmemof do not exist. This is what I am asking for though my question. An alternative answer would be to use a char array as an intermediate step.
Assuming your structures contain objects and not pointers, you can do this with a simple cast:
save_b(B b) {
unsigned char b_data[sizeof(B)];
memcpy(b_data, (unsigned char *) &b, sizeof(B));
save_bytes(b_data, sizeof(B));
}
Actually, you shouldn't need to copy from the structure into a char array. I was just hoping to make the idea clear.
Be sure to look into #pragma pack, with determines how the elements in the stuctures are aligned. Any alignment greater than one byte may increase the size unnecessarily.

What's going on here: v5 = *(_Byte *)(this + 4)?

I am looking at a code dump from IDA pro. There is a function which as this layout:
garbled_name(int this...
unsigned int v5 ;
v5 = *(_Byte *)(this + 4);
...
What I am really curious about is what exactly the '+ 4' is doing? Is this an addition or something else?
Thanks
The code takes the integer 'this', adds 4 to it, casts it to a pointer to a byte, and then sets 'v5' to the value of the byte at that address.
It's just a member function of a C++ class, this being pointer to the object. This signature of the object is probably:
class some_class {
int i; // int, void*, short, anything with sizeof() <= 4, and it's not char.
// It also can be absent if it's a virtual class (AFAIK it's compiler dependend)
unsigned char c; // or c[N]
...
};
The code in question is:
some_class::some_fn(...){
unsigned int v5 = c; // or c[0]
...
};
It is a reference to the fifth byte from the beginning of the object. Depending on what compiler generated that code, it is most likely the item in class order which is at the fifth byte in the object instance.
EDIT: Sigh, I missed the "IDA Pro" part. I'll just leave this here for entertainment value, in case someone is wondering what "this+4" does in normal C++ code.
"this+4" takes your current this pointer, moves forward four times its size. Then it casts that to a byte pointer and reads it.
Consider this:
struct A {
void foo();
int x;
int y;
};
sizeof(A), on a 32-bit system, is most likely 8 bytes.
A myArray[8];
A *pA = myArray;
Now pA points to &myArray[0].
pA++;
Now pA points to &myArray[1], i.e. it moved 8 bytes forward.
void A::foo() {
A *pA = this + 4;
}
If you call this on &myArray[0], it will point to &myArray[4], i.e. 32 bytes further down the road.