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.
Related
I've seen many topics about typecasting integers into void * but I still have trouble understanding why it works without casting them, and why solving these warnings are so time-consuming, at least the way I see it.
I tried to make this topic as small as possible but trying to explain everything, but I think explaining the steps I did, how I was trying to do it, etc.. is much easier for people to understand my issue.
I'm working with linked lists and my structure is :
typedef struct list_t {
struct list_t *prev;
void *data;
struct list_t *next;
}list_s;
In the beginning, I simply set the data type as an integer, because I would always use integers in my program. My only problem was if I wanted to set the data value to NULL to check if there was something in my linked list (if I already used it once).
Some people would say "just set it to zero" but I could have a zero-value in my list, so there could be an error at some point.
I thought about just setting a variable such as "has_list_been_already_used" or something like that but I think that it would just make my code way bigger just for nothing.
My first thought after having this warning :
warning: assignment to ‘void *’ from ‘int’ makes pointer from integer without a cast
was: "oh I'll just cast it to void * like (void*)my_atoi(datastring); and that's it.
but I got another warning :
warning: cast to pointer from integer of different size
At this point, I didn't know what to do and didn't really find any issue to typecast this way. On the other hand, I've found another way of doing it, but I wonder if this is the right thing to do and if there is another way that doesn't lead to modifying almost all of my code and expanding it. Let me explain :
Someone said that you could just cast integers to void * this way :
int x = 10;
void *pointer = &x;
and retrieving it in the code such as :
int y = *((int *) pointer);
In my code, everywhere I would be retrieving my data from my structure, I will always have to do it this way.
Is that really the only option I got? And why just type-casting it from an integer to a void* doesn't do the job, especially if it "works well", but indeed, have warnings.
Thanks.
Typecasting pointer usually doesn't do anything internally. It however tells your compiler that is is to treat the pointer as a typed pointer.
So a pointer is literally that. It points to a place in memory. And what type of object is stored at that place is not always known. You can tell your compiler that it is an integer by casting: (int* iptr = (int*) voidptr)
Now your compiler will read the memory location pointed to by the pointer as if it was an integer. If it was not an integer, you will get garbled data.
Now this example:
int x = 10;
void *pointer = &x;
This is ok, because you say "make a pointer (to anything) form this pointer to an int" Which is ok, because a pointer to an int always points to anything.
But if you do it the other ways you have to explicitly say that you are sure there is an int stored there, because the compiler doesn't know.
If you want, you can just make a linkedlist of integers. Then you don't even need to use pointers. Just put the integer in the struct instead of the void*.
The reason this linkedlist structure is written this way, is that it allows for any type of data, or data structure to be used. This is why they added stuff like templating in c++. ( But we are talking c now)
The proper c way to do it would probably be to make a macro like
#define declare_LL_type(type) ...
Which would make a custom typed linkedlist struct definition.
I am trying to access the members in the struct tCAN_MESSAGE. What I think would work is like the first example in main, i.e. some_ptr->canMessage_ptr->value = 10;. But I have some code that someone else have written and what I can see is that that person have used some_ptr->canMessage_ptr[i].value;.
Is it possible to do it the first way? We are using pointers to structs which contains pointer to another struct (like the example below) quite often, but I never see the use of ptr1->ptr2->value?
typedef struct
{
int value1;
int value2;
int value3;
float value4;
}tCAN_MESSAGE;
typedef struct
{
tCAN_MESSAGE *canMessage_ptr;
}tSOMETHING;
int main(void)
{
tCAN_MESSATE var_canMessage;
tSOMETHING var_something;
tSOMETHING *some_ptr = &var_something;
some_ptr->canMessage_ptr = &var_canMessage;
some_ptr->canMessage_ptr->value1 = 10; //is this valid?
//I have some code that are doing this, ant iterating trough it with a for:
some_ptr->canMessage_ptr[i].value1; //Is this valid?
return 0
}
It's very simple: every pointer has to be set to point at a valid memory location before use. If it isn't, you can't use it. You cannot "store data inside pointers". See this:
Crash or "segmentation fault" when data is copied/scanned/read to an uninitialized pointer
None of your code is valid. some_ptr isn't set to point anywhere, so it cannot be accessed, nor can its members. Similarly, some_ptr->canMessage_ptr isn't set to point anywhere either.
I am trying to access the members in the struct tCAN_MESSAGE. What I
think would work is like the first example in main, i.e.
some_ptr->canMessage_ptr->value = 10;. But I have some code that
someone else have written and what I can see is that that person have
used some_ptr->canMessage_ptr[i].value;. Is it possible to do it the
first way?
The expression
some_ptr->canMessage_ptr[i].value
is 100% equivalent to
(*(some_ptr->canMessage_ptr + i)).value
, which in turn is 100% equivalent to
(some_ptr->canMessage_ptr + i)->value
. When i is 0, that is of course equivalent to
some_ptr->canMessage_ptr->value
So yes, it is possible to use some_ptr->canMessage_ptr->value as long as the index in question is 0. If the index is always 0 then chaining arrow operators as you suggest is good style. Otherwise, the mixture of arrow and indexing operators that you see in practice would be my style recommendation.
We are using pointers to structs wich contains pointer to
another struct (like the example below) quite often, but I never see
the use of ptr1->ptr2->value ?
I'm inclined to suspect that you do not fully understand what you're working with. Usage of the form some_ptr->canMessage_ptr[i].value suggests that your tSOMETHING type contains a pointer to the first element of an array of possibly many tCAN_MESSAGEs, which is a subtle but important distinction to make. In that case, yes, as shown above, you can chain arrow operators to access the first element of such an array (at index 0). However, the cleanest syntax for accessing other elements of that array is to use the indexing operator, and it pays to be consistent.
Suppose I am given a (void*) ptr (my basic understanding is, it represents a pointer to a region of unknown data type) passed through the parameter of a function. I am trying to figure out how to access and check if a struct exists a few addresses behind.
To clarify, I am working with a big char array (not malloced) and the ptr passed into the function should point to an address of an unspecified data type within the array. Located before this data is a struct for which I am trying to access.
void function(void *ptr)
{
void *structPtr = (void*)((void*)ptr - sizeof(struct block));
}
Would this work to get me a pointer to the address of the struct located behind the initial "ptr"? And if so, how could I check if it is the block struct?
Apologizes in advance, I know this code is not specific as I am fairly new to the concepts entirely but also, I am in the process of coming up with an algorithm and not yet implementing it. Any references to possibly useful information are much appreciated.
what you are trying to do is risky as you must be sure that you address a correct place in memory. Usually, we add some magic number in struct block so that we can test here that we are not going anywhere.
This pattern is generally used in memory allocators,
have a look to https://sourceware.org/glibc/wiki/MallocInternals for an example.
The usual way of writing this is something like:
...function(void *ptr) {
struct block *hdr = (struct block *)ptr - 1;
relying on pointer arithmetic automatically scaling by the size of the pointed at type. As long as all the pointers passed in here were originally created by taking a pointer to a valid struct block and adding 1 to it (to get the memory after it), you should be fine.
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.
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.