Using struct pointers in C even if they are not declared - c

#include <stdlib.h>
struct timer_list
{
};
int main(int argc, char *argv[])
{
struct foo *t = (struct foo*) malloc(sizeof(struct timer_list));
free(t);
return 0;
}
Why the above segment of code compiles (in gcc) and works without problem while I have not defined the foo struct?

because in your code snippet above, the compiler doesn't need to know the size of struct foo, just the size of a pointer to struct foo, which is independent of the actual definition of the structure.
Now, if you had written:
struct foo *t = malloc(sizeof(struct foo));
That would be a different story, since now the compiler needs to know how much memory to allocate.
Additionally, if you at an point you try to access a member of a struct foo* (or dereference a pointer to a foo):
((struct foo*)t)->x = 3;
The compiler would also complain, since at this point it needs to know the offset into the structure of x.
As an aside, this property is useful to implement an Opaque Pointer.

"And what about free(t)? Can the compiler free the memory without knowing the real size of the struct?"
No, compiler doesn't free anything. Free() is just a function with input parameter void *.

Related

Creating an Instance of a struct

I have this struct
struct FluxCapacitor{
unsigned char* c_string;
unsigned int value;
};
Now I need to create an instance of this struct. I googled this problem and found that I have to use something like this
typedef struct FluxCapacitor{
unsigned char* c_string
unsigned int value;
};
But I dont really understand the next step with malloc(). Can someone explain it to me?
You do not need malloc() to create an instance of a struct. And I would recommend that you avoid typedefing structures merely to reduce keystrokes. The extra keystrokes would only be saved in declarations and function prototypes (and maybe if you need to cast something), since you don't need the struct keyword elsewhere; the advantage is that when you see struct FluxCapacitor, you know exactly what it is. If you only see FluxCapacitor alone, you don't know if it is a typedef for a struct, or a union, or an integer type or what.
Note that the posted code was missing the semicolon at the end of the declaration. Also, it is unclear why you have unsigned char* c_string;. This may not allow assignment to a string literal. I have changed this in the code below. You can create a single struct like this:
struct FluxCapacitor
{
char *c_string;
unsigned int value;
};
...
struct FluxCapacitor fcap_1;
You can then assign values to the fields of fcap_1:
fcap_1.c_string = "McFly";
fcap_1.value = 42;
Note that you could also use designated initializers at the point of declaration:
struct FluxCapacitor fcap_2 = { .c_string = "Biff",
.value = 1985
};
If you need an array of FluxCapacitor structures, just declare one:
struct FluxCapacitor fcaps[2];
You can assign to the fields of each array member in a loop:
struct FluxCapacitor fcaps[2];
char *somestrings[] = { "McFly", "Biff" };
unsigned somevalues[] = { 42, 1985 };
for (size_t i = 0; i < 2; i++) {
fcaps[i].c_string = somestrings[i];
fcaps[i].value = somevalues[i];
}
Alternatively, you can use designated initializers here too:
struct FluxCapacitor fcaps[2] = { { .c_string = "McFly", .value = 42 },
{ .c_string = "Biff", .value = 1985}
};
Using malloc()
Since OP seems determined to use malloc(), it would be good to first recall that memory allocated with malloc() must later be deallocated with free(). Also note that malloc() can fail to allocate memory, returning a null pointer. Thus the result of a call to malloc() must be checked before attempting to dereference this pointer. The additional complexity should be avoided in favor of the above approaches unless OP has good reason to do manual allocation.
In the code below, the function create_flux_cap() takes a string and an unsigned int as arguments, and returns a pointer to a newly allocated FluxCapacitor structure with the arguments assigned to the appropriate fields. Note that since the FluxCapacitor structure is accessed through a pointer, the arrow operator is used instead of the dot operator.
Inside the function, the return value from the call to malloc() is checked before attempting assignment. If the allocation has failed, no assignment is made and a null pointer is returned to the calling function. Note that in the call to malloc(), the result is not cast, since there is no need for this in C and it needlessly clutters the code. Also observe that an identifier is used instead of an explicit type with the sizeof operator. This is less error-prone, easier to maintain if types change in the future, and is much cleaner code. That is, instead of this:
new_fcap = (struct FluxCapacitor *)malloc(sizeof (struct FluxCapacitor));
use this:
new_fcap = malloc(sizeof *new_fcap);
In main(), the return values from the calls to create_flux_cap() are checked. If an allocation has failed, the program exits with an error message.
The stdlib.h header file has been included for the function prototypes of malloc() and exit(), and also for the macro EXIT_FAILURE.
#include <stdio.h>
#include <stdlib.h>
struct FluxCapacitor
{
char* c_string;
unsigned value;
};
struct FluxCapacitor * create_flux_cap(char *, unsigned);
int main(void)
{
struct FluxCapacitor *fcap_1 = create_flux_cap("McFly", 42);
struct FluxCapacitor *fcap_2 = create_flux_cap("Biff", 1985);
/* Check for allocation errors */
if (fcap_1 == NULL || fcap_2 == NULL) {
fprintf(stderr, "Unable to create FluxCapacitor\n");
exit(EXIT_FAILURE);
}
/* Display contents of structures */
printf("%s, %u\n", fcap_1->c_string, fcap_1->value);
printf("%s, %u\n", fcap_2->c_string, fcap_2->value);
/* Free allocated memory */
free(fcap_1);
free(fcap_2);
return 0;
}
struct FluxCapacitor * create_flux_cap(char *str, unsigned val)
{
struct FluxCapacitor *new_fcap;
new_fcap = malloc(sizeof *new_fcap);
if (new_fcap != NULL) {
new_fcap->c_string = str;
new_fcap->value = val;
}
return new_fcap;
}
You need malloc for dynamic allocation of memory.In your case, both the types char and int are known to the compiler, it means the compiler can know the exact memory requirement at compile time.
For e.g. you can create a struct object like in the main function
#include<stdio.h>
#include<stdlib.h>
struct FluxCapacitor{
unsigned char* c_string;
unsigned int value;
};
int main() {
FluxCapacitor x;
x.c_string = "This is x capacitor"
x.value = 10
}
The x is of value type. You can make a copy and pass around this value. Also, observe we are using . notation to access its member variables.
But this doesn't happen at all time. We are not aware of future FluxCapacitor requirement and so above program will need more memory as while it is running and by using the malloc we can ask the compiler to provide us requested memory. This is a good place to use malloc, what malloc does is, it returns us a pointer to a piece of memory of the requested size. It is dynamic memory allocation.
Here's a simple example: let suppose if you need struct declaration of FluxCapacitor but don't know how many you will need, then use malloc
#include<stdio.h>
#include<stdlib.h>
typedef struct FluxCapacitor {
unsigned char* c_string;
int value;;
} flux;
// typedef is used to have the alias for the struct FluxCapacitor as flux
int main() {
flux *a = malloc(sizeof(flux)); // piece of memory requested
a -> c_string = "Hello World"; // Pointer notation
a -> value = 5;
free(a); // you need to handle freeing of memory
return 0;
}
.

