I have to add a piece of code to a big code that already exists.
I have a pointer in my code, *Ptr. This pointer is of type, unsigned char.
unsigned char *Ptr;
And I have the below struct.
struct
{
uint8_t tag;
uint16_t data[size];
bool status;
}Test;
Test *TagData;
The pointer is typecasted as below and Now the struct pointer is pointing to the location pointed by the pointer Ptr;
TagData = (Test *)Ptr;
In my code, I will be copying some output values to this structure so that those values get copied to the memory location pointed by *Ptr.
In order to copy some values to the data array in the structure, I need to find the offset to that struct member. I want to do it without using offsetof function. I tried doing the below and I get compiler error.
TagData->data = (uint16_t *) (Ptr + sizeof(TagData->tag));
Can anyone tell how to do this ? And I don't want to use the offsetof function. Is there a simpler way to do this?
No, there's no simpler method than using offsetof, which was designed to do what you need.
Also, offsetof is not a function, but a macro, hiding the pointer arithmetic that you'd do if you didn't use offsetof.
So, clear answer: Since you don't even give a reason, it can't be an overly good reason. Get over it and use offsetof.
Related
I am building a hash library, this library works with different structs and all those structs haves an unsigned type as first member, an example:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct data {
unsigned hash;
void (*func)(struct data *);
};
struct another_data {unsigned hash; int value;};
static void *hash_insert(const char *text, size_t size)
{
unsigned *hash;
hash = malloc(size);
// *hash = hash(text);
*hash = (unsigned)strlen(text);
return hash;
}
static void func(struct data *data)
{
printf("%u\n", data->hash);
}
int main(void)
{
struct data *data;
data = hash_insert("Some text", sizeof *data);
data->func = func;
data->func(data);
free(data);
return 0;
}
Since the first member of the struct and the struct itself haves the same alignment requirements, is it valid to call malloc with a pointer of the type of the first member in order to reserve space for the entire struct?
unsigned *hash = malloc(size); /* where size is the size of the struct */
EDIT:
In this related question provided by #MohitJain:
struct Msg
{
unsigned int a;
unsigned int b;
};
...
uint32_t* buff = malloc(sizeof(Msg));
// Alias that buffer through message
Msg* msg = (Msg*)(buff);
The strict aliasing rule makes this setup illegal
But in my case I am returning a void * from the function, I can use this (returned) pointer inside main without alignment issues, is this assumption correct?
The rules about effective type and pointer aliasing say that it is fine to convert pointers between a struct (or any other "aggregate") and a pointer of the same type as the first appearing member in the struct. And another rule says that structs are not allowed to have padding in the very beginning.
So it is fine as far as the C standard goes... which doesn't really say much of the quality of the program.
The code does not make much sense. You clearly want to use the whole struct, so why not return a pointer of the struct type? Don't complicate things for the sake of it. You should always avoid using void* when there is no need for it, to increase type safety.
Overall, all these things would sort themselves out in a multi-file project with proper program design. If you had a separate file with the hash type and all functions using that type, there would be no doubt of how to write the program.
malloc is guaranteed to return memory aligned for any type.
Therefore it will work regardless of the alignment requirement of the different subtypes.
Since structure member are allocated in the order they are declared, using
unsigned *hash = malloc(size); /* where size is the size of the struct */
can work if your pourpose is just using the hash data.
It fails if you want to apply pointer aritmetic on it, so in this case using
hash++
is an undefined behavior.
Yes it is perfectly fine for first member type to point to the memory returned by malloc (Memory is aligned for any data type). What you do with this memory later may cause issues if you are not careful.
[Extracts from Joachim Pileborg's answer # Maintaining an array of pointers in C that points to two related types with minor changes]
Having a structure inside other structures or a common data type in other structures is a common way of emulating inheritance in C. This common member should contain the minimal set of data common to all structures in the "inheritance" hierarchy, and it must always be the first member in the inheriting structures.
Possible issue with this scheme is:
This "inheritance" scheme will work on all modern PC-like systems and their compilers, and have done so for a long time, but there's no guarantee that it will work on all systems and all compilers (if you're planning on porting the code to some rare system with weird hardware and compiler you might want to look out, but the cases where the "inheritance" scheme will not work is very small, and most people will never come in contact with such a system in their entire lifetime.) But once you point the same memory with struct data *, you may fall victime of strict aliasing rule. So you need to be careful there. Further readL What is the strict aliasing rule?
unsigned *hash = malloc(size);
This will create allocate an array of unsigned integers. Total number of integers allocated will be size/sizeof(int). hash here is pointer to int.
Since the first member of the struct and the struct itself haves the same alignment requirements, is it valid to call malloc with a pointer of the type of the first member in order to reserve space for the entire struct?
The point is, that hash here is a separate variable which has nothing to do with the hash inside the structure. (It is in a separate namespace, if you want to look it up)
You can then cast hash to the struct variable.
struct data *data;
unsigned *hash = malloc(size * sizeof(struct));
data = (struct data *) hash;
But, what is the point. You can just as well remove the unnecessary unsigned hash pointer and go with the traditional.
struct data *data;
data = malloc(size * sizeof(struct));
This is my first post here. I tried to find a similar question but couldn't find any and hence I am posting this question.
I am trying to copy the data in a structure pointer to another structure pointer in C as shown below. Looks like using just an '=' did the trick. Could someone please explain how the data in pointer srcStruct got copied to another memory location (pointer by destStruct) without using memcpy()?
Is this a pointer property? or is there any risk in doing this?
struct myTestStruct
{
short variable1;
short variable2;
};
struct myTestStruct *destStruct = (struct myTestStruct *)malloc(sizeof(struct myTestStruct));
struct myTestStruct *srcStruct = (struct myTestStruct *)malloc(sizeof(struct myTestStruct));
srcStruct->variable1 = 11;
srcStruct->variable2 = 12;
*destStruct = *srcStruct;
Thanks in advance.
Regards,
AJK
By using the dereferencing operator *, you are basically treating the data that the pointers point to as regular variables. Structs are copied by value, not by reference, if you aren't copying the pointer, so it's just like copying an int to another int. You are essentially doing the following by using the dereference operator *:
struct myTestStruct destStruct, srcStruct;
srcStruct.variable1 = 11;
destStruct = srcStruct; //this gets copied by value
What you're doing here isn't actually connected to pointers at all; it's a property of structs in general in C that they can be assigned as a whole unit with a single = operation. When you dereference a pointer you're using the pointed-to value directly in the expression, so what you've really got there, with a dereference on both sides, is an assignment from a value struct to another value struct. The pointers have both been "expanded out", leaving the values of the whole structs themselves.
How the value is copied is up to the compiler. It will likely emit custom instructions to do it in the most efficient possible way, but it could also use memcpy if it wanted to. There is absolutely no risk in doing this - structs being assignable is a core element of the C language and not going away! It is perfectly idiomatic, and usually the best way to do whatever you're doing that needs data copied from one struct to another. Certainly better than invoking memcpy unnecessarily.
I have a structure comprised of an array of pointers to other structures of a different type.
typedef struct{
NodeT* nodes[2];
int size;
}stackT;
with:
typedef struct{
char info;
}NodeT;
And I have a pointer to the above (first) structure:
stackT* stackPtr;
Assuming the memory is allocated for the stackT structure as well as both NodeT structures with associated assignments for the members of both NodeT structures, how would I pass to a function one of the pointers in stackT?
For example:
void setChar(NodeT* nodePtr, char setTo){
nodePtr->info = setTo;
}
called with line:
setChar(stackPtr->nodes[0], 'A');
Does not work. I figured it had something to do with the -> syntax dereferencing the pointer whereby I am actually passing in a structure. I do not get any compilation errors, but when I check for the assignment by printing whatever is stored in char info I do not get anything.
Is the notation incorrect or do I have issues elsewhere in the program perhaps? I just wanted to rule this out first (proper passing syntax).
If someone is looking for a solution to this problem, the above code was actually correct.
Assuming you have an array of pointer in some structure and you wish to pass such a pointer, the correct syntax would be:
someFunc( structPtr->ptrArray[0] )
The line:
structPtr->ptrArray[0]
Actually returns a pointer, and not whatever the pointer is pointer to.
(*structPtr).ptrArray[0]
Is also equivalent.
That being said, I either mistakenly interpreted the information before me, or I had underlying errors elsewhere in the my code.
This seems to be a very simple problem but I can't quite figure out which part is causing it. Basically, I have a struct that just contains an array of strings
struct command_stream{
char **tokens;
};
typedef struct command_stream *command_stream_t;
command_stream_t test;
Then later on, I parse some strings into shorter ones and end up with another array of strings
char **words = *array of strings*
words contains the correct information I want, I looped through and printed out each element to make sure I wasn't getting a faulty string. So now I just point tokens to words
test->tokens = words;
But it gives me a segmentation fault. I'm not sure why though. They're both pointers, so unless I'm missing something obvious...
EDIT: The function as a whole has to return a pointer, which is why it was set up like this, which I keep forgetting. But I think I've got it, if I just create a new typedef
typedef struct command_stream command_stream_s;
command_stream_s new_command_stream;
and just return
&new_command_stream;
That should work right? Even though new_command_stream itself isn't a pointer.
From your code excerpt, it seems that you have not declared the struct. You have successfully declared a pointer to the struct command_stream_t test; but this pointer does not point to anywhere yet.
You need to allocate memory for your struct in some way and make test reference it. For instance:
command_stream_t test =
(command_stream_t) malloc(sizeof(struct command_stream));
This way you can successfully use:
test->tokens = words;
as you intended.
Note that you don't need to use malloc to allocate the memory. The pointer can reference a local/global variable as long as it has memory associated to it (N.B. if you use a local var don't use the pointer outside the declaration scope of that var).
typedef struct command_stream *command_stream_t;
command_stream_t test;
This makes "test" a pointer. There is no memory allocated for the structure.
You need to allocate memory for the structure and make the test pointer point to the block of memory before you can dereference by saying -
test->tokens = words;
Do this:
typedef struct command_stream command_stream_t;
command_stream_t test;
test.tokens = words;
The difference is that, command_stream_t is no more a pointer type, it is the actual structure.
I can't seem to understand the difference between the following to pointer notations, can someone please guide me?
typedef struct some_struct struct_name;
struct_name this;
char buf[50];
this = *((some_struct *)(buf));
Now I tried to play around a bit and did the above thing like:
struct some_struct * this;
char buf[50];
this=(struct some_struct *)buf;
As far as I am concerned I think both the implementations should generate the same result, Can someone guide me whether there is a difference between the two and if yes can some one point it out?
Thanks.
In your first snippet, this is not a pointer, it's an instance of some_struct. The assignment you made did a shallow copy (i.e. memcpy()) of what's in buf as if it were an instance of some_struct as well.
In the second snippet, this is a pointer, and it's just pointed to the address of buf.
So, basically to sum up, first snippet this is not a pointer and the struct is copied into it. In the second, it's a pointer and assigned to the same memory as buf (i.e. not a copy).
In the second one, "this" will point to the first memory location of "buf". In the first example, you will either get a compiler error (I don't think you can assign structs in C with =, I could be wrong though), or the contents of buf (up to sizeof(struct_name)) will be copied into this, which resides on the stack.
Both approaches have their problems.
alignment: your buf might not be properly aligned for a variable of the structure type. If so this will produce undefined behavior (UB): in the best case it aborts your program, but it may make much worse things than that.
initialization: in the first cases you access uninitialized memory for reading. In the best case that gives you unspecific data, that is some random bytes. In the worst case, char is a signed integer type on your platform and you hit a trap representation for char => UB as above. (Your second case will encounter the same problem, once you try to access the object at the other end of the pointer.)
How to avoid all that:
Always initialize your variables. A simple = { 0 } should do in all cases.
never use char as a generic type for bytes but use unsigned char
never cast a byte buffer of arbitrary alignment to another data type. If needed, do it the other way round, cast a struct object to unsigned char.