Error when defining a struct - c

I am attempting to write a simple linked list just for practice and to jog my memory a little bit, but I have ran into trouble. I am pretty inexperienced in C, and I don't understand why this isn't working. I am trying to define a Node and a LinkedList struct, but every time I try to compile I get an error saying Node is an unknown type. I'm sure I am missing something, but I can't figure this out. Thanks all!
This is my ll.h file
1 #ifndef ll_h
2 #define ll_h
3
4 #include <stdio.h>
5
6 typedef struct {
7 void *data;
8 Node *next;
9 Node *prev;
10 } Node;
11
12
13 typedef struct {
14 Node *first;
15 Node *last;
16 int size;
17 } LinkedList;
18
19
20 void *getData(LinkedList list, int index);
21 int getSize(LinkedList list);
22 void *deleteNode(LinkedList, int index);
23 void add(LinkedList list, void *data);
24 void freeList(LinkedList list);
25
26 #endif
Errors I am receiveing
cc -Wall -g -c -o ll.o ll.c
In file included from ll.c:3:0:
ll.h:8:5: error: unknown type name ‘Node’
ll.h:9:5: error: unknown type name ‘Node’
ll.c: In function ‘getData’:
ll.c:8:18: error: expected expression before ‘LinkedList’
ll.c:12:7: warning: assignment from incompatible pointer type [enabled by default]
ll.c: In function ‘getSize’:
ll.c:21:12: error: expected expression before ‘LinkedList’
ll.c: In function ‘deleteNode’:
ll.c:26:18: error: expected expression before ‘LinkedList’
ll.c:32:7: warning: assignment from incompatible pointer type [enabled by default]
ll.c:37:12: error: request for member ‘next’ in something not a structure or union
ll.c:38:12: warning: assignment from incompatible pointer type [enabled by default]
ll.c:40:12: error: request for member ‘next’ in something not a structure or union
ll.c: In function ‘add’:
ll.c:52:16: warning: assignment from incompatible pointer type [enabled by default]
ll.c:54:21: warning: assignment from incompatible pointer type [enabled by default]
ll.c: In function ‘freeList’:
ll.c:61:18: error: expected expression before ‘LinkedList’
ll.c:62:18: warning: initialization from incompatible pointer type [enabled by default]
ll.c:65:7: warning: assignment from incompatible pointer type [enabled by default]
ll.c:67:7: warning: assignment from incompatible pointer type [enabled by default]
ll.c:62:11: warning: variable ‘next’ set but not used [-Wunused-but-set-variable]
ll.c:60:9: warning: unused variable ‘i’ [-Wunused-variable]
ll.c: In function ‘main’:
ll.c:85:6: error: ‘LinkedList’ has no member named ‘add’
ll.c:91:10: warning: dereferencing ‘void *’ pointer [enabled by default]
ll.c:91:10: error: void value not ignored as it ought to be
ll.c: In function ‘getSize’:
ll.c:22:1: warning: control reaches end of non-void function [-Wreturn-type]
make: *** [ll.o] Error 1

Use this:
typedef struct Node{
void *data;
struct Node *next; // note here
struct Node *prev;
} Node;

You either need forward declaration, or you need to drop the typedef. You can also use typedef with having the Node twice.
Forward declaration
typedef struct Node Node; // Necessary in C, harmless (but non-idiomatic) in C++
typedef struct {
void *data;
Node *next;
Node *prev;
} Node;
No typedef (Will only work in C++, not C)
struct Node {
void *data;
Node *next;
Node *prev;
};
Using typedef with tag
Works in C and C++, but non-idiomatic for C++.
typedef struct Node {
void *data;
struct Node *next;
struct Node *prev;
} Node;

