Defining a struct with a pointer - c

I'm relatively new to C and trying to understand structs and pointers. What does the *Building at the end of this struct declaration do?
typedef struct building {
char *floor;
struct building *nextBuilding;
} *Building;
Does it mean that from now on when I do
Building someBuilding = malloc(sizeof(struct building));
somebuilding is a pointer to a building?

Yes, when you write:
typedef struct building { … } *Building;
Building bp;
then bp is a pointer to a struct building. However, it is frequently regarded as bad style to include the pointer in the typedef; code is easier to understand if you use:
typedef struct building { … } Building;
Building *bp;
Now it is clear looking at the definition of bp that the type is a pointer. If you are never going to access the internals of the structure, then it doesn't matter too much (but look at FILE * in <stdio.h>; you always write FILE *fp, etc). If you're going to access the internals:
printf("Floor: %s\n", bp->floor);
then it is better to have the pointer visible. People will be mildly surprised to see Building bp; and then later bp->floor instead of bp.floor.

To answer the question: yes. You now have a type Building that is a pointer to a struct building and you can do this:
Building someBuilding = malloc(sizeof(struct building));
someBuilding->floor = malloc (sizeof(char)*20);
strcpy(someBuilding->floor, "First floor");
someBuilding->nextBuilding = NULL;
etc.
note that this might not be a good idea in all cases. For example if you declare a method:
void setFloorName(Building building, char* name)
you can't really tell that you need to pass a pointer to a building struct, but if you do:
void setFloorName(Building* building, char* name)
you immediately see that the function takes a pointer.

Related

Does it make any sense to make struct immutable?

Since I came to C from higher level Java where we don't have type quialifiers like const in order to make a type immutable we have to declare all its members final and be sure the members are immutable by themselves.
By contract, in C we have type quialifier const.
To be more specific, let me provide an example I'm currently stuck with. I have the following
application.h:
struct application_config_t{
int poll_interval;
int compression_ratio;
//other config parameters
};
struct application_t{ //This structure make me confused
void (*run_application)(struct application_t*);
void (*stop_application)(struct application_t*);
};
struct application_t* create_app(const struct application_config_t);
void release_app(struct application_t*);
I'm not sure about how to define application_t structure. Its only purpose is to do the actaul run with run_application and to handle SIGINT with stop_application to perform graceful shutdown and then after stop_application returns to call release_app(struct application_t*) to free the memory.
I have the following case to choose:
I. Immutable application_t
struct application_t{
void (*const run_application)(struct application_t*);
void (*const stop_application)(struct application_t*);
}
I think this is fine because once created an application should not be modified. But creation of such an immutable structure will entail memcpy call anyway...
II. Mutable application_t while create application will be declared as
const struct application_t* create_app(const struct application_config_t);
This would be fine, but I want to release the memory pointed to by struct application_t* after stop_application returns. Releasing struct application_t* means that appliaction_t is not really const. And usage like
struct application_config_t cfg;
//...
const struct application_t *app_ptr = create_app(cfg);
(app_ptr -> run_application)(app_ptr);
release_app((struct application_t *) app_ptr); //const cast
would require cast against constness.
Releasing struct application_t* means that appliaction is not really const
Actually it is. The client code could not mutate it, and should not be using it further after handing it over to release_app anyway. It is const throughout its lifetime, and if release_app accepts by a pointer to const, it will be semantically correct (just do the cast inside release_app).
Why do I say it will be semantically correct? Because when create_app allocates space for the structure and initializes it, it isn't const in there, is it? The const is added later as part of a contract. So accepting a const pointer in release_app is just following the same contract you already established. The fact the API pair knows the storage can be mutated doesn't break the contract.

Why does this C code treat a local struct as a pointer, when it doesn't appear to be a pointer?

In the following code, "stk" is treated as if it is a pointer. But after looking at it from every angle for hours, I cannot for the life of me see how it is a pointer. Can someone please explain what I'm missing?
struct T {
int count;
struct elem {
void *x;
struct elem *link;
} *head;
};
T Stack_new(void) {
T stk;
NEW(stk);
stk->count = 0;
stk->head = NULL;
return stk;
}
My interpretation says that T is a struct, and therefore stk is a local, automatic variable containing a struct. It is not a pointer, but then it gets treated as a pointer, leaving me stuck in a WTF state.
More Background
This code is from a book called "C Interfaces and Implementations" by Hanson. He creates a library of abstract data types that expose an interface and hide the implementation. The stack is the first one he covers. I'm a long-time programmer just now digging into C, and apparently there's some way of parsing this syntax that I'm missing. Thanks.
In case it is relevant, here is the definition for NEW and the things that new calls:
#define NEW(p) ((p) = ALLOC((long)sizeof *(p)))
#define ALLOC(nbytes) \
Mem_alloc((nbytes), __FILE__, __LINE__)
extern void *Mem_alloc (long nbytes,
const char *file, int line);
In the snippet above, T stk will declare stk as a variable of type T. However type T isn't defined anywhere, and the code won't compile.
If it instead said struct T stk;, it would be declaring stk as a variable having type struct T. However, the attempts to dereference stk would be meaningless and the code would again fail to compile.
To make the example work, you could add something like,
typedef struct T *T
which defines type T to be a pointer to struct T. I would find this highly confusing though.

