Struct Confusion in C - c

So I was looking through this C tutorial and I found these lines of code:
struct Monster {
Object proto;
int hit_points;
};
typedef struct Monster Monster;
And I thought that it would make much more sense if it were like this:
typedef struct {
Object proto;
int hit_points;
} Monster;
I could could be totally wrong, because I am very new to C, but I would assume both these pieces of code would do the same thing. So is they do, then is there any reason to prefer one over the other? Or if they are different, what makes them different? Thanks!

The first piece of code defines a type struct Monster, and then gives it another name Monster.
The second piece of code defines structure with no tag, and typedef it as Monster.
With either code, you can use Monster as the type. But only in the first code, you can also use struct Monster.

There are times when the second form won't work. Say you want to create a linked list of Monsters. With the first form, you can add a pointer to the next Monster in the struct.
struct Monster {
Object proto;
int hit_points;
struct Monster* next;
};
You can't do that in the second form since the struct doesn't have a name.

The definitions (from the first part of the question - plus my liberal re-formating):
struct Monster
{
Object proto;
int hit_points;
};
typedef struct Monster Monster;
Is equivalent to:
typedef struct Monster
{
Object proto;
int hit_points;
} Monster;
My preference is:
typedef struct MONSTER_S
{
Object proto;
int hit_points;
} MONSTER_T;
FYI... a struct name isn't required. So if the code only needs to use the type, the following is also fine:
typedef struct
{
Object proto;
int hit_points;
} MONSTER_T;

Related

Function to compare structures in order to sort a list

