How to use global variables in C functions included in other files - c

I have a simple program like:
int velocity=0;
#include "extra.h"
int main()
{
extra();
return 0;
}
where extra.h is:
void extra(){
velocity += 1;
}
yet when I compile this, I get the error:
extra.h:5:5: error: 'velocity' was not declared in this scope
Obviously, my code in extra.h can't "see" the variables in main.c, but why is this? How do I fix this?

You could add the following declaration to extra.h:
extern int velocity;
However, extra() shouldn't be defined in extra.h in the first place. This will cause problems if extra.h is included by multiple .c files in the same binary. The following is what you should have:
extra.h:
void extra();
extra.c:
#include "extra.h"
static int velocity = 0;
void extra() {
velocity += 1;
}
main.c:
#include "extra.h"
int main()
{
extra();
return 0;
}

Related

How do I use values from a .h file for calculations in a .c file?

I'm trying to calculate values in rand.h:
#ifndef RAND_H_INCLUDED
#define RAND_H_INCLUDED
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
double rando()
{
srand(time(NULL));
double base=rand(); /*using base instead of time because of random generator using the built-in time function*/
double height[20];
double pressure[20];
/*random heights*/
int i;
for(i=0;i<20;i++){
height[i]=rand();
}
/*random pressures*/
int q;
for(q=0;q<20;q++){
pressure[q]=rand();
}
}
#endif // RAND_H_INCLUDED
And then use them for the calculations in main.c:
#include <stdio.h>
#include <stdlib.h>
#include "rand.h"
int main() /*table formatting testing*/
{
rando();
double base;
double height;
double pressure;
int hnum=sizeof(height)/sizeof(height[0]);
int pnum=sizeof(pressure)/sizeof(pressure[0]);
/*printing height*/
int hloop;
for (hloop=0;hloop<hnum;hloop++){
if (hloop==0){
printf(" %g",height[hloop]);
} else{
printf(" %g",height[hloop]);
}
}
/*printing time and pressure*/
printf("\n");
int ploop;
for (ploop=0;ploop<pnum;ploop++){
if (ploop==0){
printf("%g %g",base,pressure[ploop]);
} else{
printf(" %g",pressure[ploop]);
}
}
return 0;
}
However, I get multiple errors from rand.h and main.c. From rand.h I get the both pressure and height are set but not used, and that base is unused. From main.c I get a bunch of errors saying that pressure and height aren't arrays, pointers, or vectors. How do I use the values calculated in rand.h for the calculations in main.c. Note that the values must be calculated in rand.h then somehow transferred to main.c.
You seem to be under the impression that the variables base, height, and pressure in the rando function are the same ones in the main function. They are not. Variables declared in a function are local to that function.
This is why you're getting warnings that these variables in rando are not used, because they're not being read anywhere in this function.
The errors you get from the main function are because height and pressure are in fact not arrays:
double height;
double pressure;
You need to change rando to take a parameter for each of these three objects:
void rando(double *base, double *height, double *pressure)
Note also that the return type is changed to void because you're not actually returning anything. Then the body would have the following changes:
srand(time(NULL));
*base=rand(); // dereference the given pointer to change base in main
/*random heights*/
Then in main you would make this change:
double base;
double height[20];
double pressure[20];
rando(&base, height, pressure);
Note that you need to pass the address of base so that it can be changed. This is not needed on the two arrays as the names are converted to pointers when passed to the function.
On a separate note, it's not a good idea to have function definitions in a header file. If this header were to be included by more than one .c file, you would get errors about the function being defined multiple times.
The header should only contain a declaration:
#ifndef RAND_H_INCLUDED
#define RAND_H_INCLUDED
void rando(double *base, double *height, double *pressure);
#endif // RAND_H_INCLUDED
And the body of the function would be in a separate file, i.e. rand.c. Then you would compile both rand.c and main.c and link them.
First you shouldn't implement function in .h files, create a separate .c and define it in .h file to use it in an another .c by calling this .h file, it's more readable on large project.
Second point your function isn't returning anything it should be void rando() (It's not a function, it's called a procedure if I'm right on the English name).
And I guess your procedure is made to initialize some random data, so why do you call the function before you initialize the variable ?
The point is that your variable is not even global, so you should have parameter define for calling the function (since they are array you don't need to create pointer)
Try either make rando() of type void...
#ifndef RAND_H_INCLUDED
#define RAND_H_INCLUDED
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
void rando() //change type void
{
srand(time(NULL));
double base=rand(); /*using base instead of time because of random generator using the built-in time function*/
double height[20];
double pressure[20];
/*random heights*/
int i;
for(i=0;i<20;i++){
height[i]=rand();
}
/*random pressures*/
int q;
for(q=0;q<20;q++){
pressure[q]=rand();
}
}
#endif // RAND_H_INCLUDED
or, just write a return statement,
#ifndef RAND_H_INCLUDED
#define RAND_H_INCLUDED
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
double rando()
{
srand(time(NULL));
double base=rand(); /*using base instead of time because of random generator using the built-in time function*/
double height[20];
double pressure[20];
/*random heights*/
int i;
for(i=0;i<20;i++){
height[i]=rand();
}
/*random pressures*/
int q;
for(q=0;q<20;q++){
pressure[q]=rand();
}
return 0; //correction
}
#endif // RAND_H_INCLUDED
In rand.h declare a struct containing all of the values to be initialized by rando()
Define a structure of this type in main
Pass the address of this structure to rando()
In main(), use the values with the syntax structure.member
What's usually the suggested approach in C programming language is to put:
Function Declarations in HEADER (.h) files
Function Definitions in C (.c) files
So, I would have three files in your case:
main.c (with the main function)
rand.c (with rando function definition)
rand.h (with rando function header)
main.c
#include <stdio.h>
#include <stdlib.h>
#include "rand.h"
int main() /*table formatting testing*/
{
rando();
double base;
double height;
double pressure;
int hnum=sizeof(height)/sizeof(height[0]);
int pnum=sizeof(pressure)/sizeof(pressure[0]);
/*printing height*/
int hloop;
for (hloop=0;hloop<hnum;hloop++){
if (hloop==0){
printf(" %g",height[hloop]);
} else{
printf(" %g",height[hloop]);
}
}
/*printing time and pressure*/
printf("\n");
int ploop;
for (ploop=0;ploop<pnum;ploop++){
if (ploop==0){
printf("%g %g",base,pressure[ploop]);
} else{
printf(" %g",pressure[ploop]);
}
}
return 0;
}
rand.c
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include "rand.h"
double rando()
{
srand(time(NULL));
double base=rand(); /*using base instead of time because of random generator using the built-in time function*/
double height[20];
double pressure[20];
/*random heights*/
int i;
for(i=0;i<20;i++){
height[i]=rand();
}
/*random pressures*/
int q;
for(q=0;q<20;q++){
pressure[q]=rand();
}
}
rand.h
#ifndef RAND_H_INCLUDED
#define RAND_H_INCLUDED
double rando();
#endif // RAND_H_INCLUDED
=======
After all these, you write a Makefile for your build process. But if you want to compile everything by hand, you can do:
$ gcc -c rand.c
$ gcc -c main.c
$ gcc rand.o main.o -o main
$ ./main
But, do keep in mind that your code does not compile. It has some errors (such us using pressure (or height) as a global array although it's just a local double variable inside main function.

Is there any wrong about tha static variable?

I have a problem about a program. I bet that it has to do with the fact that I use static. Here is my t.h
static int cnt;
void f();
my main.c
#include <stdio.h>
#include "t.h"
void main()
{
cnt=0;
printf("before f : cnt=%d\n",cnt);
f();
printf("after f : cnt=%d\n",cnt);
}
and finally my f.c
#include "t.h"
void f()
{
cnt++;
}
The printf prints cnt=0 both times. How is this possible when I do cnt++? Any ideas?
Thanks in advance
In C, static means "Local to the module"
Take note, that the #include statements just pastes the header file in the including file.
therefore, you are creating two distinct symbols (happens to have the same logical name) in different modules.
f.c cnt is a different cnt then main.c
Note:
static in C has different meaning then its C++ counterpart.
and because C++ is C Compatible, static outside a class have the same meaning as in C
Edit:
In your case, you don't want a static you want a variable, but i guess you had problem with the Linker telling you about "ambiguous symbols".
I would suggest to declare an extern in the header file, and declare the actual variable in a module.
t.h
extern int cnt; // declaration of the variable cnt
main.cpp
#include
#include "t.h"
void main()
{
cnt=0;
printf("before f : cnt=%d\n",cnt);
f();
printf("after f : cnt=%d\n",cnt);
}
t.cpp
#include "t.h"
int cnt = 0; // actual definition of cnt
void f()
{
cnt++;
}
Data should not be defined in the header files.
In your example you will create a separate copy of that static variable in every compilation module which includes this .h file.
Don't define cnt in your header file. Instead, define it in f.c:
#include "t.h"
int cnt = 0;
void f(){
cnt++;
}
Then in main.c, add the following before the beginning of your main function:
extern int cnt;

C static funtions accesible outside of file?

I used code blocks to make a project with main.c:
#include <stdio.h>
#include "t.h"
int main()
{
printf("%c\n", return_f('f'));
printf("%c\n", return_f(return_char(71)));
printf("%d\n", STATIC_INT);
return 0;
}
And t.h:
static int STATIC_INT = 14;
static unsigned char return_char(char n){
return (n/2 + 9);
}
unsigned char return_f(char n){
return ((n=='f' || n=='F') ? n+1 : 'f');
}
Since I assume static should limit globals and functions to their files, how does it allow to run/print out:
g
f
14
Or is that just not how it's supposed to work?
t.h is included textually before the actual compilation process takes place. Therefore static int STATIC_INT = 14; is part of your main.c file.
The real problem is that you are declaring variables in a header file which is almost always wrong.
It work because you import t.h in your .c file.
Static function can't be accesible outside of the file. But when you import t.h in your main.c file, all the code in t.h will be paste into main.c; so now your static function belong to main.c !
You have included t.h in your main.c, so these symbols are in the same unit of your main.c

Functions and variables scope in C

Why we don't use extern when using function from one .c file in another .c file , but we must do extern for variables case? Is it related to linker?
Functions are extern qualified by default (unless you change it to internal with static). For example,
int func(void) {
}
extern int func2(void) {
}
Both func and func2 are external. The extern keyword is optional for external functions.
Actually, function names act just like variable names, but function prototypes are extern by default.
From cpprerefence:
If a function declaration appears outside of any function, the identifier it introduces has file scope and external linkage, unless static is used or an earlier static declaration is visible.
you can create a .hfile,declare functions you want to use in the other .c files and #include the .hfile in the other .c files.
Demo program,
one.c
#include "one.h"
void func1() //defination
{
//code
}
one.h
void func1(); //declaration
main.c
#include <stdio.h>
#include "one.h"
int main()
{
func1();
}
Then compile program in Gcc Linux : gcc main.c one.c
Yes, Let consider you have one .c file as process.c and you declared it in process.h . Now if you want to use the function from process.c to suppose tools.c then simply #include "process.h" in tools.c and use ther function. The process.h and process.c file should be in your project.
process.c file
#include<stdio.h>
#include<conio.h>
#include "process.h"
unsigned int function_addition(unsigned int a, unsigned int b)
{
unsigned int c = 0;
c = a + b;
return c;
}
process.h:
<bla bla bla >
unsigned int function_addition(unsigned int a, unsigned int b);
<bla bla bla >
tools.c file:
#include<stdio.h>
#include<conio.h>
#include "process.h"
my_tools()
{
unsigned int X = 1, Y = 9, C = 0;
C = function_addition(X,Y);
}
All these files are in one project.

C Static Function Confusion

I am trying to make the s_cord_print function visible in the cord_s.c file only. Currently the function is visible/runnable in main.c even when it is declared static.
How do I make the s_cord_print function private to cord_s.c?
Thanks!
s_cord.c
typedef struct s_cord{
int x;
int y;
struct s_cord (*print)();
} s_cord;
void* VOID_THIS;
#define $(EL) VOID_THIS=&EL;EL
static s_cord s_cord_print(){
struct s_cord *THIS;
THIS = VOID_THIS;
printf("(%d,%d)\n",THIS->x,THIS->y);
return *THIS;
}
const s_cord s_cord_default = {1,2,s_cord_print};
main.c
#include <stdio.h>
#include <stdlib.h>
#include "s_cord.c"
int main(){
s_cord mycord = s_cord_default;
mycord.x = 2;
mycord.y = 3;
$(mycord).print().print();
//static didn't seem to hide the function
s_cord_print();
return 0;
}
~
The problem is:
#include "s_cord.c"
You should remove that. Instead, create a s_cord.h file that contains only declarations, such as:
typedef struct s_cord{
int x;
int y;
struct s_cord (*print)();
} s_cord;
and put:
#include "s_cord.h"
in main.c and s_cord.c. You also need an extern declaration for s_cord_default. So the complete code is:
s_cord.c:
#include "s_cord.h"
#include <stdio.h>
void* VOID_THIS;
static s_cord s_cord_print(){
struct s_cord *THIS;
THIS = VOID_THIS;
printf("(%d,%d)\n",THIS->x,THIS->y);
return *THIS;
}
const s_cord s_cord_default = {1,2,s_cord_print};
s_cord.h:
typedef struct s_cord{
int x;
int y;
struct s_cord (*print)();
} s_cord;
#define $(EL) VOID_THIS=&EL;EL
extern const s_cord s_cord_default;
extern void *VOID_THIS;
main.c:
#include <stdio.h>
#include <stdlib.h>
#include "s_cord.h"
int main(){
s_cord mycord = s_cord_default;
mycord.x = 2;
mycord.y = 3;
$(mycord).print().print();
return 0;
}
You'll now get a error if you try to call s_cord_print() from main, as expected.
EDIT: I forgot to move the $(EL) definition, and it needed an extern for VOID_THIS.
EDIT 2: The correct compilation command is:
gcc s_cord.c main.c -o main
When you include s_cord.c from within main.c, the compiler sees your program as one big file. It doesn't treat the included file as separate. To make them separate, you have to compile them separately. Once you have compiled them separately, you will then have to link them to create the whole program.
When you try to compile each part, you will get errors, because each file doesn't know about the code in the other file. Remember, this is what you were trying to accomplish with that one function. Well, now you've got what you asked for, many times over. Now, you have to create header files that explain the "missing parts". Generally the files being compiled look at each other's ".h" files (they #include them) to get a bearing on the "missing" (actually, external) parts. These are declarations, which tell the compiler "pretend you already know about this, and I promise that when we link everything, it will be provided".

Resources