Dynamic array stack struct C - c

I have a couple of questions. I have a bit of a hard time understanding this code. What exactly is it doing?
For example:
What does typedef struct dynArrStruct do and why does it have dynArr at the end of it? I know the definition of typedef as "allows to created alias for a known data type" but that is jargon to me. Can someone try to put it in layman terms? Thank you!
Why are there 2 struct variables (a1/a2)?
Link to full code if needed:
http://www.cs.uic.edu/pub/CS211/CS211LectureNotesS13/dynArr.c
typedef struct dynArrStruct
{
double *location;
int length;
int currSize;
} dynArr;
int main (int argc, char**argv)
{
struct dynArrStruct a1;
dynArr a2;
int i;
//rest of code
}

What does typedef struct dynArrStruct do and why does it have dynArr at the end of it?
The typedef creates an alias to a type to save you some typing, or to improve readability. In this particular case, it creates an alias called dynArr for the struct dynArrStruct.
Without a typedef, i.e. with only this
struct dynArrStruct
{
double *location;
int length;
int currSize;
};
you would be forced to write struct dynArrStruct every time you need to declare a variable of that struct's type. With a typedef in place, you can write simply dynArr, and the compiler will interpret it as the struct dynArrStruct for you.

typedef struct dynArrStruct
{
double *location;
int length;
int currSize;
} dynArr;
Is a short form of two different pieces of code.
// define a struct by name dynArrStruct
struct dynArrStruct
{
double *location;
int length;
int currSize;
};
//Example of use
struct dynArrStruct d1;
and
// define an alias to "struct dynArrStruct" called dynArr
typedef struct dynArrStruct dynArr;
//Example of use
dynArr d2; //whoa so short!

In addition to dasblinkenlight's answer,
Why are there 2 struct variables (a1/a2)?
The code presented appears to be an example of poorly modularised code (a1) and well modularised code (a2). The modifications made to a1 are very similar to the modifications made to a2. However, the modifications made to a2 are abstracted out into functions (lines 53-55 correspond to the lines found in init, 57-58 correspond to the lines found in push and push), so that that functionality can be easily reused. An example of this reuse is lines 69-72.

Related

Header file typedef definition

Hi I was triying to make something like this, but I cant sort it out. The problem is one typedef needs the other one. I would really appreciate someones help!
#ifndef SHELL_DATA_H
#define SHELL_DATA_H
#include <buffer.h>
#define COMMANDS 10
#define MAX_ARGS 4
typedef struct {
void (*command)(int, char **, t_shellData *shelldData);
char *name;
char *description;
} t_command;
typedef struct {
t_command commands[COMMANDS];
t_buffer buffer;
char username[BUFFER_SIZE];
} t_shellData;
#endif
typedef struct command t_command;
typedef struct shelldata t_shellData;
struct command {
void (*command)(int, char **, t_shellData *shelldData);
char *name;
char *description;
};
struct shelldata {
t_command commands[COMMANDS];
t_buffer buffer;
char username[BUFFER_SIZE];
};
should fix it up for you. The structure tag and typedef name can be the same; I just renamed them for clarity.
C is a simple language, with an underlying principle of do not surprise people. For this reason, entities in C need to be declared or defined before they are used. As a simple example:
int f() {
int a = 7;
int b = a;
....
}
is OK, but this is not:
int f() {
int b = a;
int a = 7;
....
}
and while not exactly, languages like golang permit this -- the compiler will root around and find the definition you obviously wanted.
Typedef, in C, really just puts an entry into the symbol table; it is like a define, but less blunt, so the line:
typedef struct a A;
Serves to inform the compiler of two things: somewhere there is a structure with tag a, and I want A to be a shortform for it. There is another form of this:
struct a;
typedef struct a A;
Here, the first line tells the compiler "I want you to know about a thing called struct a"; and the second line "I want an alias to that struct a thing called A".
So, as the compiler progresses through the source, it knows that an A means a struct a, and even if it hasn't seen the definition of struct a, it has a placeholder.
But, if you attempted, before defining struct a to define another structure:
struct b {
struct a stuff;
int morestuff;
};
The compiler would complain, because it doesn't know the layout of a struct a; however this:
struct b {
struct a *stuff;
int morestuff;
};
is OK, because it knows how big a pointer is, and can defer its understanding of a struct a until it needs it.
So, Summary: declare or define data types before you attempt to use them. The C compiler requires it. A declaration is ok, unless you need the actual layout of it, in which case a definition is required.
Good Luck.

Giving different names to a struct with same body

I have a code duplication situation where I have exact same body of struct but with different names. The body of struct is not small, hence there is risk of injecting error while modifying code in future. Following is just example to illustrate the problem:
struct read_data_on_disk {
int a;
char b;
};
struct read_data {
int a;
char b;
};
It is possible to define one of them, say read_data_on_disk and another be just defined as alias of it? I am looking for something like below:
typedef struct read_data_on_disk struct read_data; // this is wrong though
That's almost right. Try this:
struct read_data_on_disk {
int a;
char b;
};
typedef struct read_data_on_disk read_data;
But as dbush pointed out above, why have two structs if their content is identical?

