Moving pointer to desired location - c

I am offsetting my pointer as shown in the below code to copy to another structure.
#include <stdio.h>
struct a
{
int i;
};
struct test
{
struct a *p;
int x,y,z;
};
int main()
{
struct test *ptr = malloc(sizeof(struct test));
struct test *q = malloc(sizeof(struct test));
ptr->x = 10;
ptr->y = 20;
ptr->z = 30;
memcpy(&(q->x),&(ptr->x),sizeof(struct test)-sizeof(struct a*));
printf("%d %d %d\n",q->x,q->y,q->z);
return 0;
}
Is there a better way to do my memcpy() ?
My question is what if I am in-cognizant of the members of the structure and want to just move my pointer by sizeof(struct a*) and copy rest of the structure?
Edits:
I want to copy some part of the structure but I don't know the members in it, but I know I want to skip some type of variable as shown in the example (struct a*) and copy rest of the structure.

Use offsetof(struct test, x) (C99, gcc), not sizeof(stuct a *). They are not guaranteed equal, because of padding/alignment. Caution: As a result of padding, using sizeof(..) can result in undefined behaviour, as there are copied too many chars.
offsetof(<type>, <member>) returns the offset of from the start of . So, sizef(struct test) - offsetof(struct test, x) yields the number of chars to copy all fields, starting with x.
Just read here for more details

I think the best way would be to use offsetof
memcpy(&(q->x),&(ptr->x),sizeof(struct test)-offsetof(struct test, x));
Because if first element was a little different, you could have alignment problems, whereas offsetof takes care of alignment for you.
Of course, alignement problems on a pointer should not occur on common architecture, but I think that offsetof is better practice anyway

Related

Struct pointer and its pointer attribute issue

Has this code undefined behaviour which means for s is mandatory to allocate memory or is ok this way ?
PS: what is the difference between
struct X* x = (struct X*)malloc(sizeof(struct X));
and
struct X* x = (struct X*)malloc(sizeof(x));
and
struct X* x = (struct X*)malloc(sizeof *x);
Thank you.
#include <stdio.h>
#include <stdlib.h>
struct X
{
int x;
char* s;
};
int main()
{
struct X* x = (struct X*)malloc(sizeof(struct X));
x->x = 10;
// x->s = (char*)malloc(10);
// memcpy...
x->s = "something";
printf("is ok?");
return 0;
}
Rather than throw my own interpretation at you i felt it would be more helpful to share a link that might clarify what you are aiming to achieve:
https://www.geeksforgeeks.org/new-vs-malloc-and-free-vs-delete-in-c/
When you create a pointer i see that you have added the pointer to your char* variable / struct, but when calling them the use of the ampersand & is used as a reference to the address in the memory.
But not applied quite right using the int variable when declaring it no '*' and then referencing the location using '&'.
This is fine. Since s is part of the struct, allocating memory for the struct allocates memory for s. I would strongly suggest changing the type of s to be a const pointer, since it points to a literal which, because it's a type of constant, cannot be modified.
You cannot do s[0]='n'; after this. You did not allocate any space to hold any string other than the unmodifiable literal "something".

Could this use of malloc lead to an "optional" struct field?

