Division between declaration and definition in other C files - c

I would like to know how make the division between declaration and definition. I read few related with this topic question but for now I can do this only in basic funtion. The problem is when I try to declare constant global variable in header file and I want use this constant in the function which have declaration in the same place but definition in other files. I have 2 files with .c extension and one with .h extension.
File main_lib.h consist:
#ifndef _MAIN_LIB_H_
#define _MAIN_LIB_H_
const int N_POINTS=10;
struct Point{
int x;
int y;
};
void fill_random(struct Point points[], int n);
void closest(struct Point points[], int n, struct Point* p);
#endif /* _MAIN_LIB_H_ */
File main_lib.c consist:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "main_lib.h"
void fill_random(struct Point points[], int n){
...
}
void closest(struct Point points[], int n, struct Point* p){
...
}
And the last file named main.c consist:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include "main_lib.h"
int main()
{
srand(time(0));
struct Point random_points[N_POINTS];
struct Point *p;
p=&random_points[0];
fill_random(p,N_POINTS);
closest(p,N_POINTS,p);
return 0;
}
The question is how to correct this code to run it without error status. Thanks a lot for any help.

The problem is when I try to declare constant global variable in header file ...
how to correct this code to run it without error status(?)
Instead, declare extern in main_lib.h #Scheff. This would be the same if the global variable was non-const or volatile.
// const int N_POINTS=10;
extern const int N_POINTS;
Define it once and only in main_lib.c
// add
const int N_POINTS=10;

A method I often use is:
// lib.h
#ifndef EXTERN
#define EXTERN extern
#endif
EXTERN int myInt;
// lib.c
#include "lib.h"
// main.c
#define EXTERN
#include "lib.h"
myInt will now be known in all modules in which lib.h is included but will only be declared once in main.c. Usefull when you have lots of includes.

Related

Confusion about the extern keyword and multiple source files

I am trying to fully understand how extern works, so I created 3 files, two of them are source files and the last is a header file. This is what is contained in each of them:
testingfile1.c
#include <stdio.h>
#include "testingheader.h"
int main() {
change();
int my_extern;
printf("\n%d", my_extern);
return 0;
}
testingfile2.c:
#include <stdio.h>
#include "testingheader.h"
void change() {
int my_extern;
my_extern = 15;
printf("%d", my_extern);
}
testingheader.h:
#if !defined(TESTINGHEADER_H)
#define TESTINGHEADER_H
#include <stdio.h>
extern int my_extern;
void change();
#endif
The output of this program is: 15 0. However, I thought that since my_extern is an extern int, if you were to change to the value in one source file, it's value would be changed in all of the other source files. Is this not how extern works, or am I doing something wrong in the code itself?
In both cases remove int my_extern; where you have it, because those become local variables which happen to have the same name my_extern.
extern int my_extern; just means there's an int called my_extern "out there somewhere". So you'd have to declare int my_extern somewhere at file scope, for example like this:
int my_extern = 0;
void change() {
my_extern = 15;
printf("%d", my_extern);
}
In testingfile2.c, the my_extern variable is local to the function and you are not seeing the global my_extern that the extern command is referencing. Of course, you don't have a global my_extern, so that is another problem. You would get a linker error if you actually tried to reference the global my_extern that the extern command is referencing.
The issue is you're re-declaring int my_extern; inside your functions. Therefore, C treats that as a separate variable from the global my_extern.
The statement extern int my_extern; is a declaration that a global int called my_extern will be declared somewhere. You haven't done that. Instead, you've created local my_extern variables.

Header file error: expected identifier or '(' before numeric constant

I'm new to header files and am not sure why I am getting this error. The first piece of code is from the relevant header file, and gives the expected identifier error:
#define MAX_ADDR_LENGTH 1000
struct listNode{
char addr[MAX_ADDR_LENGTH];
struct listNode *next;
};
Related to this, there is another error in the file relevant to that header, which gives me a "note: in expansion of macro 'MAX_ADDR_LENGTH', which it gives me on the line which gives the declaration of int MAX_ADDR_LENGTH:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "header.h"
char *crawl(char* getLinksFrom, int hopTo){
int MAX_ADDR_LENGTH = 300;
char startAddr[MAX_ADDR_LENGTH];
char destAddr[MAX_ADDR_LENGTH];
}
I've tried a number of things hoping it was just a small oversight (removed the #define altogther, deleted the line that gives the int MAX_ADDR_LENGTH declaration, just deleted the phrase 'int' from the same; all of which just caused even more errors).
The problem: ‘MAX_ADDR_LENGTH’ is defined twice in your code; Once as a Macro and once as a variable.
Try to delete the statement declaring MAX_ADDR_LENGTH as a variable.
Build your header like this:
#ifndef HEADER_H
#define HEADER_H
#define MAX_ADDR_LENGTH 1000
typedef struct _listNode{
char addr[MAX_ADDR_LENGTH];
struct _listNode *next;
} listNode;
#endif /* HEADER_H */
and use it like this:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "header.h"
char *crawl(char* getLinksFrom, int hopTo){
char startAddr[MAX_ADDR_LENGTH];
char destAddr[MAX_ADDR_LENGTH];
.... more code
}
The #ifndef...#endif construct is called an include guard. It's not necessary to get your code compiled, but good practice to use it.
The typedef is used to define the node structure. It does not create a variable yet, it's just defining a type named listNode that you can use to build your list later on.