Posting an Answer for the next reader brought here by Google searching:error: void value not ignored as it ought to be
Remember when trying to implement pseudo-code that function pointers get initialized with the name of the function without any parenthesis. Rookie mistake? Maybe, but I'm not exactly rookie (taught C/C++ Labs at university in mid 90s) and it got me. Had I typed it and not cut-n-pasted, I probably would have caught the error, as I know not to create that code...
Example with declarations supplied for completeness:
// Static menu manager
#define MAX_SELECTIONS 4
#define MAX_PROMPT_LEN 20
typedef struct _selection {
char prompt[MAX_PROMPT_LEN];
void(*function) ( void );
int fn_arg;
} SELECTION ;
typedef struct _menu {
int id;
int num_selections;
SELECTION selection[MAX_SELECTIONS];
} MENU;
enum _menu_ids { MAIN_MENU, DEPOSIT_MENU, WITHDRAWL_MENU, BALANCE_MENU };
enum _menu_keys { DEPOSIT, WITHDRAWL, BALANCE, CHECKING, SAVINGS };
Wrong:
// WRONG
static MENU menu[] = {
{ MAIN_MENU, 4,
{"Perform A Deposit", goto_menu(), DEPOSIT_MENU},
{"Perform a Withdrawl", goto_menu(), WITHDRAWL_MENU },
{"Get Balance", goto_menu(), BALANCE_MENU },
{"Hide Menu", menu_hide(), 0}
}
}
Correct:
// Correct
static MENU menu[] = {
{ MAIN_MENU, 4, {
{"Perform A Deposit", goto_menu, DEPOSIT_MENU},
{"Perform a Withdrawl", goto_menu, WITHDRAWL_MENU },
{"Get Balance", goto_menu, BALANCE_MENU },
{"Hide Menu", menu_hide, 0} }
}
}
Particularly observant readers might notice the additional braces required to initialize the struct's array's members were missing in the pseudo-code. The gcc compiler was kind enough to provide a useful error:MENU: improper number of initializers.

Related

Error: Expected ‘struct tree_node *’ but argument is of type ‘struct tree_node *’

