Array of Pointers dereferencing when accessed in C - c

I have a array structure that should hold a pointer to another structure. My structures are like this:
struct Term{
char* term;
int times;
};
typedef struct Term TERM;
struct HeapTer{
TERM* Term;
size_t used;
size_t size;
};
typedef struct HeapTer HEAPTER;
struct Pack{
HEAPCON* hCon;
HEAPTER* hTer;
};
typedef struct Pack PACK;
Pack will just hold the pointers of both arrays I will return from my structure loading function.
My problem is when I will call a function, where I will insert a given term to the consults term heap.
InsertHeapTer(pack->hTer->Term[ind_term],consult->hTer)
Where InsertHeapTer is defined as InsertHeapTer(TERM* Ter, HEAPTER *t).
The compiler gives me the following error, error: incompatible types when assigning to type 'TERM {aka struct Term}' from type 'TERM * {aka struct Term *}'.
So, it is saying that when I use pack->hTer->Term[ind_term] it gives me a TERMand not a TERM*, even though it is defined as a pointer in the structure.
What am I doing wrong and why is this happening?
EDIT:
Code to reproduce:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
struct Termo{
char* termo;
int vezes;
};
typedef struct Termo TERMO;
struct HeapTer{
TERMO* Termo;
size_t usado;
size_t tam;
};
typedef struct HeapTer HEAPTER;
struct consulta{
char *Local;
HEAPTER *hTer;
};
typedef struct consulta CONSULTA;
struct HeapCon{
CONSULTA* con;
size_t usado;
size_t tam;
};
typedef struct HeapCon HEAPCON;
struct Pacote{
HEAPCON* hCon;
HEAPTER* hTer;
};
typedef struct Pacote PACOTE;
void InsereHeapTer(TERMO* Ter, HEAPTER *t){
}
int main(){
PACOTE* pack;
CONSULTA* consulta;
int ind_termo=1;
InsereHeapTer(pack->hTer->Termo[ind_termo],consulta->hTer);
return 0;
}
void InsereHeapTer(TERMO* Ter, HEAPTER *t){
}
I'm sorry, but this was the minimal setup I could do.

So, it is saying that when I use pack->hTer->Term[ind_term] it gives
me a TERM and not a TERM*,
Yes.
even though it is defined as a pointer in
the structure.
Be careful: even though what is defined as a pointer? It is pack->hTer->Term that is so defined. With that being the case, then, pack->hTer->Term[ind_term] indeed has type TERM. It is equivalent to *(pack->hTer->Term + ind_term).
And that suggests a resolution: if you meant to pass a pointer to that item instead of a copy of the item, then you can use pointer arithmetic to produce the wanted pointer as pack->hTer->Term + ind_term. I tend to prefer the simplicity of that, but stylistically, I'm sure some people would prefer the equivalent expression &pack->hTer->Term[ind_term].

To simplify the offending line of code, you can do:
TERMO* termo = pack->hTer->Termo;
InsereHeapTer(termo[ind_termo],consulta->hTer);
Clearly, termo is a TERMO*. The [] operator is defined like this:
The definition of the subscript operator [] is that E1[E2] is identical to (*((E1)+(E2))).
C.11 §6.5.2.1 ¶2
Thus, your function call is equivalent to:
InsereHeapTer(*(termo + ind_termo),consulta->hTer);
And this can be simplified again:
TERMO* termo_plus_ind = termo + ind_termo;
InsereHeapTer(*termo_plus_ind,consulta->hTer);
When you dereference a TERMO*, you get a TERMO.

Related

What does it mean to typedef a struct as an array?

The graph adjacency list code in my book is given by:
typedef struct vertexNode //vertexNode in an AdjacencyList
{
VertexType data;
EdgeNodeType *firstEdgeNode;
} VertexNode, AdjList[MAXVEX];
AdjList adjList; # adjList is a MAXVEX-size array
I was confused by the last line in the typedef: typedef struct{...} AdjList[MAXVEX].
The forms I can understand are:
typedef struct{
...
} VertexNode,
VertexNode AdjList[MAXVEX]; # AdjList is a MAXVEX-size array
or
struct{
...
} AdjList[MAXVEX]; # AdjList is a MAXVEX-size array
Grammatically speaking, typedef is actually a storage class, like static or extern, and type alias declarations are read like variable declarations. E.g.
int x;
declares x to be a variable of type int, while
typedef int x;
declares x to be a type alias meaning int.
Similarly,
struct vertexNode {
...
} VertexNode;
would declare VertexNode to be a struct vertexNode variable, but adding typedef makes it an alias for struct vertexNode. Note that struct vertexNode { ... } (the whole thing) is a type, just like int. It first defines struct vertexNode, and then refers to it.
Additionally, array declarations may appear to behave strangely when you use commas:
int x, y[5];
declares x to be an int, while declaring y to be an array of 5 ints. (Functions and pointers are also like this.) There are other questions on this site about it.
Putting everything together, your question looks like this if you take away the typedef:
struct vertexNode
{
VertexType data;
EdgeNodeType *firstEdgeNode;
} VertexNode, AdjList[MAXVEX];
This would declare the type struct vertexNode, the variable VertexNode of type struct vertexNode, and the array AdjList of MAXVEX struct vertexNodes. Adding the typedef means that VertexNode becomes an alias for struct vertexNode and that AdjList becomes an alias for an array of MAXVEX struct vertexNodes. Personally, I wouldn't recommend writing it like this, but I guess it's concise.
This is a sample code.
#include <stdio.h>
typedef char STR[1024];
int main() {
STR a = "1234"; // == char a[1024]
printf( "%s\n", a );
return 0;
}
I wrote a example with data type char.
You can replace it with any class or struct..
so.. Your code..
AdjList a is same with VertexNode a[MAXVEX]

