C: Symbols not found for function defined in file? - c

I have a cryptic error, and a warning. The warning: integer initialized to pointer on assignment the other is symbol not found, referring to function popdepholder.
I believe they may somehow be related due to a phantom function that exists but can't be seen or something
header dependency.h:
#include "relation.h"
#include "strhelp.h"
#include <time.h>
#ifndef _DEPENDENCY_H
#define _DEPENDENCY_H
typedef struct fd {
RELATION *left;
RELATION *right;
RELATION *referring; } DEPENDENCY;
typedef struct dh {
DEPENDENCY *data;
struct dh *next;
struct dh *prev; } DEP_HOLDER;
DEP_HOLDER * popdepholer(DEP_HOLDER **top);
...
void removedepholderat(DEP_HOLDER **list,int dest);
...
DEP_HOLDER * popdepholer(DEP_HOLDER **top) ###this function is not being seen
{
DEP_HOLDER * remove = 0;
if(*top)
{
remove=(*top);
if(remove->prev)
{
if(remove->next) /*the middle case*/
{
remove->prev->next=remove->next;
remove->next->prev=remove->prev;
(*top)=(*top)->next;
}
else /*the bottom case*/
{
remove->prev->next=0;
*top=0;
}
}
else if((remove->next)&&!(remove->prev)) /*the top case*/
{
remove->next->prev=0;
(*top)=(*top)->next;
}
else /*the single case*/
{
*top = 0;
}
remove->prev=0;
remove->next=0;
}
else
{
printf("In popdepholder, passed a null pointer!\n");
exit(4);
}
return remove;
}
...
void removedepholderat(DEP_HOLDER **list,int dest)
{
DEP_HOLDER *holder = *list;
if(dest == 1) #here
{
DEP_HOLDER * r = popdepholder(list); #here
destroydepholder(&r);
}
else
{
while((holder) && (dest>1))
{
holder=holder->next;
dest--;
}
if((holder) && dest==1)
{
DEP_HOLDER * r = popdepholder(&holder); #here
destroydepholder(&r);
}
}
}
#endif
main.c:
#include "dependency.h"
DEP_HOLDER *mydp = getnewholder(d1);
...
DEP_HOLDER * a = popdepholder(&mydp);
error:
In file included from test-dependency.c:3:
dependency.h: In function ‘removedepholderat’:
dependency.h:332: warning: initialization makes pointer from integer without a cast
dependency.h:344: warning: initialization makes pointer from integer without a cast
test-dependency.c: In function ‘main’:
test-dependency.c:37: warning: initialization makes pointer from integer without a cast
Undefined symbols for architecture x86_64:
"_popdepholder", referenced from:
_removedepholderat in ccUGYlgF.o
_main in ccUGYlgF.o
ld: symbol(s) not found for architecture x86_64
collect2: ld returned 1 exit status

You've declared and defined popdepholer instead of popdepholder (missing the second d).

Perhaps you are attempting to link a 32-bit library into a 64-bit binary. Check that your makefile build process is linking in the correct library.

Related

Multiple definition error when compiling multiple C source files with GCC

