I have the following struct that is defined in the following way
typedef struct _abcd {
int a;
unsigned long b;
void (*c)(int);
int d;
} abcd_t, *abcd;
Now i have the following code
static abcd foo
int set_size(int size){
foo = malloc(sizeof(abcd) * size);
}
This code for some reason gives me segfault when accessing some of the properties of array members.
But i have noticed that if i change the malloc line to the following - it fixes the issue
foo = malloc(sizeof(foo[0]) * size);
I find it strange as obviously sizeof(foo[0]) = sizeof(abcd)
So what is exactly the difference here?
Thanks
obviously sizeof(foo[0]) = sizeof(abcd)
It is not the same since you typedefed abcd to be a *pointer* to struct _abcd.
Use
foo = malloc(sizeof(*foo) * size);
to have robust code even if the type of foo should change at some point.
Your
foo = malloc(sizeof(foo[0]) * size);
is essentially the same since foo[0] is just syntactic sugar for *(foo + 0) which becomes *foo.
The bug is you're allocating sizeof(abcd) and that's a pointer, not a struct. You want sizeof(abcd_t) or sizeof(*abcd).
Related
When I declare structure given below, it is throwing compilation error.
typedef struct{
const char x; //it is throwing compilation error
const char y;
}A;
void main()
{
A *a1;
a1 = (A*)malloc(2);
}
How can I make structure's field (characters x and y) as constant?
That should be fine, but of course you can't assign to them, only use initialization.
So it doesn't make a lot of sense to allocate an instance on the heap.
This works:
#include <stdio.h>
int main(void) {
typedef struct {
const int x, y;
} A;
A my_a = { 12, 13 };
printf("x=%d\ny=%d\n", my_a.x, my_a.y);
return 0;
}
It prints:
x=12
y=13
Also, please don't cast the return value of malloc() in C.
First, you should use malloc to allocate the size of the struct, not a magic number 2. Also, don't cast malloc return value, it is automatically promoted to the compatible pointer type.
a1 = malloc(sizeof(A));
Second, there isn't really not much use to make struct member const.
A *a1;
a1 = malloc(sizeof(A));
a1's members are not initialized to any state here, yet the compiler forbidden any assignments to them, since it is defined as const, so a1->x = 'a'; won't compile.
A a2;
a2->x = 'a'; // won't compile too
The only valid use case is:
A a3 = {'a', 'b'};
You can't.
With POO in C you can disable the modification of those fields, if you:
define getters: char A_get_x(A *p); and char A_get_y(A *p);
define the struct in the .c to hide its implementation
only write typedef struct A A; in the .h file, to allow to use that type.
define a constructor : A *A_new(); which returns A with the values desired on x and y.
By doing this, you can only modify the values in the constructor, and after the object is created the values wont change (if you dont force the values with pointers etc..)
I have a struct defined like this:
typedef struct
{
int num;
char letter;
}* Foo;
And an array like this:
Foo* items = malloc(sizeof(Foo) * 4);
From my understanding and from the (accepted) answer to this question Dynamic array of pointers to structs, I would expect the above line to only reserve the memory for 4 Foo items, but doesn't initialize it - i.e., if I try to access items[i]->num, I should get some kind of error.
Also, in order to insert item into this array, I should do this:
items[0] = malloc(sizeof(*items[0]));
However, I did a little test, and seems like the following code prints 1 and a just fine:
Foo* items = malloc(sizeof(Foo) * 2);
items[0]->num = 4;
items[0]->letter = 'a';
printf("items[0] = {num=%d, char=%c}\n", items[0]->num, items[0]->letter);
I'm confused. Is this the expected behavior?
Your initial malloc:
Foo* items = malloc(sizeof(Foo) * 4);
Is creating an array of 4 pointers, since Foo is a pointer type. So your second malloc:
items[0] = malloc(sizeof(*items[0]));
Makes sense, since you're allocating a struct to that pointer.
However, the assignment you're doing leads to undefined behavior because you didn't do the second malloc and therefore no space has been allocated to items[0] yet. C won't prevent you from writing to a memory location you shouldn't be writing to. And once you do that, anything can happen.
One thing that's a bit confusing here is that you used typedef to define a pointer type. That can lead to a lot of confusion since it's not apparent by looking at the type that it's a pointer. And in this case, because of how you defined Foo, you had an extra layer of pointer indirection you probably don't need.
So if you define your struct like this:
typedef struct
{
int num;
char letter;
} Foo;
Then this can be done safely:
Foo* items = malloc(sizeof(Foo) * 2);
items[0].num = 4;
items[0].letter = 'a';
printf("items[0] = {num=%d, char=%c}\n", items[0].num, items[0].letter);
Now the malloc creates an array of structs instead of an array of pointers to structs, so an additional layer of mallocs is no longer necessary.
You have to allocate structs and save its pointer to items's elements if you want to use structs. Otherwise, the item's elements are junk and access to it may cause errors.
The second test may worked fine due to the optimization which removes malloc and pass the values of items[0]->num and items[0]->letter directly to printf.
This is happening because you have reserved enough space for the Foo array and probably one element but it's not the expected behavior, there is no expected behavior in this case because what you do invokes undefined behavior.
This will fail if you add more fields to the struct, because then 2 * sizeof(void *) will not be enough. To test it, try adding 2 pointers to the struct like this1
typedef struct
{
int num;
char letter;
void *pointers[2];
} *Foo;
If you want you can do it right, and this is another reason not to typedef a pointer, this would work
typedef struct
{
int num;
char letter;
void *pointers[2];
} Foo;
Foo *foo_pointer = malloc(N * sizeof(Foo));
/* ^ this would be wrong if `Foo' were a pointer */
if (foo_pointer == NULL)
please_abort_this_do_not_continue_because_malloc_has_failed();
foo_pointer[0].num = 1;
foo_pointer[0].letter = 'a';
1It really annoys me to write this, because typedefing a pointer is never a good idea
I just wanted to know if the following works. I have a struct
called foo that is defined as the following:
struct foo {
char name[255];
int amount;
};
During runtime, I need to create an array of the above structures whose size is dependent on a value I receive from a file's input. Let's say this size is k. Will the following code appropriately allocate a dynamically-sized array of structures?
struct foo *fooarray;
fooarray = malloc(k * sizeof(struct foo));
EDIT: If I want to access members of the structures within these arrays, will I use the format fooarray[someindex].member?
That will work (and your accessing is correct). Also, you can guard against size errors by using the idiom:
fooarray = malloc(k * sizeof *fooarray);
Consider using calloc if it would be nice for your items to start out with zero amounts and blank strings, instead of garbage.
However, this is not a VLA. It's a dynamically-allocated array. A VLA would be:
struct foo fooarray[k];
Yes it will.
On failure it will return 0.
And you have to free the memory returned by malloc when you are done with it
You can access the first member:
fooarray[0].name
fooarray[0].amount
The second as:
fooarray[1].name
fooarray[1].amount
etc..
One more different notation can be used in this approach:
struct foo {
char name[255];
int amount;
};
int main (void)
{
struct foo *fooarray;
struct foo *fooptr[5];
unsigned int i = 0;
for (i = 0; i < 5; i++)
fooptr[i] = malloc(1* sizeof(struct foo));
fooptr[2]->name[3] = 'A';
printf ("\nfooptr[2]->name[3]=%c\n",fooptr[2]->name[3]);
}
I have the following code:
include <stdlib.h>
typedef struct foo{
int x;
}Foo;
void funcY(Foo *f1)
{
printf("%d", f1.x);
}
void funcX(Foo *f1)
{
printf("%d", f1.x);
funcY(f1); <---- is this correct?
}
int main()
{
Foo *foo1 = (struct foo *)malloc(sizeof(struct foo));
foo1.x = 10;
funcX(foo1);
return 0;
}
I don't know exactly how to label this problem. What is the best way for me to approach this?
funcY(f1); <---- is this correct?
Yes, this particular line is correct. However, several other parts that aren't: specifically, accessing struct members by pointer needs -> operator, rather than a dot:
printf("%d", f1->x);
Another small issue is that one should not cast malloc in C:
Foo *foo1 = malloc(sizeof(struct foo));
Finally, you are missing a call to free(foo) to deallocate malloc-ed memory. Note that you do not have to use malloc - allocate the struct in the automatic store, and use & to access its address:
int main()
{
Foo foo1;
foo1.x = 10;
funcX(&foo1);
return 0;
}
funcY(f1) is correct - it passes the Foo pointer to funcY, and since funcY accepts a Foo pointer we can assume it'll work as intended.
printf("%d", f1.x);, however, is not correct. f1 is a Foo pointer, not a Foo. To access it's x field you need to derefer it first - (*f1).x - or use the sytactic sugar f1->x.
I was surprised when gcc -Wall compiled this without warning. Is this really legitimate C? What are the risks of writing code like this?
#include <stdio.h>
#include <stdlib.h>
typedef struct {
int a;
int b;
} MyStruct;
int main(void) {
MyStruct *s = malloc(sizeof(*s)); // as opposed to malloc(sizeof(MyStruct))
s->a = 5;
printf("%d\n", s->a);
}
Not only it's legitimate, it's even preferable to the alternative. This way you let the compiler deduce the actual type instead of doing it manually.
sizeof is evaluated at compile time. In this context, *s resolves to the type of *s, it does not dereference the pointer.
This is the canonical way of using sizeof. If you used sizeof(int) you leave an opening for an error should the type change (in this case, probably unlikely, but still.)
Writing
MyStruct *s = malloc(sizeof(*s));
has exactly the same effect as
MyStruct *s = malloc(sizeof(MyStruct));
except that now you only write MyStruct once. That is, the object you're allocating has its source type determined automatically, which reduces the chances of errors.
For example - it has happened to me - you start with a MyStruct. Then you decide you need also a different MyStruct for different purposes. So you end up with two different structures, MyStruct and AnotherStruct.
Then you refactor your code and change some variables from MyStruct to AnotherStruct, and end up with
AnotherStruct *s = malloc(sizeof(MyStruct));
which might actually work in several circumstances, or for a long time, until you make another little and, at that point, completely unrelated change in either structure. At that point your code goes kaboom.
E.g.
typedef struct {
int a;
int b;
} StructA;
typedef struct {
int a;
int b;
int c;
} StructB;
int main() {
// No problem here except wasted space
StructA *s = malloc(sizeof(StructB));
// t->c dwells in undefined country
StructB *t = malloc(sizeof(StructA));
}