Why are pointers to incomplete types allowed and not variables of incomplete types?

Why is the following legal:
typedef struct a aType;
struct a
{
int x;
aType *b;
};
and the following illegal:
void main()
{
typedef struct a aType;
aType someVariable;
struct a
{
int x;
aType *b;
};
}
I'm just curious as in each case it is forward referencing and as far as I know, at least for functions and variables, forward referencing is not legal.
Also, would the answer for this be the same for C++ as well?
You are allowed to create pointers to incomplete types, because the size of the pointer object does not depend on the size of the pointed-to type. Pointers to different struct types have the same size and representation, regardless of the size of the struct type itself.
You are not allowed to create instances of incomplete types, since the size of the type isn't known.
This of it this way:
typedef struct a aType;
struct a { int x; aType *b; };
is the same as:
struct a;
typedef struct a aType;
struct a { int x; aType *b; };
So you're forward-declaring a struct, typedefing it and later defining it. Perfectly fine.
Now the second example:
typedef struct a aType;
aType someVariable;
struct a { int x; aType *b; };
This has nothing to do with the fact that it's in local scope.
What's happening is this:
struct a;
typedef struct a aType;
aType someVariable; // error: when it gets here, aType is still incomplete
struct a { int x; aType *b; };
aType someVariable; // perfectly fine, aType not incomplete
Remember that compilation happens in order. When you try to declare someVariable the compiler doesn't know what struct a is yet, so it doesn't know its size, hence it doesn't know how much memory to allocate for it, hence a compile error. Declaring it after aType is defined works as expected.

What does `*` mean in a C `typedef struct` declaration?

I'm looking at a C struct with some syntax I've never seen before. The structure looks like this:
typedef struct structExample {
int member1;
int member2
} * structNAME;
I know that normally with a structure of:
typedef struct structExample {
int member1;
int member2
} structNAME;
I could refer to a member of the second struct definition by saying:
structNAME* tempStruct = malloc(sizeof(structNAME));
// (intitialize members)
tempstruct->member1;
What does that extra * in the the first struct definition do, and how would I reference members of the first struct definition?
It means the defined type is a pointer type. This is an equivalent way to declare the type:
struct structExample {
int member1;
int member2;
};
typedef struct structExample * structNAME;
You would use it like this:
structNAME mystruct = malloc (sizeof (struct structExample));
mystruct->member1 = 42;
The typedef makes these two statements the same
struct structExample *myStruct;
structName myStruct;
It makes structName stand for a pointer to struct structExample
As an opinion, I dislike this coding style, because it makes it harder to know whether a variable is a pointer or not. It helps if you have
typedef struct structExample * structExampleRef;
to give a hint that it is a pointer to struct structExample;
structNAME is defined as a pointer on struct structExample. SO you can do
structNAME tempStructPtr = malloc(sizeOf(struct structExample));
tempStructPtr->member1 = 2;
The secret to understanding these is that you can put typedef in front of any declaration, to turn TYPENAME VARIABLENAME into typedef TYPENAME ALIASEDNAME.
Since the asterisk can't be part of the VARIABLENAME part if this was a plain declaration, it has to be part of the type. An asterisk following a type name means "pointer to" the preceding type.
Compare this:
typedef int * my_int_pointer;
It's exactly the same, except in your case instead of int you're declaring a struct.
In that case (* structNAME) is pointer variable of that structure..

K&R 2E Typedef pg 146,147

typedef struct tnode { ... } Treenode;
Since typedef can't create a new type for us, is this part of the declaration of "struct tnode"? So in the above, is it creating a typedef "Treenode" AND declaring "struct tnode"?
return (Treeptr) malloc(sizeof(Treenode));
Here, since Treenode is a synonym for the entire "struct tnode" declaration, is it necessary to pass the whole declaration to sizeof or can one just do: sizeof(struct tnode) after declaring tnode elsewhere via struct tnode { ... };
typedef struct tnode *Treeptr;
Typedef is: typedef old-existing-type newtype; So here.. struct tnode * is the old type which must already exist (must be declared elsewhere) and Treeptr is the synonym for that.. but why can't we space the thing?? Like so: typedef struct tnode * Treeptr;
typedef int (*PFI)(char *, char *);
What is going on here? the old-type is int and (*PFI)(char , char) is a synonym for int?? If int (*PFI)(char *, char *) is the old-type, what's the new-type?? What does he mean by saying "In effect typedef is like #define, except that since it's interpreted by the compiler, it can cope with textual substitutions that are beyond the capabilities of the preprocessor"? In the mentioned example.. why can't the preprocessor do whatever is being done??
So in the above, is it creating a typedef "Treenode" AND declaring
"struct tnode"?
Yes, there are both declaration and typedef in the same sentence.
but why can't we space the thing?? Like so: typedef struct tnode *
Treeptr
If you are talking about the * - you can. it is a separate token anyway.
typedef int (*PFI)(char *, char *);
This is a function type definition;
typedef int (*PFI)(char *, char *);
^ define a type called
^PFI as:
^ pointer
^to function
^that receives two char pointers as arguments
^ and returns an int
Now you can use PFI instead of int (*)(char *, char *) (when used as a parameter / variable)
EDIT:
Code sample for using function pointer:
#include <stdio.h>
int add(int a, int b) { return a + b; }
typedef int (*pfi)(int,int);
int main()
{
pfi my_func = add;
int res;
res = (*my_func)(1,2);
printf( "add(1,2)=%d", res);
return res;
}

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