Is it possible to implement stack with only pointer to structure (no data type)?

Suppose I have the following structure
typedef struct _Stack {
struct _Stack *next;
} Stack;
Note in above there is no data type for storage, only *next pointer to structure. So, my question is will it be possible that the following function is valid.
void stackPush(Stack **stackP, void *dataP) {
Stack *data = (Stack*)dataP;
data->next = *stackP;
*stackP = data;
}
I saw this function in glib library in the file gtrashstack.c. But when I compiled above, I got a warning : In data->next : assignment from incompatible pointer type.
I know that, I can rewrite the structure with generic pointer. But I only want to know, why the above will not work?
Update: My mistake, here I write typedef struct _Stack but in my program, I missed _Stack.
This function is valid. Probably it is used for different structures like:
typedef struct my_Stack {
struct my_Stack *next;
sometype1 somename1;
...
sometypen somenamen;
} MyStack;
i.e. for the lists where the pointer to the next elem is placed as the first field of the structure. It is the same trick as when classes are built via simple inheritance in C++. For such a structure you can call:
x = malloc(sizeof(struct my_Stack));
x->somename1 = aaa; ...
stackPush(&mylist, x);
I am not sure if this style of programming is supported by the C standard. It's not a good style for novices. It is for developers who know what they are doing in C.
The answer is yes, it is possible to implement stack with only pointer to structure (no data type). See implementation of generic list or queue in c in Linux (don't know if it is implemented in windows also). See how it is implemented Linux Kernel Linked List Explained

Modular data structure in C with dynamic data type

For my upcoming university C project, I'm requested to have modular code as C allows it. Basically, I'll have .c file and a corresponding .h file for some data structure, like a linked list, binary tree, hash table, whatever...
Using a linked list as an example, I have this:
typedef struct sLinkedList {
int value;
struct sLinkedList *next;
} List;
But this forces value to be of type int and the user using this linked list library would be forced to directly change the source code of the library. I want to avoid that, I want to avoid the need to change the library, to make the code as modular as possible.
My project may need to use a linked list for a list of integers, or maybe a list of some structure. But I'm not going to duplicate the library files/code and change the code accordingly.
How can I solve this?
Unfortunately, there is no simple way to solve this. The most common, pure C approach to this type of situation is to use a void*, and to copy the value into memory allocated by you into the pointer. This makes usage tricky, though, and is very error prone.
Another alternative no one has mentioned yet can be found in the Linux kernel's list.h generic linked list implementation. The principle is this:
/* generic definition */
struct list {
strict list *next, *prev;
};
// some more code
/* specific version */
struct intlist {
struct list list;
int i;
};
If you make struct intlist* pointers, they can safely be cast (in C) to struct list* pointers, thus allowing you to write genericized functions that operate on struct list* and have them work regardless of datatype.
The list.h implementation uses some macro trickery to support arbitrary placement of the struct list inside your specific list, but I prefer to rely on the struct-cast-to-first-member trick myself. It makes the calling code much easier to read. Granted, it disables "multiple inheritance" (assuming you consider this to be some kind of inheritance) but next(mylist) looks nicer than next(mylist, list). Plus, if you can avoid delving into offsetof hackery, you're probably going to end up in better shape.
Since this is a university project, we can't just give you the answer. Instead, I'd invite you to meditate on two C features: the void pointer (which you've likely encountered before), and the token pasting operator (which you may not have).
You can avoid this by defining value as void* value;. You can assign a pointer to any type of data this way, but the calling code is required to cast and dereference the pointer to the correct type. One way to keep track of this would be to add a short char array to the struct to note the type name.
This problem is precisely the reason why templates were developed for C++. The approach I've used once or twice in C is to have the value field be a void*, and cast the values thereto on insertion and cast them back on retrieval. This is far from type-safe, of course. For extra modularity, I might write insert_int(), get_mystruct() etc. functions for each type you use this for, and do the casting there.
You can use Void* instead of int. This allows the data to be of any type. But the user should be aware of the type of data.
For that, optionally you can have another member which represents Type. which is of enum {INT,CHAR,float...}
Unlike C++ where one can use template, void * is the de-facto C solution.
Also, you can put the elements of the linked list in a separate struct, e.g:
typedef struct sLinkedListElem {
int value; /* or "void * value" */
} ListElem;
typedef struct sLinkedList {
ListElem data;
struct sLinkedList *next;
} List;
so that the elements can be changed without affecting the link-ing code.
Here is an example of linked list utilities in C:
struct Single_List_Node
{
struct Single_List * p_next;
void * p_data;
};
struct Double_List_Node
{
struct Double_List * p_next;
struct Double_List * p_prev; // pointer to previous node
void * p_data;
};
struct Single_List_Data_Type
{
size_t size; // Number of elements in list
struct Single_List_Node * p_first_node;
struct Single_List_Node * p_last_node; // To make appending faster.
};
Some generic functions:
void Single_List_Create(struct Single_List_Data_Type * p_list)
{
if (p_list)
{
p_list->size = 0;
p_list->first_node = 0;
p_list->last_node = p_list->first_node;
}
return;
}
void Single_List_Append(struct Single_List_Data_Type * p_list,
void * p_data)
{
if (p_list)
{
struct Single_List_Node * p_new_node = malloc(sizeof(struct Single_List_Node));
if (p_new_node)
{
p_new_node->p_data = p_data;
p_new_node->p_next = 0;
if (p_list->last_node)
{
p_list->last_node->p_next = p_new_node;
}
else
{
if (p_list->first_node == 0)
{
p_list->first_node = p_new_node;
p_list->last_node = p_new_node;
}
else
{
struct Single_List_Node * p_last_node = 0;
p_last_node = p_list->first_node;
while (p_last_node->p_next)
{
p_last_node = p_last_node->p_next;
}
p_list->last_node->p_next = p_new_node;
p_list->last_node = p_new_node;
}
}
++(p_list->size);
}
}
return;
}
You can put all these functions into a single source file and the function declarations into a header file. This will allow you to use the functions with other programs and not have to recompile all the time. The void * for the pointer to data will allow you to use the list with many different data types.
(The above code comes as-is and has not been tested with any compiler. The responsibility of bug fixing is up to the user of the examples.)

Why often a struct's tagName differs from the typedef's name?

Sometimes I see code like this (I hope I remember it correctly):
typedef struct st {
int a; char b;
} *stp;
While the usual pattern that I familiar with, is:
typedef struct st {
int a; char b;
} st;
So what's the advantage in the first code example?
You probably mean this:
typedef struct ST {
/* fields omitted */
} *STP;
The asterisk is at the end of the statement. This simply means "define the type STP to be a pointer to a struct of this type". The struct tag (ST) is not needed, it's only useful if you want to be able to refer to the struct type by itself, later on.
You could also have both, like so:
typedef struct {
/* fields omitted */
} ST, *STP;
This would make it possible to use ST to refer to the struct type itself, and STP for pointers to ST.
Personally I find it a very bad practice to include the asterisk in typedefs, since it tries to encode something (the fact that the type is a pointer) into the name of the type, when C already provides its own mechanism (the asterisk) to show this. It makes it very confusing and breaks the symmetry of the asterisk, which appears both in declaration and use of pointers.
It's a habit that stems from the time when typedef names and struct tagnames were in the same namespace. See http://blogs.msdn.com/oldnewthing/archive/2008/03/26/8336829.aspx
I think you are talking about :
typedef struct{
int a;
char b;
} object, *objectPointer;
This means that (new) type objectPointer is a pointer to struct (object) defined above. Its easy to declare pointers to object struct this way. For instance,
objectPointer A = (objectPointer)malloc(sizeof(object));
A->a = 2;
Now, A is a pointer to struct object and you can access its variables as described above.
In case, objectPointer was not defined,
struct object *A = (struct object *)malloc(sizeof(object));
A->a = 2;
So, I guess objectPointer is more intuitive and easy to use.
I hope that the first code would say a compiler error ,
I see no good reason for the typedef name be different from the tag name.
Now, the reason for which the tag name needs to be typedefed if you don't want to use
struct tag v;
but
tag v;
is probably an historical one. For as long as I remember, C had typedef but I don't know if it was true when struct have been introduced (handling of typedef is a nuisance in the C grammar). In the old code I've seen, using typedef for struct isn't done, and there are things like unix
struct stat;
int stat(const char*, struct stat*);
which would break with an automatic typedef. One those are introduced, changing is quite difficult (yes, C++ has automatic typedef but C++ has special wording to handle that case of overloading and it would be yet another complication).

Resources