I have an abstract data type in C, LIST OF THINGS, ist node has a void* pointer, what i'm trying to do is create a function to compare an specific field of different structures in order to sort my list of things.
typedef struct node{
char *name;
void *thing;
struct node *next;
}Node;
This is the node i'm working with, i've already created a list of integers, list of structures and te compare function for both, but i can't figure out how to do a compare function to diferent structures. for example:
given these types:
typedef struct main{
float weight;
char*model;
float maxspeed;
}Main;
typedef struct airplane{
float weight;
float maxspeed;
}Airplane;
typedef struct car{
char*model;
float maxspeed;
}Car;
And this is the function, so you have an idea of what i'm trying to do, it doesn't work, Main has fields that doesn't exist in either one or the other structure.
int comparefunction(void*a,void*b){
Main a1, a2;
a1=*(Main*)a;
a2=*(Main*)b;
return a1.weight-a2.weight;
}
This function(doesn't work) is passed as a paremeter to the function that links the nodes in order to use the comparefunction.
//insert prototype:
//insert(Node*listp,Node*newp,int(*func_comp)(void*,void*));
list=insert(list,newItem(&car1),comparefunction);
list=insert(list,newItem(&airplane1),comparefunction);
list=insert(list,newItem(&airplane2),comparefunction);
How can i do to compare a single field of two or more different structures? assuming that i know what each structure contains
If you're trying to compare somewhat similar things, you can look into unions.
struct attributes{
float weight;
// other common things?
};
struct thing {
enum { Car, Main, Airplane } type;
struct attributes attrs;
union {
struct Car car;
struct Main main;
struct Airplane airplane;
} other_thing;
};
You'd change your list to store the thing struct, which is a structure that encapsulates all your possible types. The common elements of each type are extracted to the attributes struct. Your compare function would then operate on the attributes struct of the thing struct. The union is used here to only create enough space within struct thing for the largest of the union elements, so that you're not wasting space storing all three structs and only using one.
Well, your car struct doesn't have a weight field, so I'm not exactly sure what you're trying to accomplish here. If you had your car struct look like
typedef struct car {
float weight;
char* model;
float maxspeed;
} Car;
I think your function would work. Note, it is important that the member that you want to compare is at the same offset into each struct including the Main struct.
EDIT
This does work.
Another edit based on comments
You can't compare two completely unrelated things. This is not a technical deficiency with C. It just does not logically make any sense to compare for example an Airplane and an int.

Handling incomplete type errors in C

I have a struct called 'residence' below. It contains a person_list struct where the person_list struct contains a struct for each person.
typedef struct a_person
{
char name [MAX_LENGTH];
int age;
} person;
typedef struct person_list
{
struct person people[MAX_ALLOWED];
} personList;
struct residence {
char residence_name [MAX_LENGTH];
struct personList resident_list;
};
I'm getting these errors upon compilation:
error: resident_list; has incomplete type
error: array type has incomplete element type (#struct person
people[MAX_ALLOWED];)
If you need additional code or information please don't hesitate to ask
You could predeclare every struct that you are further defining, e.g. by starting your file (or your header file) with
struct a_person; // should be person_st
struct person_list; // should be person_list_st
then you may have a pointer to such struct (even without having defined the fields of that struct yet).
However, when you define a struct by listing all its fields, every field should have a size known to the compiler.
Some further hints (including conventions):
you could (and I do, conventionally) name every struct tag ending with e.g. _st (this is a convention that I do like to follow)
you can make a typedef together with the struct declaration, e.g.
typedef struct a_person_st Person;
BTW, I am following the convention (inspired by GTK) that a structure type starts with a capital letter.
I don't recommend having typedef for pointers. Being a pointer type is really important in C, and I feel it should be kept apparent. So I recommend against typedef Person*PersonPtr; (but again, this is my convention).
You would later define the struct by listing its fields, e.g.
struct person_st { // or Person
char name[MAX_LENGTH];
int age;
}; // end of definition of struct person_st
You might be interested (assuming a C99 or C11 compiler) by flexible array members (it is a C feature, not a C++ one, and that flexible array member should always be the last of its containing struct).

Clarification of C struct syntax

As usual, Wikipedia's article on structs is less than clear. It gives the syntax for structs as this:
[typedef] struct [struct_name]
{
type attribute;
type attribute2;
/* ... */
[struct struct_name *struct_instance;]
} [struct_name_t] [struct_instance];
What would the typedef keyword do here?
What does the [struct_name] mean? (Is it the name you're giving to the new struct data type?)
What does the [struct_name_t] mean?
what does the [struct_instance] mean? (Is it creating a single instance of the struct?)
I presume [struct struct_name *struct_instance;] creates a pointer in the struct which would point to a second instance of the struct). Correct?
I would greatly appreciate an example: Say I have three files: main.c, sub.c and sub.h. I want to declare an instance of a struct in sub.h, and instantiate and use it it in sub.c. Say I want a Song type struct, with members char name[20] and char artist[10], and say I want to make an instance, mySong, {"Me singing", "Me"}, how would this look in sub.c and sub.h?
Thanks
•What would the typedef keyword do here?
It would allow you to create a typedef of your structre, just like any other type. This allow you to not have to type struct xxx struct_name everytime. You don't need this, hence the []
•What does the [struct_name] mean? (Is it the name you're giving to the new struct data type?)
Yes, if you chose too. You can also make a nameless struct so you don't need to give it a name.
•What does the [struct_name_t] mean?
That's the typedef'd name, if you chose to typedef the struct
•what does the [struct_instance] mean? (Is it creating a single instance of the struct?)
Yes, it's for creating one or more instance(s) of the sturct
•I presume [struct struct_name *struct_instance;] creates a pointer in the struct which would point to a second instance of the struct). Correct?
Right, this would be usefull for a "next" type pointer in a linked list.
struct example:
typedef struct foo{
int count;
struct foo *next;
} foo_t myfoo;
is an example of that filled in; this allows you to declare a new struct via:
foo_t new_foo_struct;
because of the typedef and typedef'd name. If you omit those like this:
struct foo{
int count;
struct foo *next;
} myfoo;
Now you'd have to use the struct key word for every instance, such as:
struct foo new_foo_struct;
to break it up over more than 1 file:
/*sub.h*/
typedef struct{
char name[20];
char artist[10];
}song;
Then in the source:
/*sub.c*/
#include "sub.h"
/*this needs to go into a function or something...*/
song mysong;
strcpy(mysong.name, "Mesinging");
strcpy(mysong.artist, "Me");
That article is just wrongly mixing different concepts, rectified this now. A struct is declared through
struct tagname {
... fields ...
};
that's just it, only that the tagname part is optional in some contexts.
In addition you may
declare an alias for the struct type through typedef
or a variable of the struct type
"in one go", but I don't think that it is good style and should be separated.
sub.h
------
typedef struct{
char name[20];
char artist[10];
}song;
sub.c
----
song mysong={"Me Singing","Me"};
typedef struct struct_name
{
char name[20];
char artist[10];
}struct_name_t structInstance;
typedef - this means that you are creating a new type (struct_name_t)
So, in C code you can create an instance like this:
struct_name_t myVariable;
or you can explicitly write:
struct struct_name myVariable;
The structInstance at the end means that you want to create an instance of your struct at the same moment you defined it (and the name of that variable is structInstance). It's not something you will use all the time, but it is useful in some situations.
If you want to create an instance of your struct and assign/initialize members at the creation time, you can do it like this:
struct_name_t myVariable = { "Foo", "bar" };
The 'name' member will contain "Foo" and the artist member will contain "bar".
Note:
If you write this:
struct_name_t myVariable = { 0 };
That will fill your entire struct with zeroes!

array type has incomplete element and field 'status' has incomplete type

Im a NOOB with programming and Im really stumped. I get "array type has incomplete element and field 'status' has incomplete type" errors when i compile this code. I have this linked with another pile of code "which is thankfully error free". the errors are identified in this section so any help will be appreciated.
Thank you. here's the C code
struct name;
struct book;
struct Library{
struct Book collection[100];
struct person patrons[100];
int totalBooks;
int totalPatrons;
};
struct person{
char first[32];
char last[32];
enum Stat status;
};
struct Book{
char title[32];
char author[32];
int id;
int year;
int status;
};
enum Stat{ACTIVE=1, INACTIVE=2, CHECKED_OUT=3, CHECKED_IN=4, UNDER_REPAIR=5, LOST=6};
~
Looks like you've come from a C background - unfortunately it isn't valid C# code.
Arrays are defined as char[] first; (also size isn't relevant at this point)
Enums do not need an enum prefix when defining the variables. Same with structs.
You don't need to declare structs for name and book
In fact, I think you're probably wanting to use a string variable instead of char arrays.
struct Library{
Book[] collection;
Person[] patrons;
};
struct Person{
string first;
string last;
Stat status;
};
struct Book{
string title;
string author;
int id;
int year;
int status;
};
enum Stat{ACTIVE=1, INACTIVE=2, CHECKED_OUT=3, CHECKED_IN=4, UNDER_REPAIR=5, LOST=6};
There are basically two things wrong with the section of code you showed that the compiler is complaining about:
C is case sensitive: struct book and struct Book are two different types.
In C, you cannot refer to a type until it has been declared; that is, you cannot define a field of type enum Stat before you define enum Stat.
The actual problem, then, is that the compiler doesn't know what a struct Book is at the point where you try to define an array of them. Similarly, it doesn't know what an enum Struct is at the point where you define a field of that type.
(Mostly unimportant tangent: The reason you are getting the "incomplete type" errors instead of something slightly more useful is because the compiler allows you, in certain cases, to use struct types that you don't actually have the full definition of, but only if you use them through so-called "opaque" pointers (that is, you never actually use the type, you just pass pointers to them around.) In your case you are telling the compiler you want an array of struct Book, which requires a completely define type, which you don't have.)
To fix it you just need to reorder your type definitions so that none of them are used before they're defined, and use consistent casing throughout. Also, while it's legal to continue to refer to struct foo and enum bar in the rest of your program, most people would create a typedef (basically, type aliases) instead. For example:
typedef enum tagStat {
ACTIVE=1,
INACTIVE=2,
CHECKED_OUT=3,
CHECKED_IN=4,
UNDER_REPAIR=5,
LOST=6
} Stat;
typedef struct tagPerson {
char first[32];
char last[32];
Stat status;
} Person;
typedef struct tagBook {
char title[32];
char author[32];
int id;
int year;
int status;
} Book;
typedef struct tagLibrary {
Book collection[100];
Person patrons[100];
int totalBooks;
int totalPatrons;
} Library;
It looks like you are trying to use the Stat enum in your definition of person before you declare/define it. Add enum Stat; where you have the struct statements at the top of the file.

What's the benefit of a typedef in C?

typedef struct _VIDEO_STREAM_CONFIG_CAPS
{
GUID guid;
ULONG VideoStandard;
SIZE InputSize;
SIZE MinCroppingSize;
SIZE MaxCroppingSize;
int CropGranularityX;
int CropGranularityY;
int CropAlignX;
int CropAlignY;
SIZE MinOutputSize;
SIZE MaxOutputSize;
int OutputGranularityX;
int OutputGranularityY;
int StretchTapsX;
int StretchTapsY;
int ShrinkTapsX;
int ShrinkTapsY;
LONGLONG MinFrameInterval;
LONGLONG MaxFrameInterval;
LONG MinBitsPerSecond;
LONG MaxBitsPerSecond;
} VIDEO_STREAM_CONFIG_CAPS;
Why not define structure VIDEO_STREAM_CONFIG_CAPS directly instead of involving _VIDEO_STREAM_CONFIG_CAPS?
Quite simply (at least for me) because some people like to be able to treat user defined types as "primary" types.
Just like I wouldn't like to have to say:
struct int i;
I prefer:
VIDEO_STREAM_CONFIG_CAPS vscc;
to:
struct VIDEO_STREAM_CONFIG_CAPS vscc;
In fact, I usually get rid of the structure tag altogether, preferring:
typedef struct {
GUID guid;
ULONG VideoStandard;
:
} VIDEO_STREAM_CONFIG_CAPS;
The only time I genarally use the tag is if I have to refer to the type within the type definition itself, such as in linked lists:
typedef struct sNode {
char paylod[128];
struct sNode *next;
} tNode;
That's because, at the time of creating the definition, tNode doesn't yet exist but struct sNode does (you can think of it as a simple sequencing thing if that makes it easier - struct sNode gets created on line 1 above, tNode on line 4, which means on line 3 where you create the next pointer, you have to use the structure name).
In the case you cite, the structure tag is superfluous at least in the code shown. Whether some other piece of the code declares a variable with the structure name rather than the typedef name is unclear.
In c, you have to put struct in front of a declaration of a struct type. Without this typedef, you'd have to write struct VIDEO_STREAM_CONFIG_CAPS each time you wanted to use it. With the typedef, you can say just VIDEO_STREAM_CONFIG_CAPS as you would in c++.
struct a {};
struct a A;
OR
typedef struct a {} a;
a A;
In that case, each time a variable of type VIDEO_STREAM_CONFIG_CAPS is declared, the following syntax would be required:
struct VIDEO_STREAM_CONFIG_CAPS vscc;
With typedef struct it is:
VIDEO_STREAM_CONFIG_CAPS vscc;

Resources