what's the correct way to malloc struct pointer using sizeof?

Imagine I've the following struct
struct Memory {
int type;
int prot;
};
typedef struct Memory *Memory;
How would I initialise it using malloc()?
Memory mem = malloc(sizeof(Memory));
or
Memory mem = malloc(sizeof(struct Memory));
What is the correct way to allocate that?
Your struct declaration is a bit muddled up, and the typedef is wrong on many levels. Here's what I'd suggest:
//typedef + decl in one
typedef struct _memory {
int type;
int prot;
} Memory;
Then allocate like so:
Memory *mem = malloc(sizeof *mem);
Read the malloc call like so: "Allocate the amount of memory required to store whatever type mem is pointing to". If you change Memory *mem to Memory **mem, it'll allocate 4 or 8 bytes (depending on the platform), as it now stands it'll probably allocate 8 bytes, depending on the size of int and how the compiler pads the struct check wiki for more details and examples.
Using sizeof *<the-pointer> is generally considered to be the better way of allocating memory, but if you want, you can write:
Memory *mem = malloc(sizeof(Memory));
Memory *mem = malloc(sizeof(struct _memory));
They all do the same thing. Mind you, if you typedef a struct, that's probably because you want to abstract the inner workings of something, and want to write an API of sorts. In that case, you should discourage the use of struct _memory as much as possible, in favour of Memory or *<the-pointer> anyway
If you want to typedef a pointer, then you can write this:
typedef struct _memory {
int type;
int prot;
} *Memory_p;
In which case this:
Memory_p mem = malloc(sizeof *mem);
might seem counter intuitive, but is correct, as is:
Memory_p mem = malloc(sizeof(struct _memory));
But this:
Memory_p mem = malloc(sizeof(Memory_p));
is wrong (it won't allocate the memory required for the struct, but memory to store a pointer to it).
It's a matter of personal preference, perhaps, but I personally find typedefs obscure certain things. In many cases this is for the better (ie FILE*), but once an API starts hiding the fact you're working with pointers, I start to worry a bit. It tends to make code harder to read, debug and document...
Just think about it like this:
int *pointer, stack;
The * operator modifies a variable of a given type, a pointer typedef does both. That's just my opinion, I'm sure there are many programmers that are far more skilled than me who do use pointer typedefs.
Most of the time, though, a pointer typedef is accompanied by custom allocator functions or macro's, so you don't have to write odd-looking statements like Memory_p mem = malloc(sizeof *mem);, but instead you can write ALLOC_MEM_P(mem, 1); which could be defined as:
#define ALLOC_MEM_P(var_name, count) Memory_p var_name = malloc(count * sizeof *var_name)
or something
Both
typedef struct Memory * Memory;
and
Memory mem = malloc (sizeof (Memory));
are wrong. The correct way to do it is :
typedef struct memory
{
int type;
int prot;
} *MEMPTR;
or
struct memory
{
int type;
int prot;
};
typedef struct memory *MEMPTR;
The name of the structure should be different than the name of a pointer to it.
This construction
struct {
int type;
int prot;
} Memory;
defines an object with name Memory that has type of unnamed structure.
Thus the next construction
typedef struct Memory *Memory;
defined 1) a new type struct Memory that has nothing common with the definition above and the name Memory. and 2) another new type name Memory that is pointer to struct Memory.
If the both constructions are present in the same compilation unit then the compiler will issue an error because name Memory (the name of the pointer) in the typedef declaration tries to redeclare the object of the type of the unnamed structure with the same name Memory.
I think you mean the following
typedef struct Memory {
int type;
int prot;
} Memory;
In this case you may use the both records of using malloc like
Memory *mem = malloc( sizeof( Memory ) );
and
struct Memory *mem = malloc( sizeof( struct Memory ) );
or
Memory *mem = malloc( sizeof( struct Memory ) );
or
struct Memory *mem = malloc( sizeof( Memory ) );
because now the two identifiers Memory are in two different name spaces, The first one is used with tag struct and the second is used without tag struct.

