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)
Related
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.
I have looked around but have been unable to find a solution to what must be a well asked question.
Here is the code I have:
#include <stdlib.h>
struct my_struct {
int n;
char s[]
};
int main()
{
struct my_struct ms;
ms.s = malloc(sizeof(char*)*50);
}
and here is the error gcc gives me:
error: invalid use of flexible array member
I can get it to compile if i declare the declaration of s inside the struct to be
char* s
and this is probably a superior implementation (pointer arithmetic is faster than arrays, yes?)
but I thought in c a declaration of
char s[]
is the same as
char* s
The way you have it written now , used to be called the "struct hack", until C99 blessed it as a "flexible array member". The reason you're getting an error (probably anyway) is that it needs to be followed by a semicolon:
#include <stdlib.h>
struct my_struct {
int n;
char s[];
};
When you allocate space for this, you want to allocate the size of the struct plus the amount of space you want for the array:
struct my_struct *s = malloc(sizeof(struct my_struct) + 50);
In this case, the flexible array member is an array of char, and sizeof(char)==1, so you don't need to multiply by its size, but just like any other malloc you'd need to if it was an array of some other type:
struct dyn_array {
int size;
int data[];
};
struct dyn_array* my_array = malloc(sizeof(struct dyn_array) + 100 * sizeof(int));
Edit: This gives a different result from changing the member to a pointer. In that case, you (normally) need two separate allocations, one for the struct itself, and one for the "extra" data to be pointed to by the pointer. Using a flexible array member you can allocate all the data in a single block.
You need to decide what it is you are trying to do first.
If you want to have a struct with a pointer to an [independent] array inside, you have to declare it as
struct my_struct {
int n;
char *s;
};
In this case you can create the actual struct object in any way you please (like an automatic variable, for example)
struct my_struct ms;
and then allocate the memory for the array independently
ms.s = malloc(50 * sizeof *ms.s);
In fact, there's no general need to allocate the array memory dynamically
struct my_struct ms;
char s[50];
ms.s = s;
It all depends on what kind of lifetime you need from these objects. If your struct is automatic, then in most cases the array would also be automatic. If the struct object owns the array memory, there's simply no point in doing otherwise. If the struct itself is dynamic, then the array should also normally be dynamic.
Note that in this case you have two independent memory blocks: the struct and the array.
A completely different approach would be to use the "struct hack" idiom. In this case the array becomes an integral part of the struct. Both reside in a single block of memory. In C99 the struct would be declared as
struct my_struct {
int n;
char s[];
};
and to create an object you'd have to allocate the whole thing dynamically
struct my_struct *ms = malloc(sizeof *ms + 50 * sizeof *ms->s);
The size of memory block in this case is calculated to accommodate the struct members and the trailing array of run-time size.
Note that in this case you have no option to create such struct objects as static or automatic objects. Structs with flexible array members at the end can only be allocated dynamically in C.
Your assumption about pointer aritmetics being faster then arrays is absolutely incorrect. Arrays work through pointer arithmetics by definition, so they are basically the same. Moreover, a genuine array (not decayed to a pointer) is generally a bit faster than a pointer object. Pointer value has to be read from memory, while the array's location in memory is "known" (or "calculated") from the array object itself.
The use of an array of unspecified size is only allowed at the end of a structure, and only works in some compilers. It is a non-standard compiler extension. (Although I think I remember C++0x will be allowing this.)
The array will not be a separate allocation for from the structure though. So you need to allocate all of my_struct, not just the array part.
What I do is simply give the array a small but non-zero size. Usually 4 for character arrays and 2 for wchar_t arrays to preserve 32 bit alignment.
Then you can take the declared size of the array into account, when you do the allocating. I often don't on the theory that the slop is smaller than the granularity that the heap manager works in in any case.
Also, I think you should not be using sizeof(char*) in your allocation.
This is what I would do.
struct my_struct {
int nAllocated;
char s[4]; // waste 32 bits to guarantee alignment and room for a null-terminator
};
int main()
{
struct my_struct * pms;
int cb = sizeof(*pms) + sizeof(pms->s[0])*50;
pms = (struct my_struct*) malloc(cb);
pms->nAllocated = (cb - sizoef(*pms) + sizeof(pms->s)) / sizeof(pms->s[0]);
}
I suspect the compiler doesn't know how much space it will need to allocate for s[], should you choose to declare an automatic variable with it.
I concur with what Ben said, declare your struct
struct my_struct {
int n;
char s[1];
};
Also, to clarify his comment about storage, declaring char *s won't put the struct on the stack (since it is dynamically allocated) and allocate s in the heap, what it will do is interpret the first sizeof(char *) bytes of your array as a pointer, so you won't be operating on the data you think you are, and probably will be fatal.
It is vital to remember that although the operations on pointers and arrays may be implemented the same way, they are not the same thing.
Arrays will resolve to pointers, and here you must define s as char *s. The struct basically is a container, and must (IIRC) be fixed size, so having a dynamically sized array inside of it simply isn't possible. Since you're mallocing the memory anyway, this shouldn't make any difference in what you're after.
Basically you're saying, s will indicate a memory location. Note that you can still access this later using notation like s[0].
pointer arithmetic is faster than arrays, yes?
Not at all - they're actually the same. arrays translate to pointer arithmetics at compile-time.
char test[100];
test[40] = 12;
// translates to: (test now indicates the starting address of the array)
*(test+40) = 12;
Working code of storing array inside a structure in a c, and how to store value in the array elements Please leave comment if you have any doubts, i will clarify at my best
Structure Define:
struct process{
int process_id;
int tau;
double alpha;
int* process_time;
};
Memory Allocation for process structure:
struct process* process_mem_aloc = (struct process*) malloc(temp_number_of_process * sizeof(struct process));
Looping through multiple process and for each process updating process_time dyanamic array
int process_count = 0;
int tick_count = 0;
while(process_count < number_of_process){
//Memory allocation for each array of the process, will be containting size equal to number_of_ticks: can hold any value
(process_mem_aloc + process_count)->process_time = (int*) malloc(number_of_ticks* sizeof(int));
reading data from line by line from a file, storing into process_time array and then printing it from the stored value, next while loop is inside the process while loop
while(tick_count < number_of_ticks){
fgets(line, LINE_LENGTH, file);
*((process_mem_aloc + process_count)->process_time + tick_count) = convertToInteger(line);;
printf("tick_count : %d , number_of_ticks %d\n",tick_count,*((process_mem_aloc + process_count)->process_time + tick_count));
tick_count++;
}
tick_count = 0;
the code generated will be identical (array and ptr). Apart from the fact that the array one wont compile that is
and BTW - do it c++ and use vector
Frankly, is such a code valid or does it invoke undefined behavior?
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
struct two_values
{
int some;
char value;
};
int main(void) {
int some = 5;
char value = 'a';
unsigned char *data = malloc(sizeof(struct two_values));
memcpy(data, &some, sizeof(int));
memcpy(data+sizeof(int), &value, sizeof(char));
struct two_values dest;
memcpy(&dest, data, sizeof(struct two_values));
printf("some = %d, value = %c\n", dest.some, dest.value);
return 0;
}
http://ideone.com/4JbrP9
Can I just put the binary representation of two struct field together and reinterpret this as the whole struct?
You had better to not disturb the internal compiler doings in your code, as it would lead you to incorrect code and undefined behaviour. You can switch compilers, or just updating the version of your favourite, and run into trouble.
The best way to solve the thing you show of having two variables and to store them properly in the struct fields is to use properly the types provided by C, and use a pointer typed to the proper type. If you use
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
struct two_values
{
int some;
char value;
};
int main(void) {
int some = 5;
char value = 'a';
/* next instead of unsigned char *data = malloc(sizeof(struct two_values)); */
struct two_values *data = malloc(sizeof(struct two_values));
/* next instead of memcpy(data, &some, sizeof(int)); */
data->some = some;
/* next instead of memcpy(data+sizeof(int), &value, sizeof(char)); */
data->value = value;
struct two_values dest;
/* next instead of memcpy(&dest, data, sizeof(struct two_values)); */
dest = *data;
printf("some = %d, value = %c\n", dest.some, dest.value);
return 0;
}
You'll avoid all compiler alignment issues. It is always possible to do it with the language operators & (address of) and * (points to) or -> (field of struct pointed to).
Anyway, if you prefer the memcpy approach (no idea of why, but you are on your way, anyway) you can substitute:
data->some = some;
...
data->value = value;
...
dest = *data;
by
memcpy(&data->some, &some, sizeof data->some);
...
memcpy(&data->value, &value, sizeof data->value);
...
memcpy(&dest, data, sizeof dest);
And that will take internally the alignments that the compiler could make by itself.
All compilers have defined some pragma, or keyword, to control alignment. This is also nonportable, as you can switch compilers and get to the issue of having to change the way you expressed things. C11 has some standard means to control for packed structs and use no alignment in the compiler. This is done mainly when you have to serialize some structure and don't want to deal with holes on it. Look at the C11 specs for that.
Serializing structs is not completely solved by just making them packed, as normally you have to deal with the serialized representations of integer, floating point or char data (which can or cannot coincide with the internal representation used by the compiler) so you again face the problem of being compiler agnostic and have to think twice before using externally the internal representation of data.
My recomendation anyway, is never trust how the compiler stores data internally.
The padding is determined by the compiler. The order is guaranteed. If you need something similar to your code above, I would recommend the offsetof-macro in <stddef.h>.
memcpy(data + offsetof(struct two_values, value), &value, sizeof(char));
Or without explicitly adding the offset at all:
memcpy(&data->value, &value, sizeof(char));
It depend on how your structure is aligned. You can check by verifying sizeof(two_values), if it comes 5(assuming sizeof int is 4), you probably are ok.
If its more than that it implies filler bytes are inserted in your structure to align each element of your structure at correct byte boundry
May I assume that struct fields are placed in order
Yes, this is guaranteed by the standard. C11 6.2.5/20:
a structure is a type consisting of a sequence of members, whose
storage is allocated in an ordered sequence
and with no padding?
No, you cannot assume this. C11 6.7.1/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. /--/
There may be unnamed padding within a structure object, but not at its beginning.
Padding and alignment are implementation-defined behavior.
You are however guaranteed that two structs of the same type have the same padding. Copying from a struct to another struct of same type, as in your example, is safe and well-defined.
Consider the following code fragment:
struct data_t {
int data1;
int data2;
struct data_t *next;
size_t size;
int data3;
int data4;
};
int *ptr;
struct data_t data;
...
ptr = &data.data4;
Now using pointer, which is set to point to the last element in the structure, how can one use that pointer to access the first element in the structure (data1)?
Normally, what I would do in this case is back up the pointer by so many words to point to that element, but there is a problem. The pointer variable next in the middle of the structure has a varying size depending on the platform. If this is running on a 32-bit platform, then the pointer is 4 bytes while on a 64-bit platform, the pointer takes up 8 bytes. A similar issue happens with the size_t datatype as well.
Although not clear in the example, the structure is the header to a block of memory that is variable in size and is part of a linked list. AKA a free list in a memory allocator. Other than using some kind of an initialization that calculates the size of the pointer itself, is there a portable way of getting the address of the first element of the structure?
You can use offsetof to know how far a member is from the start of the structure. In this case:
struct data_t *p = (struct data_t *)( (char *)ptr - offsetof(struct data_t, data4) );
Obviously this requires you to know that the pointer is pointing at a data4 already, there's no way to autodetect that or anything. And, of course, it would be preferable to use a code design where you pass around the struct data * in the first place.
So I have one struct and I initialized a variable A with that struct data type then Ι put in some values. But now Ι need to take those values and put it into another variable B with the same struct data type. How can Ι achieve this?
struct s_Especialidade{
int id;
char nome[60];
char descricao[60];
struct s_Especialidade *proximo;
};
typedef struct s_Especialidade Especialidade;
PESPECIALIDADE p, *array;
p->nome = &array[i]->nome; //THIS LINE GIVES THE ERROR
Since it is an array of characters, you need to copy each element of the array.
strcpy(p->nome, array[i]->nome) will do it, but for extra security look at strncpy where you can set a maximum length to avoid overruns.
Try that way :
memcpy( p->nome, array[i].nome, 60 * sizeof(char) );
Or generalizing the type as well, picking the type used in the p->nome array :
memcpy( p->nome, array[i].nome, 60 * sizeof(*(p->nome)) );
This is the generalized and secure way to copy an array into another (not only for strings).
To extend the answer recommending strcpy() I'd use memcpy() and use a #defined length to make sure you always use the same value.
#define NOME_LENGTH 60
struct s_Especialidade{
int id;
char nome[NOME_LENGTH];
char descricao[60];
struct s_Especialidade *proximo;
};
typedef struct s_Especialidade Especialidade;
PESPECIALIDADE p, *array;
memcpy(p->nome, array[i]->nome, NOME_LENGTH);
Things get even more complicated trying to consider what an assignment does, but, in an example program:
struct stuff {
char buf[2];
};
int main() {
struct stuff a;
memcpy(a.buf, "aa", 2); // *Edit: "aa" is a bad example as it
// actually becomes at compilation 3 bytes long
// {'a','a','\0'} as noted in the comments
struct stuff b;
b.buf = a.buf; // *Edit: For illustrative purposes, an assignment
// between two char[2] members is not correct and
// does not compile.
}
Compilation yeilds the error error: incompatible types when assigning to type ‘char[2]’ from type ‘char *’ for the b.buf = a.buf line.
The topic of pointers and arrays has been covered elsewhere, Is an array name a pointer? among others.
*Edit: As noted in the comments, in the above code if instead of b.buf = a.buf; the struct assignemnt b = a; were done, the internal members would be copied correctly. This is because struct to struct assignment is effectively memcpy(&b, &a, sizeof(b)); (Assign one struct to another in C)