I was implementing a structure in which I needed (at runtime) to have an optional field.
So I thought about this:
//...
#include <stdlib.h>
struct test {
int x; // Must be
int y; // Optional (Must be the last field..(?))
};
int main(int argc, char **argv) {
// With the optional field
struct test *a = malloc(sizeof(*a));
a->x = 11;
a->y = 55;
// Without the optional field
struct test *b = malloc(sizeof(*b) - sizeof(int));
b->x = 22;
// ...
free(a);
free(b);
return 0;
}
Could this code do what I ask?
Possibly adding a bit field to check if there is the optional field or not.
Also, if the proposed solution works, if this were implemented for a list of multiple items (> 100000), would it be better to do it to save memory?
Could this code do what I ask?
Well, it could, but you cannot rely on that. Do not do this; it is not a way to write correct programs.
When you write b->x = 22;, the compiler is entitled to behave as if there were a whole struct test at b. You may be thinking, “I am just putting 22 in the bytes for the member x,” but the compiler may use a “store eight bytes” instruction:
Consider some architecture where memory is organized into eight-byte groups. The bus can only read and write whole eight-byte chunks.
Since there is no way to write four bytes in hardware, writing four bytes to memory requires reading eight bytes, manipulating them in processor registers to insert the desired values in four of the bytes, and writing eight bytes back to memory.
The compiler wants to optimize b->x = 22;, and it knows y has not been set yet, so it is allowed to have any value. So, instead of using an inefficient write-four-byte sequence, the compiler generates an eight-byte store that puts 22 in b->x and 0 in b->y.
Then this fails because the compiler has just written 0 to memory that might be in use for something else because it is not part of the space you allocated for b.
“If you lie to the compiler, it will get its revenge.” — Henry Spencer
What you're attempting doesn't conform to the C standard because you're attempting to use an object of type struct test that doesn't have enough memory allocated for it, even though you're only accessing the fields for which memory was allocated. It might work but you can't rely on that.
What you can do is make use of a flexible array member:
struct test {
int x;
int y[];
};
In a struct like this, sizeof(struct test) doesn't include the last member. You can use such a struct by allocating space for the struct plus as many array elements of the last member that you want. For example:
struct test *b = malloc(sizeof(*b) + sizeof(int));
b->x = 1;
b->y[0] = 2;
You'll need to use array indexing to access the last member, but this is a way to do what you want in a standard-conforming manner.
Then in the case you don't want the last member, you do this:
struct test *b = malloc(sizeof(*b));
b->x = 1;
I think your proposed solution is dangerous. Use two different structs:
struct test_x {
int x;
};
struct test_xy {
int x;
int y;
};
Either have two arrays or store a void * to either along with a discriminator (tagged pointer for instance). The other option is use a pointer for the optional element but sizeof(int *) is the same as sizeof(int) at least on my box, so that only makes things larger.
Consider a column layout if all the y members are optional, or you can sort the data so all the xy elements comes first:
struct test_column {
int *x;
int *y;
};
struct test_column t = {
.x = malloc(100000 * sizeof(int)),
.y = 0
It doesn't help you in case but unions are the standard way to two structs share memory so size of each element is
max(sizeof(test_xy), sizeof(test_x)) instead of sizeof(test_xy) + sizeof(test_x).
Finally, consider compression especially if you use the test_column format.

Type casting struct to short/int for saving value on adress

I would like to know, if its possible to cast struct to short but only 2 bites of its adress and save value in there. I personally dont even know if its possible just wanna get any ideas how to do that.
In my project i link void adress of char to struct and then doing something similar like malloc but without using malloc.. making somthing like function malloc.
My struct and its pointer:
typedef struct mem_list {
int size;
struct mem_list *next;
struct mem_list *prev;
}mem_list;
mem_list *start;
my function memory init:
void memory_init(void *ptr, unsigned int size){
mem_list *temp;
temp = (mem_list*)ptr;
if(size <= sizeof(mem_list)){
temp->size = 0;
printf("Failed\n");
return;
}
else
{
temp->size = size - sizeof(mem_list);
temp->next = NULL;
*((unsigned short*)(&temp + size - sizeof(unsigned short))) = 0;
start = temp;
printf("Inicialized was %d bits\n",size-sizeof(mem_list));
return;
}
}
My main:
int main() {
char region[100];
memory_init(region, 60);
//char* pointer = memory_alloc(20);
//printf("adresa %d\n", pointer);
return 0;
}
My problem is in function memory init in this part of code:
*((unsigned short*)(&temp + size - sizeof(unsigned short))) = 0;
What i want to do is to move to end of my inicialized memory and save there short typed zero for showing me later where is end of my memory. And also would like to ask how can i acces that value later? I know there maybe are mistakes in my code. Woul be happy if you point me where and give me some ideas how to do that. thank you :)
(&temp + size - sizeof(unsigned short))): &temp is the address of the pointer to your mem_list, so &temp + xxx is the address of somewhere in the stack :-(
The address of the last byte of your mem_list object is (char*)temp + size.
To be cleaner you could define your
typedef struct mem_list {
int size;
struct mem_list *next;
struct mem_list *prev;
unsigned short body[]
} mem_list_t ;
Then:
blen = (size + sizeof(unsigned short) - 1) / sizeof(unsigned short) ;
temp->body[blen] = 0 ;
writes 0 to the last unsigned short of the body of the mem_list_t.
Note that this assumes that ptr points to an object which has been allocated with asize bytes:
asize = offsetof(mem_list_t, body[blen+1]) ;
with blen calculated as above. (And ptr needs to be aligned as required for mem_list_t, of course.)
It is not clear whether you can reuse a char buffer to create objects of other types in it(*), but you should at least care about alignment. Some processors require non char types to be correctly aligned, for example that:
the address of an int16_t shall be even
the address of an int32_t or larger shall be a multiple of 4
And even if some other processors do not enforce this rule, accessing mis-aligned data often adds a significant overhead. That is the reason for padding in structs.
So without more precautions, this line:
*((unsigned short*)(&temp + size - sizeof(unsigned short))) = 0;
could break because if size is odd, you are trying to write an unsigned short at an odd address.
(*) For more details, you can read that other post from mine, specialy the comments on my own answer
if its possible to cast struct to short but only 2 bites of its adress and save value in there
No, it isn't possible. *((unsigned short*)(&temp...) invokes undefined behavior. It is a so-called "strict aliasing violation" and can also lead to misalignment issues depending on system. What is the strict aliasing rule?
The rule of thumb is: never wildly cast between completely different pointer types. You need a lot of detailed knowledge about C in order to so in a safe manner.
You can do "type punning" either by using a union between the struct and a unsigned short though. Please note that endianess is an issue to consider when doing so.
Other than that, you can safely memcpy the contents of a struct into an allocated unsigned short or vice versa. memcpy is excempt from pointer aliasing rules and will handle alignment safely.

Cast void pointer to struct and move it given size

I got a binary file that contains 3 different structs which I'm suppose to read to my program. After I have read the first struct I store its size, and then I'm suppose to convert my void pointer + the first structs length to a struct ip_hdr * (which is the second struct) and then read all it's values.
But the problems is I don't understand how you move a void pointer. I have understood that the void pointers don't have the same arithmetic rules as like a int pointer.
I want to do something like this:
ptr = (struct ip_hdr *)ptr) + (ethRes));
But that doesn't work instead I get following error message:
Expression must be a pointer to a complete object type
Here is my code:
#pragma warning(disable: 4996)
#include <stdio.h>
#include <stdlib.h>
#include "framehdr.h"
#include <crtdbg.h>
int main()
{
_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
FILE *fileOpen = fopen("C:\\Users\\Viktor\\source\\repos\\Laboration_3\\Laboration_3\\TCPdump", "rb");
//Pointers and variables
struct ethernet_hdr eth;
struct ethernet_hdr *ethPtr;
struct ip_hdr ip;
struct ip_hdr *ipPtr;
struct tcp_hdr tcp;
struct tcp_hdr *tcpPtr;
if (fileOpen == NULL)
{
printf("Error\n");
}
else
{
printf("Success\n");
}
char ethrr[10];
fscanf(fileOpen, "%s", ethrr);
int length = atoi(ethrr);
printf("Nr: %d\n", length);
void *ptr;
ptr = (void *)malloc(length);
fread(ptr, sizeof(eth), 1, fileOpen);
int ethRes = sizeof(((struct ethernet_hdr*)ptr)->dhost) +
sizeof(((struct ethernet_hdr*)ptr)->shost) +
sizeof(((struct ethernet_hdr*)ptr)->type);
printf("%d\n", ethRes);
printf("ptr1: %d\n", &ptr);
system("pause");
fclose(fileOpen);
return 0;
}
I now it's broken but I'm not done with it. Just need help with the pointers for now.
This should work, assuming the structure is compatible with whatever is in the file (in general saving structs "raw" to disk is a bad idea, the exact layout of a struct in memory is compiler-dependent and not stable enough to use as a file format):
const struct ip_hdr * const ip = (struct ip_hdr *) ((struct ethernet_hdr *) ptr + 1);
This adds "1" to a pointer of type ethernet_hdr, which will advance the actual pointer value by whatever size the Ethernet header structure has. The result is then cast to struct ip_hdr *.
I think this is what you wanted to do. You can do it by adding bytes to a char *, but what's the point?
You can't add directly to the void pointer, since pointer arithmetic is always in units of whatever is pointed at, and void has no size.
Here's an example of moving along an array of structures using a pointer to void.
The compiler doesn't know the type of object pointed to by a void* pointer.
So you have two choices. One is to convert it to a pointer to the 'correct' type and then add the number of elements you want to move. The other is to add the number of bytes you want to an unsigned char* (or similar).
The action happens on the lines marked [1] and [2] below.
#include <stdio.h>
typedef struct {
int payload;
double other;
} thingy;
int main(void) {
thingy athingy[2];//An array of two thingys.
void* voidptr=athingy; //a pointer to first thingy.
thingy* nextthingy=((unsigned char*)voidptr)+sizeof(thingy); //[A] next thingy points to second element of array.
thingy* altnext=((thingy*)voidptr)+1; //[B] Points to the same thing!
printf("voidptr==%p %zu\n",voidptr,sizeof(thingy));
printf("nextthingy==%p\n",nextthingy);
printf("altthingy==%p\n",altnext);
if(nextthingy==altnext){
printf("Same\n");
}else{
printf("Not same (oh dear)\n");
}
return 0;
}
Typical output:
voidptr==0x7ffd6909d660 4
nextthingy==0x7ffd6909d664
altthingy==0x7ffd6909d664
Same
The actual values may vary.
Caveat
If I understand the question, the requirement is to move through a number of different structs read together.
That may be problematic because of alignment. It's beyond the scope of this question to go into detail but C may place or require padding between members or objects of different type to ensure they are aligned on the architecture. It's very common for example for 4 byte integers to lie on memory addresses that numerically divide by 4. That simplifies hardware and improves performance.
It's not clear from the fragment provided that the objects read in will be aligned and further copying of data and shuffling may be required.
That may have been taken into account but that can't be seen from the information provided.
What may help is the often overlooked offsetof(,) macro defined in stddef.h.
That returns the offset of a member within a type (taking internal padding into consideration). For example there is in general no guarantee (above) that:
voidptr+sizeof(payload)==((unsigned char*)voidptr)+offsetof(thingy,other)