Pointer to pointer of struct field in C

I have:
typedef struct
{
int id;
Other_Struct *ptr;
} My_Struct;
Lets say I have the pointer abcd which its type is My_Struct.
How can I get the address of:
abcd->ptr
?
I mean the address of ptr itself (like pointer to pointer) and not the address which is stored in ptr.
Just use the & address of operator, like this
Other_Struct **ptrptr = &(abcd->ptr);
How about this:
&(abcd->ptr)
If I understood correctly, in this scenario you have My_Struct *abcd pointing to an address, and what you want is the address of a field inside this structure (it doesn't matter if this field is a pointer or not). The field is abcd->ptr, so its address you want is &abcd->ptr.
You can easily check this by printing the actual pointer values (the difference between the addresses should give you the offset of ptr inside My_Struct):
struct My_Struct {
int id;
void *ptr;
};
main()
{
struct My_Struct *abcd;
printf("%p %p\n", abcd, &abcd->ptr);
}
Update: If you want your code to be portable, standards-compliant, and past and future proof, you may want to add casts to void * to the printf() arguments, as per #alk's comments below. For correctness, you can also use a standard entry point prototype (int main(void) or int main(int argc, char **argv)) and, of course, include stdio.h to use printf().
The most unambiguous way to do it is thus:
My_Struct *abcd;
Other_Struct **pptr;
pptr = &(abcd->ptr);
I don't know if the parentheses are really necessary, and I don't care, because it's more readable this way anyway.

Allocating memory with an undefined pointer

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));
}

Accessing members in a pointer to a pointer of a struct

Code is as follows:
/* set.h */
struct setElement{
char *element;
setElement *next;
};
typedef struct setElement *Set; //Set is now the equivalent of setElement*
Set a;
setInit(&a);
/* setInit function declaration # setInit.c */
int setInit(Set *a){
(*a)->element = "asdf"; //results in a seg fault
}
Trying to malloc 'a' works, but if I try to access any member within the set 'a' doesn't work. I understand I'm passing a reference of the set from the main() function to setInit, so I believe the pointer contained within setInit is addressing the memory allocated by 'Set a' in the main() function, so a malloc wouldn't be required...
Iunno. Help is appreciated :)
The problem is that you have not allocated the setElement you are trying to assign to. In the main part of the code you are creating a Set, which is just a pointer to a setElement. This pointer is never set to point to anything sensible. I.e. you need something like
Set a = malloc(sizeof(setElement));
Alas, it is unclear where exactly your variables are defined. I assume your main.c is something like
#include "set.h"
Set a;
int main()
{
setInit(&a);
}
If so, your a, which is a pointer by itself, should point to somewhere.
If your framework wants malloc()ed data, you should do
int main()
{
a = malloc(sizeof(*a)); // *a is a struct setElement now, with 2 pointer-sized members.
setInit(&a); // Now seInit should be able to operate on the struct as wanted.
}
As #amaurea has mentioned, you'll need to make use of malloc() for your setElement structure. In addition to this, you need to do the same for the setElement struct's element member. A char* is merely a pointer to a char or char array and will not implicitly allocate anything.
int setInit(Set *a){
(*a)->element = "asdf"; //results in a seg fault
}
Could be re-written
int setInit(Set *a){
(*a)->element = malloc(sizeof("asdf"));
strcpy((*a)->element,"asdf");
}
Which the above could be rewritten to take a second parameter of the actual element contents.

Resources