C program not compiling when using headers - c

(C PROGRAM) I'm trying to compile a main.c that uses a header but I'm getting the errors below.
When I don't use the header (all methods in the main file) everything works.
In a string S, the program find all words occurrences and returns the word that appears the most.
I'm compiling using: gcc main.c
Thank you.
errors
In file included from main.c:9:0:
frequence.h:4:16: warning: useless storage class specifier in empty declaration [enabled by default]
main.c: In function ‘main’:
main.c:15:10: error: variable ‘word’ has initializer but incomplete type
main.c:15:10: warning: passing argument 1 of ‘show_all_words’ from incompatible pointer type [enabled by default]
frequence.h:6:17: note: expected ‘char *’ but argument is of type ‘char (*)[34]’
main.c:15:10: error: invalid use of undefined type ‘struct stat_mot’
main.c:15:19: error: storage size of ‘word’ isn’t known
main.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "frequence.h"
#define LONGUEURMAX 4
int main(char *argv[]) {
char texte[] = ";! one two, tree foor one two !:;";
struct stat_mot word = show_all_words(&texte);
printf("%s : %d\n", word.word, word.frequency);
return (EXIT_SUCCESS);
};
frequence.h
#ifndef DEF_FREQUENCE
#define DEF_FREQUENCE
typedef struct stat_mot;
int count_word(char * , char * );
struct stat_mot show_all_words(char *);
#endif
frequence.c
#include "frequence.h"
typedef struct stat_mot {
char * word;
int frequency;
} stat_mot;
int count_word(char * mot, char * text) {
int n = 0;
char *p;
p = strstr(text, mot);
while (p != NULL) {
n++;
p = strstr(p + 1, mot);
}
return n;
}
stat_mot show_all_words(char * text) {
char * text_rw = strdup(text);
char * p = strtok(text_rw, " .,;:-!?");
char word_to_return[strlen(text)];
int word_frequence = 0;
while (p != NULL) {
if (strlen(p) >= 0) {
int offset = p - text;
int count = count_word(p, text);
if (word_frequence < count) {
strcpy(word_to_return, p);
word_frequence = count;
}
};
p = strtok(NULL, " .,;:-!?");
}
free(text_rw);
struct stat_mot word = { word_to_return, word_frequence };
return word;
}

At the least, you need to move the definition of stat_mot from frequence.c to frequence.h. main() tries to create an instance of it, you can't do that without the struct definition.
There are some other issues too:
I find it hard to believe that the type mismatch between char* and char(*)[34] is resolved by putting everything into one file. So I expect the fix has nothing to do with your organization of the code into files, it's just that you should pass texte, not &texte.
"useless storage class specifier in empty declaration" -- is a confusing error message, but it comes about because in the C syntax typedef is a storage class specifier. Don't ask why. Basically, typedef struct stat_mot; is wrong, but that's OK because you can remove it anyway when you move the struct definition.

Your struct definition must be in header.

You must put your stat_mot structure in frequence.h.
Additionally, main() should be declared like
int main(int argc, char **argv)
and texte should be a char *:
int main(char *argv[])
{
char *texte = ";! one two, tree foor one two !:;";
struct stat_mot word = show_all_words(texte);
You also ought to include <string.h> and <stdlib.h> in frequence.c since you use strstr, strlen and free.
In frequence.c, strlen is always greater or equal to zero, so the comparison will always be true.

The header is only good for the definitions -- e.g. compiling actually works, but linker does not know where to look for the bodies of the functions.
Try compiling with gcc main.c frequence.c
Also, typedef struct stat_mot; does not have much meaning -- struct stat_mot is not defined at this moment, and also, you are not giving it a new name with this typedef.
I think separating the struct definition does not make sense even if it was allowed - after all, if you just distribute the header file, people should know how to use the struct (e.g. see what it contains)

You declare the structure stat_mot in the header file (a forward declaration) but you define it in the source file frequence.c. Therefore it's not usable from main.c.

Just put the structure declaration into the header file:
/* in frequence.h */
struct stat_mot {
char* word;
int frequency;
};
so both translation units (i.e. the .c files) see it.

struct stat_mot needs to be defined in the header file or use pointers.
Oh and (though this is not the problem)
typedef struct stat_mot;
you need to specify second type name like this:
typedef struct stat_mot stat_mot;

May be you should write this
typedef struct stat_mot stat_mot;
in your frequence.h
and then
typedef struct stat_mot {
char * word;
int frequency;
};
in .c file.
.h file is just a declare of data file or method,but you should declare it clearly.
TIPs: there is no need a ; at the end of main(){};

Related

Makefiles and structures in C

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.

Dereferencing pointer to incomplete type [Working on structs]

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.

error: dereferencing pointer to incomplete type in main file

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);
}

"warning: 'struct matrix' declared inside parameter list [enabled by default]" and error: conflicting types for 'scanToken'

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.

how can I use a pointer to global struct in ansi-c?

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.

Resources