How to set value of struct indirectly in c? - c

I would like to know, how to access first member of struct through pointer. I have tried this:
#include <stdio.h>
#include <stdlib.h>
struct foo
{
int a;
char *str;
};
int main()
{
struct foo *p = malloc(sizeof(struct foo));
int val = 10;
*(int**)p = &val; //set the value of the first member of struct foo
printf("%i\n",p->a);
}
but that print some garbage. How can I set it in similar manner?

What you're doing there is setting the value of p->a to the address of val (possibly truncated to 32 bits, depending on the implementation).
To access the field via a pointer, you have to take the field's address and then assign to the dereferenced pointer.
int *pa = &p->a;
*pa = val;
Of course you can also just write p->a = val. Note that p->a is just an abbreviation for (*p).a.

The assignment should be:
*(int*)p = val;
You want to assign to an int member, so the pointer has to be a pointer to int, not pointer to pointer to int. And the value being assigned must be int; &val is a pointer to int.

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".

What is the difference between ptr->thing and *ptr->thing in C?

My understanding is that the -> operator is shorthand for dereferencing a pointer to a struct, and accessing the value of one struct member.
struct point {
int x;
int y;
};
struct point my_point = { 3, 7 };
struct point *p = &my_point; /* p is a pointer to my_point */
(*p).x = 8; /* set the first member of the struct */
p->x = 8; /* equivalent method to set the first member of the struct */
So the last 2 lines of the example above are equivalent. But I've encountered some code similar to this:
*p->x = 8
Using both the asterisk and arrow together. What does this do? Would this try to "double dereference" the pointer and assign to memory address 8, or something else? Maybe undefined behavior, or just a compiler error?
*p->x is equivalent to *(p->x) - you are dereferencing the result of p->x, which implies the x member itself has pointer type. Given a line like
*p->x = 8;
that implies x has type int *:
struct foo {
...
int *x;
...
};
Note that x must be assigned a valid pointer value before you can assign to *x. You can allocate memory dynamically:
struct foo *p = malloc( sizeof *p ); // dynamically allocate space for 1 instance of struct foo
if ( !p )
// handle allocation failure and exit here.
p->x = malloc( sizeof *p->x ); // dynamically allocate space for 1 int.
if ( !p->x )
// handle allocation failure and exit here.
Or you can set x to point to an existing int object:
int a;
...
p->x = &a;
*p->x = 8;
For a structure
struct tagp
{
int *x=someaddress;
}p0;
struct tagp *p=&p0;
*p->x accesses the address stored in the pointer x inside the structure. It is same as *((*p).x) and *(p0.x) which accesses the memory at Someaddress.
Check this link

How to know struct size casted to void pointer in C?