Error: storage size of 'c' isn't known

I'm getting "Error: storage size of 'c' isn't known" when i try to create the variable "c" of my struct called "struct car"
Here is the code:
teste.h
#ifndef TESTE_H_INCLUDED
#define TESTE_H_INCLUDED
typedef struct car Car;
#endif // TESTE_H_INCLUDED
teste.c
#include <stdio.h>
#include <stdlib.h>
#include "teste.h"
struct car{
char name[20];
char model[20];
};
main.c
#include <stdio.h>
#include <stdlib.h>
#include "teste.h"
int main()
{
Car c;
return 0;
}
I can't figure out why I'm getting this error... I bet it is something stupid... could someone help me?
the Car structure on the header file is just a forward declaration, when it's included on main.c, it only has knowledge of the forward declaration but no clue of how it's defined (or in this case, what the size of the struct is). define your struct on the header file.
struct car {
char name[20];
char model[20];
};

Compile error on using extern

I wrote a very simple program on C. It compiles and works fine. But if I add extern int x at the functions.h instead of functions.c I get this error
functions.c:3:12: error: use of undeclared identifier 'x'
return x / 2;
^
1 error generated.
I thought the correct place for extern is in the header file.
variables.h
int x = 10;
functions.h
#include "variables.h"
int calculate_items(int d);
functions.c
extern int x;
int calculate_items(int d)
{
return x / 2;
}
main.c
#include <stdio.h>
#include "functions.h"
int main() {
printf("%d", calculate_items(5));
}
No, you can't have an initializer in the header.
It will not work as soon as more than one C file include the same header, there will be multiple declarations.
You should make the variable a global in one of the C files, for instance in main.c, and then just have extern int x; in the files that need to access it (or in headers that they can #include, of course).
In this case, since the variable ends up "belonging to" the main.c file, you should probably add a main.h header that has the extern int x; declaration, and #include that from functions.c and other places that need the variable.
If you don't put extern int x; in functions.c and functions.c doesn't #include anything that declares x, how is it supposed to know what x is?
If you expect some kind of implicit relationship between functions.h and functions.c because they both have names like functions.* then you should just get rid of that expectation.
The normal way to do this is to put the extern int x; in functions.h, then int x=10; in one of the .c files, and #include "functions.h" from all of the .c files that reference x, including functions.c.

C extern struct pointer dynamic allocation

I'm trying to allocate dynamically a global struct in c, but something makes my c file not being able to find the reference to the extern variable.
The log:
main.c:18: undefined reference to `gate_array'
extern.h
#ifndef EXTERN_H_
#define EXTERN_H_
typedef struct gate_struct {
int out;
} gate;
extern gate *gate_array;
#endif /* EXTERN_H_ */
main.c:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include "extern.h"
int main(int argc, char *argv[]){
gate_array = (gate*) malloc (2* sizeof(gate));
return 0;
}
Thanks!
There is no definition of gate_array due to extern. In this case, you can just remove the extern qualifier. However, if extern.h was used in multiple translation units (#include in several .c files) then this approach would result in multiple definition errors. Consider adding another .c file that would contain the definiton of gate_array (and any future variables), ensuring there is exactly one definition of gate_array.
The extern gate *gate_array tells the compiler that there is a variable called gate_array, but it is defined somewhere else. But there is no definition of gate_array in the posted code.
Also, you may wish to read
Do I cast the result of malloc?
This is probably what you meant to do:
#ifndef EXTERN_H_
#define EXTERN_H_
typedef struct gate_struct {
int out;
} gate;
typedef gate *gate_array;
#endif /* EXTERN_H_ */
This typedefs gate * to gate_array. Then in your main.c you want to do:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include "extern.h"
int main(int argc, char *argv[]){
gate_array name_of_array = malloc (2* sizeof(gate));
free(name_of_array);
return 0;
}
Previously you were missing a variable name. Furthermore, it is bad practice to cast the return of malloc.
Pointer to gate i.e. gate_array was typedef not declared so you were doing something like this:
typedef int *IXX;
IXX = (int*) malloc(2*sizeof(int));
Do something like this:
IXX ix = (int*) malloc(2*sizeof(int));

Resources