"warning: useless storage class specifier in empty declaration" in struct

typedef struct item {
char *text;
int count;
struct item *next;
};
So I have this struct with nodes defined as above, but Im getting the error below and Im not able to figure out whats wrong.
warning: useless storage class specifier in empty declaration
};
I'm not sure, but try like that :
typedef struct item {
char *text;
int count;
struct item *next;
}item;
typedef is used to create a shorthand notation for an existing type in C. It is similar to #define but unlike it, typedef is interpreted by the compiler and offers more advanced capabilities than the preprocessor.
With its simplest form, typedef is given as
typedef existing_type new_type;
for instance,
typedef unsigned long UnsignedLong;
For example, if you trace the definition of size_t back to its root, you will see that
/* sys/x86/include/_types.h in FreeBSD */
/* this is machine dependent */
#ifdef __LP64__
typedef unsigned long __uint64_t;
#else
__extension__
typedef unsigned long long __uint64_t;
#endif
...
...
typedef __uint64_t __size_t;
and then
/* stddef.h */
typedef __size_t size_t;
which actually means, size_t is an alias for unsigned long long,depending on the 64-bit modal (LP64, ILP64, LLP64) your machines has.
For your question, you attempt to define a new type but do not name it. Don't let the struct item {..} definition confuse you, it is just a type you are declaring. If you replace the whole struct item {...} with a basic type, say with an int, and rewrite your typedef, you would end up something like this
typedef int; /* new type name is missing */
the correct form should be
typedef struct item {...} Item;
See the examples below for different structure definitions
#include <stdio.h>
/* a new type, namely Item, is defined here */
typedef struct item_t {
char *text;
int count;
struct item_t *next; /* you canot use Item here! */
} Item;
/* a structure definition below */
struct item {
char *text;
int count;
struct item *next;
};
/* an anonymous struct
* However, you cannot self-refence here
*/
struct {
int i;
char c;
} anon;
int main(void) {
/* a pointer to an instance of struct item */
struct item *pi;
/* Shorthand for struct item_t *iI */
Item *iI;
/* anonymoous structure */
anon.i = 9;
anon.c = 'x';
return 0;
}
The typedef is useless because you didn't give it a name. You cannot use the typedef in any way. That's why you get a warning, because the typedef is useless.
The struct is actually still usable without the warning if you remove the typedef keyword like this:
struct item {
char *text;
int count;
struct item *next;
};
You just need to include the 'struct' keyword in the variable declaration. i.e.
struct item head;
as other have pointed out if you include the name at the end of the struct definition then you can use it as the typedef and you get rid of the warning even without the struct keyword but this makes the first instance of 'item' superfluous i.e.
typedef struct {
char *text;
int count;
struct item *next;
} item;
item head;
will also get rid of the warning.
This is an oldie, but stumbled here because I had the same linker error.
I made the foolish mistake of naming a file with an extension .c, and should have been .cpp - created the SAME error - so watch out!
Renamed the file to have a .cpp extension, and the problem magically went away.
Took a while to figure that out, so happy to share my experience.

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;

C: pointer to struct in the struct definition

How can I have a pointer to the next struct in the definition of this struct:
typedef struct A {
int a;
int b;
A* next;
} A;
this is how I first wrote it but it does not work.
You can define the typedef and forward declare the struct first in one statement, and then define the struct in a subsequent definition.
typedef struct A A;
struct A
{
int a;
int b;
A* next;
};
Edit: As others have mentioned, without the forward declaration the struct name is still valid inside the struct definition (i.e. you can used struct A), but the typedef is not available until after the typedef definition is complete (so using just A wouldn't be valid). This may not matter too much with just one pointer member, but if you have a complex data structure with lots of self-type pointers, may be less wieldy.
In addition to the first answer, without a typedef and forward declaration, this should be fine too.
struct A
{
int a;
int b;
struct A *next;
};
You are missing the struct before the A*
typedef struct A {
int a;
int b;
struct A* next;
} A;
You can go without forward declaration:
struct A {
int a;
int b;
struct A *next;
};
Please, you're in C, not C++.
If you really must typedef a struct (and most programmers that I work with would not¹), do this:
typedef struct _A {
int a;
int b;
struct _A *next;
} A;
to clearly differentiate between _A (in the struct namespace) and A (in the type namespace).
¹typedef hides the size and storage of the type it points to ― the argument (and I agree) is that in a low-level language like C, trying to hide anything is harmful and counterproductive. Get used to typing struct A whenever you mean struct A.
typedef struct {
values
} NAME;
This is shorter way to typedef a struct i think its the easiest notation, just don't put the name infront but behind.
you can then call it like
NAME n;
NAME *n; // if you'd like a ptr to it.
Anything wrong with this approach?

Resources