Casting struct * to int * to be able to write into first field

I've recently found this page:
Making PyObject_HEAD conform to standard C
and I'm curious about this paragraph:
Standard C has one specific exception to its aliasing rules precisely designed to support the case of Python: a value of a struct type may also be accessed through a pointer to the first field. E.g. if a struct starts with an int , the struct * may also be cast to an int * , allowing to write int values into the first field.
So I wrote this code to check with my compilers:
struct with_int {
int a;
char b;
};
int main(void)
{
struct with_int *i = malloc(sizeof(struct with_int));
i->a = 5;
((int *)&i)->a = 8;
}
but I'm getting error: request for member 'a' in something not a struct or union.
Did I get the above paragraph right? If no, what am I doing wrong?
Also, if someone knows where C standard is referring to this rule, please point it out here. Thanks.
Your interpretation1 is correct, but the code isn't.
The pointer i already points to the object, and thus to the first element, so you only need to cast it to the correct type:
int* n = ( int* )i;
then you simply dereference it:
*n = 345;
Or in one step:
*( int* )i = 345;
1 (Quoted from: ISO:IEC 9899:201X 6.7.2.1 Structure and union specifiers 15)
Within a structure object, the non-bit-field members and the units in which bit-fields
reside have addresses that increase in the order in which they are declared. A pointer to a
structure object, suitably converted, points to its initial member (or if that member is a
bit-field, then to the unit in which it resides), and vice versa. There may be unnamed
padding within a structure object, but not at its beginning.
You have a few issues, but this works for me:
#include <malloc.h>
#include <stdio.h>
struct with_int {
int a;
char b;
};
int main(void)
{
struct with_int *i = (struct with_int *)malloc(sizeof(struct with_int));
i->a = 5;
*(int *)i = 8;
printf("%d\n", i->a);
}
Output is:
8
Like other answers have pointed out, I think you meant:
// Interpret (struct with_int *) as (int *), then
// dereference it to assign the value 8.
*((int *) i) = 8;
and not:
((int *) &i)->a = 8;
However, none of the answers explain specifically why that error makes sense.
Let me explain what ((int *) &i)->a means:
i is a variable that holds an address to a (struct with_int). &i is the address on main() function's stack space. This means &i is an address, that contains an address to a (struct with_int). In other words, &i is a pointer to a pointer to (struct with_int). Then the cast (int *) of this would tell the compiler to interpret this stack address as an int pointer, that is, address of an int. Finally, with that ->a, you are asking the compiler to fetch the struct member a from this int pointer and then assign the value 8 to it. It doesn't make sense to fetch a struct member from an int pointer. Hence, you get error: request for member 'a' in something not a struct or union.
Hope this helps.

Resources