EDIT: To try and make things easier for the kind souls trying to help me, here are a couple links that should make things more clear:
Pre-makefile repl
Post-makefile repl
A little background on the assignment: We are supposed to take a program we wrote last week and break up the separate functions into their own files and use a makefile to compile and link and all that stuff. This is my original program (basically, it reads a file of name number and stores them in a struct, then uses the command line arguments to search for a name).
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct _data {
char* name;
long number;
};
int SCAN(FILE *(*input)) {
int lines = 0;
char word[50];
long num = 0;
while (1) {
fscanf(*input,"%s %ld",word, &num);
lines++;
if (feof(*input)) break;
}
return lines;
}
struct _data *LOAD(FILE *input, int size) {
char* line = NULL;
size_t len = 0;
int i=0;
rewind(input);
struct _data *book = calloc(size,sizeof(struct _data));
for (i = 0;i<size;i++) {
getline(&line, &len, input);
book[i].name = calloc(len+1,sizeof(char));
strcpy(book[i].name,strtok(line," "));
book[i].number = atoi(strtok(NULL, " "));
}
return book;
}
void SEARCH(struct _data *BlackBook, char *name, int size) {
int i;
for (i=0;i<size;i++) {
if (strcmp(name,BlackBook[i].name) == 0) {
printf("*******************************************\n");
printf("The name was found at the %d entry.\n",i+1);
printf("*******************************************\n");
break;
}
//If we reach the end of the array and name was not found
if (i == size-1) {
printf("*******************************************\n");
printf("The name was NOT found.\n");
printf("*******************************************\n");
}
}
}
void FREE(struct _data *BlackBook, int size) {
int i;
for (i=0;i<size;i++){
free(BlackBook[i].name);
}
free(BlackBook);
}
//MAIN DRIVER ===================
int main(int argv, char** argc) {
int size;
char* filename = "hw5.data";
FILE *input = fopen(filename,"r");
size = SCAN(&input);
struct _data *phone_book = LOAD(input,size);
fclose(input);
//Check a name is given. If so, search
if (argv < 2) {
printf("*******************************************\n");
printf("* You must include a name to search for. *\n");
printf("*******************************************\n");
} else {
SEARCH(phone_book, argc[1], size);
}
FREE(phone_book,size);
return 0;
}
When I make my makefile, I can get the SCAN and LOAD functions to work appropriately. But, when I try to put either SEARCH or FREE into their own files, my compiler freaks out and I get warnings like:
In file included from hw6-free.c:1:0:
hw6-free.h:9:18: warning: ‘struct _data’ declared inside parameter list
void FREE(struct _data *BlackBook, int size);
^
hw6-free.h:9:18: warning: its scope is only this definition or declaration, which is probably not what you want
hw6-free.c:3:18: warning: ‘struct _data’ declared inside parameter list
void FREE(struct _data *BlackBook, int size) {
^
hw6-free.c:3:6: error: conflicting types for ‘FREE’
void FREE(struct _data *BlackBook, int size) {
^
In file included from hw6-free.c:1:0:
hw6-free.h:9:6: note: previous declaration of ‘FREE’ was here
void FREE(struct _data *BlackBook, int size);
^
hw6-free.c: In function ‘FREE’:
hw6-free.c:6:5: error: invalid use of undefined type ‘struct _data’
free(BlackBook[i].name);
^
hw6-free.c:6:19: error: dereferencing pointer to incomplete type ‘struct _data’
free(BlackBook[i].name);
^
Makefile:20: recipe for target 'hw6-free.o' failed
make: *** [hw6-free.o] Error 1
And reading through it, it looks like the fact my program takes a struct as an argument is my main problem? My 'post-makefile' program looks like:
#include "hw6-main.h"
int main(int argv, char** argc) {
int size;
char* filename = "hw5.data";
FILE *input = fopen(filename,"r");
size = SCAN(&input);
struct _data *phone_book = LOAD(input,size);
fclose(input);
//Check a name is given. If so, search
if (argv < 2) {
printf("*******************************************\n");
printf("* You must include a name to search for. *\n");
printf("*******************************************\n");
} else {
SEARCH(phone_book, argc[1], size);
}
FREE(phone_book,size);
return 0;
}
And my makefile looks like:
DEP = hw6-scan.o hw6-load.o hw6-search.o hw6-free.o hw6-main.o
HDR = hw6-scan.h hw6-load.h hw6-search.h hw6-free.h hw6-main.h
NAME = output
all: $(NAME)
output: $(DEP) $(HDR)
gcc $(DEP) $(HDR) -o $(NAME)
hw6-scan.o: hw6-scan.c
gcc -c hw6-scan.c
hw6-load.o: hw6-load.c
gcc -c hw6-load.c
hw6-search.o: hw6-search.c
gcc -c hw6-search.c
hw6-free.o: hw6-free.c
gcc -c hw6-free.c
hw6-main.o: hw6-main.c
gcc -c hw6-main.c
clean:
rm *.o *.gch *.out output testfile
As an example, my hw6-free.c and hw6-free.h look like:
#include "hw6-free.h"
void FREE(struct _data *BlackBook, int size) {
int i;
for (i=0;i<size;i++){
free(BlackBook[i].name);
}
free(BlackBook);
}
and
#include <stdio.h>
#include <stdlib.h>
void FREE(struct _data *BlackBook, int size);
respectively.
And, finally, I defined the struct in the hw6-load.h file, along with a function prototype. Is that also a problem? Should I be defining it elsewhere?
I am SO SORRY for the long post, but I have been working on the for 10 hours and I'm about to throw my computer of a cliff.
THANK YOU FOR YOUR HELP STACK OVERFLOW!
This is an in-depth explanation of the details. It might be a bit too much, but if you keep reading, you may get a much deeper understanding of the language than if you just learn to write code that your compiler is ok with.
You are using your struct before you have declared it. Keep in mind that an #include is just a fancy way of telling your compiler: "Please, paste the contents of this .h file at this spot." The result of this pasting must read like valid code to the compiler.
It is true that the compiler's error message looks a bit weird. It certainly does not say "You used struct _data before you declared it". The reason for this is, that structs are implicitly declared at their first use. So, if you declare a variable with struct foo* bar; and the compiler has never seen a struct foo before, it will immediately consider struct foo as being declared, and a pointer variable to this struct foo of unknown size and shape will be defined. Likewise, when your compiler sees the function declaration
void foo(struct bar *baz);
it sees that it doesn't know a struct bar and implicitly declares one. Because this struct declaration happens inside a function declaration, the resulting type is declared local to the declaration at hand. As such, it is impossible for calling code to pass an argument of the correct type into this function, or even to implement the function in a separate statement. Such a function declaration is always useless. This is what the warning text "its scope is only this definition or declaration, which is probably not what you want" means: The compiler writers knew that such a declaration is bullshit, but it's legal C as far as the standard is concerned, so they compile it, but warn about it.
Ok, let's get to the actual error message. As the compiler tells you, the struct _data was only declared for the function declaration at hand. When your compiler later sees the function implementation, it stumbles across the undeclared struct _data a second time. Again, it implicitly declares a local struct type which is distinct from the previously implicitly declared type. Because those two implicitly declared types are distinct, so are the signatures of the declared functions. However, C mandates that a function can only have one signature, so the compiler produces the error "conflicting types for ‘FREE’".
You can try this out with this simple code:
void foo(struct bar* baz); //warning: local declaration of `struct bar`
void foo(struct bar* baz); //repeated warning + conflicting types error
So, how to fix this?
Simple. Declare your struct before you use it. That way you avoid its implicit declaration. The following code compiles fine:
struct bar; //global declaration of `struct bar`
void foo(struct bar* baz); //`struct bar` is known and the global declaration is used
void foo(struct bar* baz); //same as above, because this uses the same global declaration of `struct bar`, this redeclaration of `foo()` is ok
The declaration of the struct _data belongs into the header file that declares the functions which use struct _data as arguments.
Idiomatic declarations
Usually, types are declared with a typedef. This allows the code to omit the struct keyword when declaring variables. This takes one of two idiomatic forms:
To have a type with public members (pure data, no object in the OO sense), put the struct definition into the header:
typedef struct foo //`struct foo` is declared implicitly here
{ //it is also defined (= inner details are given) right here
int bar; //its member variables are defined
} baz; //this concludes the typedef, giving `struct foo` a second name
//`struct foo` and `baz` are now equivalent.
Usually, the two names will be the same or very similar, so the cleaned definition looks like this:
typedef struct foo {
int bar;
} foo;
//declarations of the functions that use `struct foo`
...
If the type is an object that should keep its data members to itself, the declaration and definitions are split like this:
Inside foo.h:
typedef struct foo foo; //declare that `struct foo` == `foo` exists, but don't give details
//declare the functions working on a `foo`
void foo_bim(foo* me);
void foo_bam(foo* me, ...);
...
Inside foo.c:
#include "foo.h" //so that the compiler may check that the function declarations in the header agree with the implementations in this file
struct foo { //define the size and shape of `struct foo` == `foo`
int bar;
};
//now only this file knows how a `struct foo` actually looks like
//implement the member functions of `foo`
void foo_bim(foo* me) {
...
}
void foo_bam(foo* me, ...) {
...
}
Note that the typedef ... non-struct-name; is purely optional in both cases, and there are quite a few programmers who want to see the struct keyword wherever a struct is used (like a certain Mr. Torvalds). These programmers simply leave off the typedef ... non-struct-name; part, otherwise they use the idioms above in the same way. I have described the full-featured version here, to ensure that you'll not be surprised when you first see the typedef construct.
I'm not sure what you did. But to step back: keep clear in your mind the difference between declarations and definitions. A declaration shows a variable or function signature, but does not create any variables of that type or implement that function. A definition declares a new variable (of some type) or implements a function. A declaration of a type just states that it exists (basically). A definition of a type shows its structure and members.
So, a definition of your type would be:
struct _data {
char* name;
long number;
};
And a declaration of a function would be:
void FREE(struct _data *BlackBook, int size);
and a definition of a function would be:
void FREE(struct _data *BlackBook, int size) {
int i;
for (i=0;i<size;i++){
free(BlackBook[i].name);
}
free(BlackBook);
}
So here're the rules:
Only #include header files in other files, never #include source files.
If a type is needed in more than one file, put its definition into a header file and #include that header file in all source files that use the type.
If a function is used in more than one file, put the declaration of that function into a header file and #include that header file in all the source files that use the function, including the source file containing the definition of the function.
If you follow these rules you'll never run into duplicate definitions at link time: you can't have duplicate definitions if you link each source file only one time and no included file contains a definition.
Type declarations can be useful, and breaking some of these rules can be useful, but for the work you're doing that's probably not worth worrying about.
Try to put header of struct declaration at top of files which uses it and be sure you’ve imported the file which contains struct declaration.
I have declared:
#include stdio.h
#include stdlib.h
#include string.h
#include dictionary.h
int main( int argc, char ** argv ){
char * dictionary_name = DEFAULT_DICTIONARY;
dictionary_t dictionary;
dictionary->entries = 1;
if ( dictionary == NULL){
printf("NULL\n");
return -1;
}
return 0;
}
Error:
src/main.c: In function ‘main’:
src/main.c:40:12: error: dereferencing pointer to incomplete type ‘struct dictionary_s’
dictionary->entries = 1;
In dictionary.c:
#include dictionary.h
struct dictionary_s{
char * name;
llist_t content;
int entries;
};
In header (dictionary.h):
typedef struct dictionary_s* dictionary_t;
It's my first time asking a question in here, so, please forgive me if I'm missing something important.
The file dictionary.h only contains the name of the type struct dictionary_s, so that is all that is visible to your main function. This means it doesn't know what the structure contains.
You need to move the definition of struct dictionary_s into the header file. That way it can be used from main.
You have to place the definition of the struct in the header file, not in the dictionary.c-file; otherwise, its components are not known outside of dictionary.c.
So your dictionary.h should look as follows:
struct dictionary_s{
char * name;
llist_t content;
int entries;
};
typedef struct dictionary_s* dictionary_t;
Your file dictionary.c is probably obsolete then.
Can you explain why the struct Test is incomplete and how to remove the error? Is the error related to declaration in test.h or to definition in test.c? I tried to move the definition code to header file but then createTest does not know type Test or if I move the function to header there is the error multiple definition of createTest
test.h
typedef struct STest Test;
test.c
typedef struct STest {
int v;
char *str;
}Test;
Test *createTest(int v,char *str) {
Test *t=(Test*)malloc(sizeof(Test));
t->v=v; // error
t->str=str; // error
return t;
}
main function (main.c)
error:
main.c|44|error: dereferencing pointer to incomplete type
Put
typedef struct STest {
int v;
char *str;
} Test;
into test.h.
typedef struct STest Test only says that Test is another name for struct STest. At the moment, that's all that main.c knows. Especially, main.c doesn't know which members the struct has. That sounds quite incomplete to me.
If you don't define the structure in the header file it will not be visible from your main.c.
You need to do the following
Point 1. Put the structure definition in the test.h header file. use include guard also.
#ifndef __MY_HDR_H_
#define __MY_HDR_H_
typedef struct STest {
int v;
char *str;
}Test;
#endif //__MY_HDR_H_
[EDIT: Also, you need to add the function prototype for createTest() in the .h file]
Point 2. include test.h in test.c and main.c.
Point 3. Compile using
gcc main.c test.c -o output
Standard Warning : Please do not cast the return value of malloc() and family.
Place the code in the header file.
typedef struct STest {
int v;
char *str;
} Test;
Because compiler doesn't know to dereference that.
Hint: Then don't cast the result of malloc.
You seem to define Test twice.
In test.h you do
typedef struct STest Test;
Inside test.c remove the typedef and just do:
struct STest {
int v;
char *str;
};
A full example below:
To define an opaque type, a type which is know in detail only to the translation unit implementing its functions, you might take the following approach:
opaque.h
#ifndef OPAQUE_H
#define OPAQUE_H
typedef struct S T;
T * createT(int, char *);
#endif
opaque.c
include <stdlib.h>
#include "opaque.h"
struct S
{
int i;
char * p;
};
T * createT(int i, char * p)
{
T * t = malloc(sizeof *t);
if (NULL != t)
{
t->i = i;
t->p = p;
}
return t;
}
And use it like follows:
#include "opaque.h"
int main(void)
{
T * t = createT(0, NULL);
}
I've been pouring over this issue trying to figure out what is causing these errors, but so far I've come up with nothing. I have this function:
struct token scanToken(struct matrix refTable){
struct token send;
int counter = 0;
int currState = refTable.start;
while (1) {
printf("%d ", currState);
char c = getchar();
send.buffer[counter] = c;
int class = classifyChar(c);
char result = refTable.grid[class][currState].action;
currState = refTable.grid[class][currState].nextState;
if (currState = 99){
findEnd();
send.recrej = 'd';
return send;
}
else if (currState = refTable.accept){
if (c == EOF){
send.isEnd = 't';
}
else{
send.isEnd = 'f';
send.recrej = 'a';
}
}
++counter;
}
return send;
}
It is matched with the following header file:
struct token {
char buffer[512];
char recrej;
char isEnd;
};
void findEnd(void);
struct token scanToken(struct matrix refTable);
int classifyChar(char c);
This code is currently used in this snippet in my main function:
struct matrix table;
table = buildMatrix(argv[1]);
char c;
int class;
struct token found;
found = scanToken(table);
while(found.isEnd != 't'){
if (found.recrej == 'a'){
printf("recognized '%s'\n", found.buffer);
}
else {
printf("rejected\n");
}
found = scanToken(table);
}
the matrix struct is prototyped in another header file, which is included in the scanner.c file (pictured first), and the tokenize.c file (pictured last). However, this produces the following warnings and errors.
In file included from scanner.c:10:0:
scanner.h:16:31: warning: 'struct matrix' declared inside parameter list [enabled by default]
struct token scanToken(struct matrix refTable);
^
scanner.h:16:31: warning: its scope is only this definition or declaration, which is probably not what you want [enabled by default]
scanner.c:60:14: error: conflicting types for 'scanToken'
struct token scanToken(struct matrix refTable){
^
In file included from scanner.c:10:0:
scanner.h:16:14: note: previous declaration of 'scanToken' was here
struct token scanToken(struct matrix refTable);
I've been searching for quite some time, and have tried rewriting things a number of ways, with the same result all around. Any help would be greatly appreciated. Thank you.
You have to declare struct matrix outside a function prototype, like the error message implies.
You have in your scanner.h header:
struct token scanToken(struct matrix refTable);
Since there's no prior declaration of struct matrix in that header, or a header read before it is read, the struct matrix is a new distinct type. It's also incomplete, so you really need to use a pointer to it.
You can fix it as simply as:
struct matrix;
struct token scanToken(struct matrix *refTable);
To be able to pass the struct matrix by value instead of by pointer, you need a full definition of the structure, but pointers can be passed to incomplete types.
Or include the header that defines the struct matrix fully in the scanner.h header.
Note that you should protect your headers with multiple inclusion guards:
#ifndef SCANNER_H_INCLUDED
#define SCANNER_H_INCLUDED
…current contents…
#endif // SCANNER_H_INCLUDED
You might well add #include "otherheader.h" in that one — the other header that defines struct matrix in full.
Here is the case. In the file "fileA.c" I have
typedef struct MY_STRUCT
{
int A;
int B;
int C;
}MY_STRUCT;
MY_STRUCT Data;
/* Function */
int function(MY_STRUCT *params)
{
int varA, varB, varC;
varA = params->A;
varB = params->B;
varC = params->C;
}
And I need to fill the struct elements from other routine, for instance, "fileB.c" which contains the following:
extern MY_STRUCT Data;
int function(MY_STRUCT *params);
/* Function */
void userMain(void)
{
Data.A = 1254;
Data.B = 5426;
Data.C = 1236;
function(&Data);
}
But I'm getting the error:
"[Error] fileB.c E208: syntax error - token ";" inserted before "Data"
And whe I cross probe the error the compiler take me to the declaration "extern MY_STRUCT Data;"
So my question is how do I accomplish this functionality? I mean, how do I fill the elements of the structure from another function in another file different from the file where I declared the struct?
When the compiler is compiling fileB.c, it doesn't know about the typedef that you've defined in fileA.c. So in fileB.c, MY_STRUCT is an unknown type.
You should move the typedef to a common header, and include it in fileA.c and fileB.c.
Elaborating a bit on #pb2q answer:
Create a filea.h file with (omitting the defines and stuff):
struct MY_STRUCT
{
(blah blah blah ...)
};
extern MY_STRUCT Data;
This will declare the struct and tell whoever wants to know that the variable is declared in another file. Then put in filea.c the following lines
#include "filea.h" // near the top
(...)
MY_STRUCT Data; // Somewhere meaningful
This will actually declare the variable Data. Finally, in file "fileb.c" type
#include "filea.h"
that allows you to use the variable Data.