I'm facing two errors when trying to assign a value to the components of a struct and later when passing a pointer of struct to a function.
I have a user-defined data type: my_node defined in a header file as follows:
enum n_type
{
N_COMMAND,
N_PIPE,
N_REDIRECT,
N_SUBSHELL,
N_SEQUENCE,
N_DETACH
};
struct my_node;
typedef struct my_node node_t;
struct my_node
{
enum n_type type;
union {
struct {
char *program;
char **argv;
size_t argc;
} command;
struct {
node_t **parts; // array
size_t n_parts;
} pipe;
struct {
... etc
}
and I have a function that takes a pointer to a my_node variable:
void run_command(struct my_node *a_node);
In myprogram.c, I try to make a new node, populate its components, define a pointer to its address then pass the pointer to the function above like this:
// first I get input as a string:
fgets(str, 100, stdin);
// create the new node
struct my_node
{
enum n_type type;
union
{
struct {
char *program;
char **argv;
size_t argc;
} command;
};
} node;
// assign values to its components (values are just for testing)
node.type = N_COMMAND;
node.command.program = &str;
node.command.argv = &node.command.program;
node.command.argc = 3;
// define a pointer to the node
struct my_node *ptr;
ptr = &node;
//pass the pointer to run command to execute it
run_command(ptr);
When I try to compile, I get those weird errors:
gcc ./shell.c -o shelli
./shell.c: In function ‘main’:
./shell.c:37:23: warning: assignment from incompatible pointer type [-Wincompatible-pointer-types]
node.command.program = &str;
^
./shell.c:47:14: warning: **passing argument 1 of ‘run_command’ from incompatible pointer type** [-Wincompatible-pointer-types]
run_command(ptr);
^~~
In file included from ./shell.c:2:0:
./shell.h:21:6: note: **expected ‘struct tree_node *’ but argument is of type ‘struct tree_node *’**
void run_command(struct tree_node *n);
^~~~~~~~~~~
How come that the provided and requested argument types are the same but still there's an error?
What is the type of str? My guess is that it's a char* since you used it as a parameter to fgets, and the compiler didn't complain. If that is the case, then
node.command.program = &str;
doesn't compile since node.comand.program has type char*, but the type of &str is char**. So, the solution is to remove the &, ie.
node.command.program = str;
The compile messages indicate a struct tree_node type, but that type isn't defined in your question. I'll assume it is similar to your struct node definition. With this assumption, the run_command(ptr) is a problem since you redefined what a struct node is in your source file. The redefinition is not compatible with the original definition in the header file. You should define a struct only once in a header file, and then include that header file in any source file that uses that struct.

"void value not ignored as it ought to be" in exercise from "Learn C the Hard Way"

So I'm following this lesson from the Learn C the Hard Way tutorials and I'm a little stuck.
When I try to compile I get this:
cc -Wall -g ex19.c object.o -o ex19
ex19.c:81:2: warning: initialization from incompatible pointer type [enabled by default]
ex19.c:81:2: warning: (near initialization for 'RoomProto.move') [enabled by default]
ex19.c: In function 'Map_move':
ex19.c:91:7: error: void value not ignored as it ought to be
ex19.c: At top level:
ex19.c:140:2: warning: initialization from incompatible pointer type [enabled by default]
ex19.c:140:2: warning: (near initialization for 'MapProto.move') [enabled by default]
make: *** [ex19] Error 1
From what I understand, this error occurs b/c the function returns next when it expects a void return type. But I thought void *foo() meant returning a void pointer.
Here's the code:
Object RoomProto = {
.move = Room_move,
.attack = Room_attack
};
void *Map_move(void *self, Direction direction) {
Map *map = self;
Room *location = map->location;
Room *next = location->_(move)(location, direction);
if(next)
map->location = next;
return next;
}
Room Struct:
struct Room {
Object proto;
Monster *bad_guy;
struct Room *north;
struct Room *south;
struct Room *east;
struct Room *west;
};
How can I fix this error? I tried to change the return type, but ended up getting another error instead.
As far as I can tell, I copied the code in the tutorial char for char, so unless I made a mistake, the tutorial is incorrect.
#MattMcNabb helped me find the answer
Line 13 in object.h file was:
void *(move) (void *self, Direction direction);
instead of:
void *(*move) (void *self, Direction direction);

Peculiar warnings at C

In my project I have these 2 files. When I try to compile it a get some peculiar warnings that I cannot solve, though my program runs fine. I use the -Wall and -Wextra arguments at compile.
//File: DataStructures.h
typedef struct EntryListPacketStruct EntryListPacket;
typedef struct IndexesPacketStruct IndexesPacket;
typedef struct MatchingQueriesResultStruct MatchingQueriesResult;
typedef struct DataPacketStruct* DataPacketPtr;
extern DataPacketPtr Packet;
EntryListPacket* allocateEntryListPacket(void);
void initializeDataPacket(DataPacketPtr);
void freeDataPacket(DataPacketPtr);
void initializeEntryListPacket(EntryListPacket*);
void freeEntryListsPacket(EntryListPacket*);
I include the DataStructures.h in the following file:
//File: DataStructures.c
struct EntryListPacketStruct {
EntryList* exactTypeEntryList;
EntryList** editDistEntryLists;
EntryList** hammingDistEntryLists;
};
struct DataPacketStruct {
struct EntryListPacket* entryLists;
struct IndexesPacket* indexes;
dllistptr matchingQResultList;
};
EntryListPacket* allocateEntryListPacket(void){
EntryListPacket* temp=malloc(sizeof(EntryListPacket));
return temp;
}
void initializeDataPacket(DataPacketPtr packet){
DataPacketPtr temp;
temp=malloc(sizeof(struct DataPacketStruct));
initializeEntryListPacket(temp->entryLists);
initializeIndexesPacket(temp->indexes);
packet=temp;
}
void freeDataPacket(DataPacketPtr packet){
freeEntryListsPacket(packet->entryLists);
freeIndexesPacket(packet->indexes);
free(packet);
}
void initializeEntryListPacket(EntryListPacket* packet) {
packet->exactTypeEntryList = NULL;
packet->editDistEntryLists = malloc(sizeof (EntryList)*22);
int i;
for (i = 0; i < 22; i++) {
packet->editDistEntryLists[i] = NULL;
}
packet->hammingDistEntryLists = malloc(sizeof (EntryList)*27);
for (i = 0; i < 27; i++) {
packet->hammingDistEntryLists[i] = NULL;
}
}
void freeEntryListsPacket(EntryListPacket* packet){
if(packet->exactTypeEntryList!=NULL)
DestroyEntryList(packet->exactTypeEntryList);
free(packet->exactTypeEntryList);
int i;
for(i=0;i<22;i++){
if(packet->editDistEntryLists[i]!=NULL){
printf("%d\n",i);
DestroyEntryList(packet->editDistEntryLists[i]);
}
free(packet->editDistEntryLists[i]);
}
free(packet->editDistEntryLists);
for(i=0;i<27;i++){
if(packet->hammingDistEntryLists[i]!=NULL){
printf("%d\n",i);
DestroyEntryList(packet->hammingDistEntryLists[i]);
}
free(packet->hammingDistEntryLists[i]);
}
free(packet->hammingDistEntryLists);
free(packet);
}
//File:main.c
EntryListPacket *temp;
temp=allocateEntryListPacket();
initializeEntryListPacket(temp);
freeEntryListsPacket(temp);
And I get the following Warnings:
DataStructures.c: In function ‘initializeDataPacket’:
DataStructures.c:48:6: warning: passing argument 1 of ‘initializeEntryListPacket’ from incompatible pointer type [enabled by default]
initializeEntryListPacket(temp->entryLists);
^
In file included from DataStructures.c:6:0:
DataStructures.h:27:10: note: expected ‘struct EntryListPacket *’ but argument is of type ‘struct EntryListPacket *’
void initializeEntryListPacket(EntryListPacket*);
^
DataStructures.c:50:6: warning: passing argument 1 of ‘initializeIndexesPacket’ from incompatible pointer type [enabled by default]
initializeIndexesPacket(temp->indexes);
^
In file included from DataStructures.c:6:0:
DataStructures.h:30:10: note: expected ‘struct IndexesPacket *’ but argument is of type ‘struct IndexesPacket *’
void initializeIndexesPacket(IndexesPacket*);
^
DataStructures.c:43:42: warning: parameter ‘packet’ set but not used [-Wunused-but-set-parameter]
void initializeDataPacket(DataPacketPtr packet){
^
DataStructures.c: In function ‘freeDataPacket’:
DataStructures.c:57:6: warning: passing argument 1 of ‘freeEntryListsPacket’ from incompatible pointer type [enabled by default]
freeEntryListsPacket(packet->entryLists);
^
In file included from DataStructures.c:6:0:
DataStructures.h:28:10: note: expected ‘struct EntryListPacket *’ but argument is of type ‘struct EntryListPacket *’
void freeEntryListsPacket(EntryListPacket*);
^
DataStructures.c:58:6: warning: passing argument 1 of ‘freeIndexesPacket’ from incompatible pointer type [enabled by default]
freeIndexesPacket(packet->indexes);
^
In file included from DataStructures.c:6:0:
DataStructures.h:31:10: note: expected ‘struct IndexesPacket *’ but argument is of type ‘struct IndexesPacket *’
void freeIndexesPacket(IndexesPacket*);
I cannot figure out what I am doing wrong or if the compiler is stuck since this for example: DataStructures.h:28:10: note: expected ‘struct EntryListPacket *’ but argument is of type ‘struct EntryListPacket *’
doesn't seem reasonable to me.
Thx in advance!
Your struct tags include a Struct suffix, but you omitted it when you declared:
struct DataPacketStruct {
struct EntryListPacket* entryLists;
struct IndexesPacket* indexes;
dllistptr matchingQResultList;
};
It should be:
struct DataPacketStruct {
struct EntryListPacketStruct* entryLists;
struct IndexesPacketStruct* indexes;
dllistptr matchingQResultList;
};
Or just:
struct DataPacketStruct {
EntryListPacket* entryLists;
IndexesPacket* indexes;
dllistptr matchingQResultList;
};
Also, your initializeDataPacket function is leaking the memory. Assigning temp to packet doesn't return the value since packet is passed by value, not by reference.
In DataStructures.h, try replacing this:
struct DataPacketStruct {
struct EntryListPacket* entryLists;
...
With this:
struct DataPacketStruct {
EntryListPacket* entryLists;
...
Or this:
struct DataPacketStruct {
struct EntryListPacketStruct* entryLists;
...
And similarly for struct IndexesPacket* indexes;. The compiler warning comes from missing the typedef symbol up with the struct symbol itself.

Warnings when creating a singly linked list with arrays

#include <stdio.h>
typedef struct
{
int data;
struct node *next;
}node;
void print(node *head)
{
node *tmp = head;
while (tmp)
{
printf ("%d ", tmp->data);
tmp = tmp->next;
}
}
int main()
{
node arr[5] = {
{1, &arr[1]},
{2, &arr[2]},
{3, &arr[3]},
{4, &arr[4]},
{5, NULL}
};
print(arr);
return 0;
}
Why do i get these warnings while compiling with gcc -Wall ? (even without -Wall, gcc produces the same warnings)
list.c: In function ‘print’:
list.c:15:7: warning: assignment from incompatible pointer type [enabled by default]
list.c: In function ‘main’:
list.c:22:18: warning: initialization from incompatible pointer type [enabled by default]
list.c:22:18: warning: (near initialization for ‘arr[0].next’) [enabled by default]
list.c:23:18: warning: initialization from incompatible pointer type [enabled by default]
list.c:23:18: warning: (near initialization for ‘arr[1].next’) [enabled by default]
list.c:24:18: warning: initialization from incompatible pointer type [enabled by default]
list.c:24:18: warning: (near initialization for ‘arr[2].next’) [enabled by default]
list.c:25:18: warning: initialization from incompatible pointer type [enabled by default]
list.c:25:18: warning: (near initialization for ‘arr[3].next’) [enabled by default]
What #metalhead said was correct. Another probably better way to achieve the same result is
typedef struct _node
{
int data;
struct _node *next;
} node;
After this definition node (without underscore) can simply be used as a type name like e.g. int.
P.S. The underscore is just a standard convention, not a requirement. Any name could have been used in place of _node as long as you replace in both occurrences. However, in c this is a norm and sort of a coding convention that helps the devs to quickly understand _node refers to the node type actually.
You are trying to use struct node inside the definition of node so therefore the compiler doesn't know you mean them to be the same thing. Try forward declaring the struct first:
struct node;
struct node
{
int data;
struct node *next;
};

Implementing a linked list in C gives warnings and running the code shows nothing

I just tried to implement linked list in C using the GCC compiler but I got these warnings.
Most of the warnings I got were "assignment from incompatible pointer type":
linklist.c: In function 'insertatbegin':
linklist.c:20:8: warning: assignment from incompatible pointer type [enabled by default]
linklist.c:24:18: warning: assignment from incompatible pointer type [enabled by default]
linklist.c:25:8: warning: assignment from incompatible pointer type [enabled by default]
linklist.c: In function 'display':
linklist.c:37:7: warning: assignment from incompatible pointer type [enabled by default]
and after running the code I get nothing output.
#include <stdio.h>
#include <string.h>
#include <conio.h>
#include <stdlib.h>
typedef struct
{
int data;
struct node *next;
}node;
void insertatbegin(node **head,int item)
{
node *nextnode=(node *)malloc(sizeof(node));
if(nextnode!=NULL)
{
nextnode->data=item;
nextnode->next=head; //warning line 24
head=nextnode; // warning line 25
}
else
printf("memory not allocated\n");
}
void display(node * head)
{
node *temp=head;
while(temp!=NULL)
{
printf(" %d ",temp->data);
temp=temp->next; //warning line 37
}
}
void main()
{
node *head=NULL;
insertatbegin(&head,20);
insertatbegin(&head,30);
insertatbegin(&head,40);
display(head);
getch();
}
It seems correct but I got nothing output from that.
You show the typedef:
typedef struct
{
int data;
struct node *next;
}node;
Here, you have an untagged structure type with the typedef name node, and an unrelated tagged structure type struct node (the details of which are not defined in the code you show).
You need:
typedef struct node
{
int data;
struct node *next;
} node;
Now node and struct node refer to the same type. Remember, typedef introduces an alias for another type; it does not introduce a distinct type.
Since the line you mark as 24 in the code here is line 16 in the code shown, it is difficult to know where line 20 really is. It is not obvious why you get a warning at line 20 as:
linklist.c:20:8: warning: assignment from incompatible pointer type [enabled by default]
linklist.c:24:18: warning: assignment from incompatible pointer type [enabled by default]
linklist.c:25:8: warning: assignment from incompatible pointer type [enabled by default]
The warnings at lines 24 and 25 are because you have:
nextnode->next=head; //warning line 24
head=nextnode; // warning line 25
and you need:
nextnode->next = *head; //warning line 24
*head = nextnode; // warning line 25
This is because head is a node ** yet nextnode and nextnode->next are both node * (with the fixed structure definition). The warnings at line 37 is due to the struct node vs node confusion; you'd also get that warning for line 24 if you just fixed the assignment as shown above.
Also, as noted in the comments, the return type for main() should be int, not void (because that's what the C standard says is the return type of main()). If you are using a C89 compiler (which #include <conio.h> suggests you are), you should explicitly return a status from the main() function. C99 and later allows you to omit that return; IMNSHO, it is better to be explicit about it and return a value from every function that is declared to return a value.
Also note that you should output a newline somewhere; there is no guarantee that anything will be displayed until you do output a newline.

Resources