I am writing a program in C that contains two source files, one containing main() and one containing function definitions. I also have a header file declaring the functions and variables so I don't have to pass variables back and forth. Here is the content of the files.
main.c:
#include <stdio.h>
#include "defs.h"
#include "sorting.c"
int main(int argc, char **argv){
listLength = 0;/*this is a load of barnacles*/
EOFFlag = 1;
input = fopen(argv[1], "r");
if(input == NULL){
printf("Could not open requested file.\n");
return -1;
}
while(EOFFlag){
sortNextWord();
}
if(FULLLISTCONSEQUENCES){
for(genericIterator = 0; genericIterator < USHRT_MAX + 1; genericIterator++){
printf("%d: %s; %d", genericIterator + 1, wordlist[genericIterator], wordcount[genericIterator]);
}
}else{
for(genericIterator = 0; genericIterator < listLength; genericIterator++){
printf("%d: %s; %d", genericIterator + 1, wordlist[genericIterator], wordcount[genericIterator]);
}
}
return 1;
}
sorting.c
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "defs.h"
int sortNextWord(){
getNextWord();
if(wordHolder[0] != '\0')/*checks to ensure that getNextWord didn't get an empty string*/
listMatch();
return 1;
}
int getNextWord(){
char charStore;
char returnFlag = 0;
genericIterator = 0;
while(genericIterator != USHRT_MAX){
switch(charStore = getc(input)){
case EOF:
EOFFlag = 0;
goto exitcond;/* checks for EOF or whitespace, exits loop if found*/
case ' ':
case '\n':
case '\t':
goto exitcond;
default:
wordHolder[genericIterator++] = charStore;/* otherwise it writes the character it read to the next available spot */
break;
}
}
exitcond:
wordHolder[genericIterator] = '\0';
wordlen = genericIterator;
return 1;
}
int listMatch(){/* runs through wordlist to find a matching word. If found, increments the respective wordcount entry, otherwise, creates new entry in wordlist */
for(genericIterator = 0; genericIterator < listLength; genericIterator++){
if(strcmp(wordHolder, wordlist[genericIterator])){
++wordcount[genericIterator];
goto foundmatch;
}
}
addToList();
foundmatch:
return 1;
}
int addToList(){ /*adds word to next available spot in wordlist*/
char *string;
if(FULLLISTCONSEQUENCES) /*doesnt do anything if wordlist is full */
return 0; /* John Freeman, who was Go */
if(listLength == USHRT_MAX)
FULLLISTCONSEQUENCES = 1;
string = malloc((wordlen + 1) * sizeof(char));
string[0] = '\0';
strncat(string, wordHolder, USHRT_MAX + 1);
wordcount[listLength] = 1;
wordlist[listLength++] = string;
return 1;`
}
defs.h (ignore the stuff about heapsort. I'm going to implement that to sort the wordlist, but i need to make sure this works first.
#ifndef DEFS_H
#define DEFS_H
#include <limits.h>
#include <stdio.h>
char *wordlist[USHRT_MAX + 1];
int wordcount [USHRT_MAX + 1];
unsigned short listLength;
unsigned short genericIterator;
FILE *input;
/*heapsort goes here */
char wordHolder[USHRT_MAX + 1];
unsigned short wordlen;
char EOFFlag;
char FULLLISTCONSEQUENCES;
int heapsort();
int buildMaxHeap();
int restoreMaxHeap();
int swap(unsigned short, unsigned short);
unsigned short getParent(unsigned short);
unsigned short getRightChild(unsigned short);
unsigned short getLeftChild(unsigned short);
int sortNextWord();
int getNextWord();
int listMatch();
int addToList();
#endif`
When I run those through gcc with the command
gcc -o wordsort main.c sorting.c
I get the following error:
/usr/bin/ld: /tmp/cc8X0W8R.o:(.bss+0x0): multiple definition of `wordlist'; /tmp/cc3dFw3Q.o:(.bss+0x0): first defined here
/usr/bin/ld: /tmp/cc8X0W8R.o:(.bss+0x80000): multiple definition of `wordcount'; /tmp/cc3dFw3Q.o:(.bss+0x80000): first defined here
/usr/bin/ld: /tmp/cc8X0W8R.o:(.bss+0xc0000): multiple definition of `listLength'; /tmp/cc3dFw3Q.o:(.bss+0xc0000): first defined here
/usr/bin/ld: /tmp/cc8X0W8R.o:(.bss+0xc0002): multiple definition of `genericIterator'; /tmp/cc3dFw3Q.o:(.bss+0xc0002): first defined here
/usr/bin/ld: /tmp/cc8X0W8R.o:(.bss+0xc0008): multiple definition of `input'; /tmp/cc3dFw3Q.o:(.bss+0xc0008): first defined here
/usr/bin/ld: /tmp/cc8X0W8R.o:(.bss+0xc0020): multiple definition of `wordHolder'; /tmp/cc3dFw3Q.o:(.bss+0xc0020): first defined here
/usr/bin/ld: /tmp/cc8X0W8R.o:(.bss+0xd0020): multiple definition of `wordlen'; /tmp/cc3dFw3Q.o:(.bss+0xd0020): first defined here
/usr/bin/ld: /tmp/cc8X0W8R.o:(.bss+0xd0022): multiple definition of `EOFFlag'; /tmp/cc3dFw3Q.o:(.bss+0xd0022): first defined here
/usr/bin/ld: /tmp/cc8X0W8R.o:(.bss+0xd0023): multiple definition of `FULLLISTCONSEQUENCES'; /tmp/cc3dFw3Q.o:(.bss+0xd0023): first defined here
/usr/bin/ld: /tmp/cc8X0W8R.o: in function `sortNextWord':
main.c:(.text+0x0): multiple definition of `sortNextWord'; /tmp/cc3dFw3Q.o:sorting.c:(.text+0x0): first defined here
/usr/bin/ld: /tmp/cc8X0W8R.o: in function `getNextWord':
main.c:(.text+0x2a): multiple definition of `getNextWord'; /tmp/cc3dFw3Q.o:sorting.c:(.text+0x2a): first defined here
/usr/bin/ld: /tmp/cc8X0W8R.o: in function `listMatch':
main.c:(.text+0xdf): multiple definition of `listMatch'; /tmp/cc3dFw3Q.o:sorting.c:(.text+0xdf): first defined here
/usr/bin/ld: /tmp/cc8X0W8R.o: in function `addToList':
main.c:(.text+0x191): multiple definition of `addToList'; /tmp/cc3dFw3Q.o:sorting.c:(.text+0x191): first defined here
collect2: error: ld returned 1 exit status
What is happening? I've only defined these functions once in sorting.c. Where did this error come from?
I've tried removing some of the #include headers, and I added the #ifndef statement to defs.h. Neither made any difference. I've also tried compiling and then linking as suggested in https://stackoverflow.com/questions/18777326/compiling-multiple-c-files-with-gcc`your text`

Dynamic Memory Allocation in C not working

I'm trying to make a game that requires dynamically sized arrays in C but my code isn't working even though identical code works in another one of my programs.
Here are my #includes
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "SwinGame.h" //API for graphics, physics etc
#include <math.h>
Here are my typedefs for the relevant structs used:
typedef struct position_data
{
double x;
double y;
} position_data;
typedef enum enemy_type_data {CIRCLE, TRIANGLE, SQUARE} enemy_type_data;
typedef struct enemy_data
{
position_data location;
enemy_type_data type;
bitmap bmp;
double health;
double speed;
int path_to;
} enemy_data;
typedef struct enemy_data_array
{
int size;
enemy_data *data;
} enemy_data_array;
Here is the function to add an element to the array:
void add_enemy(enemy_data_array *enemies)
{
enemy_data *new_array;
enemies->size++;
new_array = (enemy_data *)realloc(enemies->data, sizeof(enemy_data) * enemies->size);
if (new_array) //if realloc fails (ie out of memory) it will return null
{
enemies->data = new_array;
// enemies->data[enemies->size - 1] = read_enemy_data();
printf("Enemy added successfully!\n");
}
else
{
printf("FAILED. Out of Memory!\n");
enemies->size--;
}
}
And here is my function call and variable declaration in the main procedure:
int main()
{
path_data my_path[41];
enemy_data_array enemies;
enemies.size = 0;
add_enemy(&enemies);
}
Why isn't this working?
You invoked undefined behavior by passing indeterminate value enemies->data in uninitialized variable having automatic storage duration. Initialize it before using add_enemy().
int main()
{
path_data my_path[41];
enemy_data_array enemies;
enemies.size = 0;
enemies.data = 0; /* add this line */
add_enemy(&enemies);
}
0 is a null pointer constant and can safely be converted to pointer NULL. Unlike NULL, 0 will work without including any headers. Of course you can use enemies.data = NULL; with proper header included.
#2501's explanation is completely correct. Another solution is to change your implementation of add_enemy() to something like this:
void add_enemy(enemy_data_array *enemies)
{
enemy_data *new_array;
// check if size was non-zero
if (enemies->size++)
{
new_array = (enemy_data *)realloc(enemies->data, sizeof(enemy_data) * enemies->size);
}
// start new allocation
else
{
new_array = (enemy_data *)alloc(sizeof(enemy_data) * enemies->size);
}
if (new_array) //if (re)alloc fails (ie out of memory) it will return null
{
enemies->data = new_array;
// enemies->data[enemies->size - 1] = read_enemy_data();
printf("Enemy added successfully!\n");
}
else
{
printf("FAILED. Out of Memory!\n");
enemies->size--;
}
}
If fails because you haven't cleared the content of "enemies". Since it is a stack variable, it will contain whatever garbage data is on the stack.
set enemies.data to NULL in the main function and try it again.

Multiple definitions and First defined error

I have written a small C program which is assembled of several files.
When I compile, I get an error for "multiple definitions".
My main.c:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "general_structs.h"
#define FOREVER for(;;)
#define INPUT_LEN 30
int main()
{
char command[INPUT_LEN];
char *func;
int i;
int t;
FOREVER
{
if(scanf("%s", command) == 1)
{
func = strtok(command, " ");
for(i=0;cmd[i].func != NULL;i++)
{
if(strcmp(func, cmd[i].name) == 0)
{
(*((cmd[i].func)));
t = 1;
}
}
if(t == 1)
{
printf("No such command");
}
}
}
return 0;
}
My mat.c file:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "general_structs.h"
#define LENGTH 100
#define SIXTEEN 16
#define SIZE 4
void read_mat()
{
int i = 0;
int j = 0;
int k = 0;
char tmp_name[LENGTH];
char num_buffer[LENGTH];
char *token;
double num_list[16];
double tmp_num = 0;
scanf("%[^,], %s", tmp_name, num_buffer);
token = strtok(num_buffer, ",");
while(token != NULL)
{
if(strcmp(token, "0") == 0)
{
num_list[i] = 0;
}
else
{
tmp_num = atof(token);
if(tmp_num == 0)
{
printf("Error in parameter: %d\n", (i-1));
break;
}
else
{
num_list[i] = tmp_num;
}
}
i++;
token = strtok(NULL, ",");
}
if(!strcmp(tmp_name, "MAT_A"))
{
for(i=0;i<SIZE;i++)
for(j=0;j<SIZE;j++)
{
mats[0].mat[0][i][j] = num_list[k];
k++;
}
}
else if(!strcmp(tmp_name, "MAT_B"))
{
for(i=0;i<SIZE;i++)
for(j=0;j<SIZE;j++)
{
mats[1].mat[0][i][j] = num_list[k];
k++;
}
}
else if(!strcmp(tmp_name, "MAT_C"))
{
for(i=0;i<SIZE;i++)
for(j=0;j<SIZE;j++)
{
mats[2].mat[0][i][j] = num_list[k];
k++;
}
}
else if(!strcmp(tmp_name, "MAT_D"))
{
for(i=0;i<SIZE;i++)
for(j=0;j<SIZE;j++)
{
mats[3].mat[0][i][j] = num_list[k];
k++;
}
}
else if(!strcmp(tmp_name, "MAT_E"))
{
for(i=0;i<SIZE;i++)
for(j=0;j<SIZE;j++)
{
mats[4].mat[0][i][j] = num_list[k];
k++;
}
}
else if(!strcmp(tmp_name, "MAT_F"))
{
for(i=0;i<SIZE;i++)
for(j=0;j<SIZE;j++)
{
mats[5].mat[0][i][j] = num_list[k];
k++;
}
}
else
{
printf("No such matrix name.");
}
}
My general_structs.h file:
#define SIZE 4
#define SIZE_NAME 5
#define SIZE_FUNC 10
typedef double matrix[SIZE][SIZE];
matrix MAT_A, MAT_B, MAT_C, MAT_D, MAT_E, MAT_F;
void read_mat(void);
struct
{
char name[SIZE_NAME];
matrix *mat;
} mats[] = {
{"MAT_A", &MAT_A},
{"MAT_B", &MAT_B},
{"MAT_C", &MAT_C},
{"MAT_D", &MAT_D},
{"MAT_E", &MAT_E},
{"MAT_F", &MAT_F},
{"non", NULL}
};
struct
{
char name[SIZE_FUNC];
void (*func)(void);
} cmd[] = {
{"read_mat", read_mat},
{"not_valid", NULL}
};
My make file:
int_loop: my_math.o int_loop.o
gcc -g -ansi -Wall -pedantic my_math.o int_loop.o -o int_loop
int_loop.o : int_loop.c
gcc -c -ansi -Wall -pedantic int_loop.c -o int_loop.o
my_math.o : my_math.c
gcc -c -ansi -Wall -pedantic my_math.c -o my_math.o
I have been trying to solve this issue with various techniques but yet with no success.
The error I recieve is:
gcc -g -Wall -ansi -pedantic main.o mat.o -o mamantest
mat.o:(.data+0x0): multiple definition of `mats'
main.o:(.data+0x0): first defined here
mat.o:(.data+0x70): multiple definition of `cmd'
main.o:(.data+0x70): first defined here
collect2: ld returned 1 exit status
make: *** [mamantest] Error 1
Why does this error occurs? How do I solve this?
Thanks
In the header file you define the variables mats and cmd, meaning both translation units (both source files that includes the header file) will have those defined.
The variables should be defined only in a single place, in a single source file, like
struct mat mats[7] = { ... };
The above defines the array mats, and like I said should be done in only one place.
For the other source file you declare the variables, which can be done in the header file like e.g.
extern struct mat
{
...
} mats[7];
The above declare the variable mats as an array of seven mat structures. It also define the structure so it can be used to e.g. define the array.
After modifications suggested above, the complete header file should look something like
// First header include guards (see https://en.wikipedia.org/wiki/Include_guard)
#ifndef GENERIC_STRUCTS_H
#define GENERIC_STRUCTS_H
#define SIZE 4
#define SIZE_NAME 5
#define SIZE_FUNC 10
typedef double matrix[SIZE][SIZE];
// Declare the variables (note the added use of the extern keyword)
extern matrix MAT_A, MAT_B, MAT_C, MAT_D, MAT_E, MAT_F;
void read_mat(void);
// Define a structure named mat (note added structure tag name)
struct mat
{
char name[SIZE_NAME];
matrix *mat;
};
// Define a structure named command (note added structure tag name)
struct command
{
char name[SIZE_FUNC];
void (*func)(void);
};
// Now declare variables of the previous structures
extern struct mat mats[7];
extern struct command cmd[2];
// End of header include guard
#endif
That header file only declares variables, and can be included in all your source files.
Then in a single source file (for example your main.c file) you do the actual variable definitions:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "general_structs.h"
matrix MAT_A, MAT_B, MAT_C, MAT_D, MAT_E, MAT_F;
struct mat mats[7] = {
{"MAT_A", &MAT_A},
{"MAT_B", &MAT_B},
{"MAT_C", &MAT_C},
{"MAT_D", &MAT_D},
{"MAT_E", &MAT_E},
{"MAT_F", &MAT_F},
{"non", NULL}
};
struct command cmd[2] = {
{"read_mat", read_mat},
{"not_valid", NULL}
};
#define FOREVER for(;;)
#define INPUT_LEN 30
int main()
{
...
}
The important thing you need to learn here is that there is a difference between declaring and defining something.
A declaration is basically telling the compiler that "this thing exists somewhere", and a definition is telling the compiler "this is the thing".
The problem is that unless a thing has already been declared, a definition is also a declaration, and many simply call these combined definitions/declarations just declaration, which muddles the whole concept up a bit.

compiler warning of rpcgen program in ubuntu

I am new in programming with rpcgen. I created a simple rpc program which provides a remote directory listing service in Ubuntu 14.04. It uses rpcgen not only to generate stub routines, but also to generate the XDR routines.
First, the protocol file
const MAXNAMELEM = 255;
typedef string nametype<MAXNAMELEM>; /*a directory entry*/
typedef struct namenode *namelist; /*a link in the listing*/
/*a node in the directory listing*/
struct namenode {
nametype name; /*name of directory entry*/
namelist next; /*next entry*/
};
/*the result of READDIR operation*/
union readdir_res switch (int errornumber) {
case 0:
namelist list; /*no error: return directory listing*/
default:
void; /*error occurred: nothing else to return*/
};
/*the directory program definition*/
program DIRPROG {
version DIRVERS {
readdir_res READDIR(nametype) = 1;
} = 1;
} = 76;
The server:
#include <rpc/rpc.h>
#include <sys/dir.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include "rdir.h"
readdir_res *readdir_1_svc(nametype *dirname, struct svc_req *req)
{
DIR *dirp = NULL;
struct direct *d = NULL;
namelist nl;
namelist *nlp = NULL;
static readdir_res res; /*must be static*/
/*open directory*/
dirp = opendir(*dirname);
if (dirp == NULL)
{
res.errornumber = errno;
return (&res);
}
/*Free previous result*/
xdr_free(xdr_readdir_res, &res);
nlp = &res.readdir_res_u.list;
while (d = readdir(dirp))
{
nl = *nlp = (namenode*)malloc(sizeof(namenode));
nl->name = strdup(d->d_name);
nlp = &nl->next;
}
*nlp = NULL;
res.errornumber = 0;
closedir(dirp);
return (&res);
}
The client:
#include <stdio.h>
#include <rpc/rpc.h>
#include "rdir.h"
int main(int argc, char *argv[])
{
CLIENT *cl;
char *server = NULL;
char *dir = NULL;
readdir_res *result = NULL;
namelist nl;
if (argc != 3)
{
fprintf(stderr, "usage: %s host directory\n", argv[0]);
exit(1);
}
/*remember what our command line arguments refer to*/
server = argv[1];
dir = argv[2];
cl = clnt_create(server, DIRPROG, DIRVERS, "tcp");
if (cl == NULL)
{
clnt_pcreateerror(server);
exit(1);
}
result = readdir_1(&dir, cl);
if (result == NULL)
{
clnt_perror(cl, server);
exit(1);
}
if (result->errornumber != 0)
{
perror(dir);
exit(1);
}
for (nl = result->readdir_res_u.list; nl!=NULL; nl=nl->next)
{
printf("%s\n", nl->name);
}
return 0;
}
Then I compile them:
rpcgen rdir.x
gcc rls.c rdir_clnt.c rdir_xdr.c -o rls
gcc rdir_svc.c dir_proc.c rdir_xdr.c -o dir_svc
When I compile with instruction:
gcc rdir_svc.c dir_proc.c rdir_xdr.c -o dir_svc
I got the following warnings:
esta#esta-U48L:~/Learning/rpcgen/dir_ls$ gcc rdir_svc.c dir_proc.c rdir_xdr.c -o dir_svc
dir_proc.c: In function ‘readdir_1_svc’:
dir_proc.c:27:2: warning: passing argument 1 of ‘xdr_free’ from incompatible pointer type [enabled by default]
xdr_free(xdr_readdir_res, &res);
^
In file included from /usr/include/rpc/rpc.h:42:0,
from dir_proc.c:1:
/usr/include/rpc/xdr.h:373:13: note: expected ‘xdrproc_t’ but argument is of type ‘bool_t (*)(struct XDR *, struct readdir_res *)’
extern void xdr_free (xdrproc_t __proc, char *__objp) __THROW;
^
dir_proc.c:27:2: warning: passing argument 2 of ‘xdr_free’ from incompatible pointer type [enabled by default]
xdr_free(xdr_readdir_res, &res);
^
In file included from /usr/include/rpc/rpc.h:42:0,
from dir_proc.c:1:
/usr/include/rpc/xdr.h:373:13: note: expected ‘char *’ but argument is of type ‘struct readdir_res *’
extern void xdr_free (xdrproc_t __proc, char *__objp) __THROW;
^
Could anybody help me out with the warning?
P.S. The program run just fine even with those warnings.
You can safely cast the arguments you pass to xdr_free:
xdr_free((xdrproc_t)xdr_readdir_res, (char *)&res);

warning: ‘return’ with a value, in function returning void return next; ex19.c:95:10: error: void value not ignored as it ought to be

I am going through the Learn Code the hard way book and stuck on exercise 19 http://c.learncodethehardway.org/book/ex19.html. I got desperate, copied and pasted the code, yet still I am getting errors:
cc -Wall -g ex19.c object.o -o ex19
ex19.c: In function ‘Room_move’:
ex19.c:65:5: warning: ‘return’ with a value, in function returning void
return next;
^
ex19.c: In function ‘Map_move’:
ex19.c:95:10: error: void value not ignored as it ought to be
next = location->_(move)(location, direction);
^
ex19.c: In function ‘Room_attack’:
ex19.c:145:5: warning: initialization from incompatible pointer type
.move = Map_move,
^
ex19.c:145:5: warning: (near initialization for ‘MapProto.move’)
ex19.c:199:5: warning: ‘main’ is normally a non-static function [-Wmain]
int main(int argc, char *argv[])
^
ex19.c:214:1: error: expected declaration or statement at end of input
}
^
ex19.c:214:1: error: expected declaration or statement at end of input
ex19.c:214:1: warning: control reaches end of non-void function [-Wreturn-type]
}
This is what I got:
void Room_move(void *self, Direction direction)
{
Room *room = self;
Room *next = NULL;
if(direction == NORTH && room->north) {
printf("You go north, into:\n");
next = room->north;
} else if(direction == SOUTH && room->south) {
printf("You go south, into:\n");
next = room->south;
} else if(direction == EAST && room->east) {
printf("You go east, into:\n");
next = room->east;
} else if(direction == WEST && room->west) {
printf("You go west, into:\n");
next = room->west;
} else {
printf("You can't go that direction.");
next = NULL;
}
if(next) {
next->_(describe)(next);
}
return next;
}
void *Map_move(void *self, Direction direction)
{
Map *map = self;
Room *location = map->location;
Room *next = NULL;
next = location->_(move)(location, direction);
if(next) {
map->location = next;
}
return next;
}
int main(int argc, char *argv[])
{
// simple way to setup the randomness
srand(time(NULL));
// make our map to work with
Map *game = NEW(Map, "The Hall of the Minotaur.");
printf("You enter the ");
game->location->_(describe)(game->location);
while(process_input(game)) {
}
return 0;
}
This line:
void Room_move(void *self, Direction direction)
should be:
void *Room_move(void *self, Direction direction)
This is the case on the page you linked, so you messed up while copy/pasting the code.
You're missing up a pointer variable while specifying the return type for Room_move() function. You need to use
void* Room_move(void *self, Direction direction)
instead of void Room_move(void *self, Direction direction).
void* Room_move() makes the return type as void *, but void Room_move() essentially means a void return. Side effect:
warning: ‘return’ with a value, in function returning void
error: void value not ignored as it ought to be
So, as you can see, a void and void* are not the same.

Resources