In my code, there are 2 types that refer a struct:
TypeX and typeX.
TypeX is a void pointer, and typeX is the struct type.
After allocating memory to a typeX variable, I passed it (casted) to a TypeX variable (or a void pointer).
I want to get the size of following struct casted to void pointer:
Code
#include <stdio.h>
#include <stdlib.h>
struct _typeX {
double a;
double b;
};
typedef struct _typeX typeX;
typedef void* TypeX;
int main(int argc, char const *argv[]) {
TypeX t = NULL;
typeX *t0 = NULL;
t0 = (typeX *) calloc(1, sizeof(typeX));
t0->a = 123;
t0->b = 456;
t = (TypeX) t0;
printf("%lu\n", sizeof(*t0));
printf("%lu\n", sizeof(*t));
free(t);
return 0;
}
But struct size and void pointer size are different:
Output
16
1
Is there any way to identify the struct size correctly by passing a void pointer as parameter?
First off, having both typeX and TypeX but with very different meanings is very confusing. Also, don't hide pointers behind typedefs.
As for your question: No, you cannot recover the size of the object that t is pointing to.
sizeof EXPR gives you the size of the type of EXPR (in bytes). It does not matter what the actual value is (in fact, EXPR isn't even evaluated1).
Consider
char c;
int i;
double d[100];
TypeX p1 = (TypeX)&c, p2 = (TypeX)&i, p3 = (TypeX)d;
All of p1, p2, p3 have the same type, so sizeof will return the same value for all of them, even though the objects they're pointing to have very different sizes.
Finally, sizeof (void) is not a thing in standard C. GCC allows it as an extension (and returns 1), but it will warn you that this is non-standard if you enable -pedantic diagnostics.
1 - With one relatively obscure exception, which I'm just going to ignore.

Is it possible to get the size of the item the pointer is pointing at?

Is it possible to find the size of item_t through the pointer?
typedef struct item
{
char x;
char y;
char life;
}item_t;
void main (void)
{
item_t test;
void *ptr = &test;
printf("%d\n",sizeof(ptr));
}
return: 8
Not if ptr is of type void* -- but it probably shouldn't be.
You can't dereference a void* pointer. You can convert it to some other pointer type and dereference the result of the conversion. That can sometimes be useful, but more often you should just define the pointer with the correct type in the first place.
If you want a pointer to an item_t object, use an item_t* pointer:
item_t test;
item_t *ptr = &test;
printf("%zu\n", sizeof(*ptr));
This will give you the size of a single item_t object, because that's the type that ptr points to. If ptr is uninitialized, or is a null pointer, you'll get the same result, because the operand of sizeof is not evaluated (with one exception that doesn't apply here). If ptr was initialized to point to the initial element of an array of item_t objects:
ptr = malloc(42 * sizeof *ptr);
sizeof *ptr will still only give you the size of one of them.
The sizeof operator is (usually) evaluated at compile time. It uses only information that's available to the compiler. No run-time calculation is performed. (The exception is an operand whose type is a variable-length array.)
The correct format for printing a value of type size_t (such as the result of sizeof) is %zu, not %d.
And void main(void) should be int main(void) (unless you have a very good reason to use a non-standard definition -- which you almost certainly don't). If a book told you to define main with a return type of void, get a better book; its author doesn't know C very well.
Short answer: no. Given only ptr, all you have is an address (answer by WhozCraig).
Longer answer: you can implement inheritance by having the first field in all your structs specify its size. For example:
struct something_that_has_size
{
size_t size;
};
struct item
{
size_t size;
char x;
char y;
char life;
};
struct item2
{
size_t size;
char x;
char y;
char z;
char life;
};
// Somewhere in your code
...
struct item *i1 = malloc(sizeof(struct item));
i1->size = sizeof(struct item); // you are telling yourself what the size is
struct item2 *i2 = malloc(sizeof(struct item2));
i2->size = sizeof(struct item2);
// Later in your code
void *ptr = ... // get a pointer somehow
size_t size = ((struct something_that_has_size*)ptr)->size; // here is your size
But instead of size, you should better record the type of your struct - it's more useful than just the size. This technique is called discriminated union.
You can only cast a void pointer to get what is behind in the correct type, you cannot dereference it directly.
#include <stdio.h>
#include <stdlib.h>
typedef struct item {
char x;
char y;
char life;
} item_t;
int main()
{
item_t test;
void *ptr = &test;
printf("%zu %zu\n", sizeof(*(item_t *) ptr), sizeof(item_t));
exit(EXIT_SUCCESS);;
}
But that is of not much use because you need to know the type in the first place and have won nothing.
TL;DR: no, not possible

Change address of struct in C

Let's say that I was given a struct and I need to assign all of it's attributes to a particular address. The code below is giving me a conditional error, but i'm not trying to evaluate it.
struct header block_o_data;
block_o_data.a = 1;
block_o_data.b = 2;
void* startingAddress = sbrk(0);
&block_o_data = *address;
Please let me know what im doing wrong.
In the assignment to block_o_data, you're taking its address and trying to assign a value to it. The address of a variable is not an lvalue, meaning the expression cannot appear on the left side of an assignment.
You need to declare a pointer to a struct, then assign it the address of where the values actually live:
struct header *block_o_data;
void* startingAddress = sbrk(0);
block_o_data = startingAddress;
Suppose you have a struct like this:
struct mystruct {
int a;
char b;
};
then you probably need something like this:
// A pointer variable supposed to point to an instance of the struct
struct mystruct *pointer;
// This is a general address represented by void*
void *addr = some_function(0);
// Cast that general address to a pointer varibale pointing to
// an instance of the struct
pointer = (struct mystruct *) addr;
// Use it!
printf("%d", pointer->a);

Resources