Static constants - c

Does it make any difference in C99 when one writes const int x = 1; vs. static const int x = 1; in a header (*.h) file?

Yes. First, I don't advise you to place such definitions in a header file, but if you do then it depends on where the header file is included. Anyway, static makes the variable local to the current program unit. Here is an example:
mp1.c:
#include <stdio.h>
void myfunc(void);
const int x = 1;
int main (int argc, char *argv[])
{
printf ("main: value of x: %d\n",x);
myfunc();
return 0;
}
mp2.c:
#include <stdio.h>
extern int x;
void myfunc(void)
{
printf ("myfunc: value of x: %d\n",x);
}
compilation:
gcc -o mp mp1.c mp2.c
works fine. Now change mp1.c to use static const int x = 1; and when we compile (actually its a link error), we get:
home/user1> gcc -o mp mp1.c mp2.c
/tmp/ccAeAmzp.o: In function `myfunc':
mp2.c:(.text+0x7): undefined reference to `x'
collect2: ld returned 1 exit status
The variable x is not visible outside of mp1.c.
The same applies to the static prefix to functions.

As cdarke said, it makes a difference.
const int x = 1; creates a for the linker visible symbol, for each module including your h-file.
The linker should stop then with an error, as there are multiple (visible) defines of the same symbol.
static const int x = 1; creates a variable but no linker symbol, for each module including your h-file.
The linker could link the code, but as you created multiple instances of the variable with the same name, it's not sure that your code works as expected.
Btw. It's an absolutly bad idea to define a variable in a h-file, the standard way is to define them in the c-file and only to declare them in the h-file (if you really need to access them).
You use static when you only want to use the variable in one module, and it should be invisible to all others.
const ... only if you really need to access it from another module, but IMHO you should normally avoid global accessible variables.
myFile.c
#include "myFile.h"
const int x=1;
static const int y=2;
myFile.h
extern const int x;

Related

Please can anyone explain me this warning while writing a c program(use of extern keyword)

file name :- next.c
extern int global_var = 2;
file name :- try.c
#include <stdion.h>
#include "next.c"
void main()
{
printf("%d", global_var);
}
The waring that I am getting
In file include form try.c:2:0:
next.c.1.12: warning: 'globl_var' initialized and declared 'extern'
extern in global_var = 22;
^~~~~~~~~
The warning itself tells you that your code is wrong. The messages can be "translated" into something like: "Declaring a variable as extern and at the same time assigning a value, is wrong.
It seems you have misunderstood the normal way to use include files. You don't do:
#include "next.c"
What you do is
#include "next.h"
That is... a c-file contains source code for a unit. The corresponding h-file contains information about the unit that you want to share with other units (aka c-files).
Try this:
next.h:
extern int global_var; // Tell other c-files that include next.h
// that a int-variable with name global_var
// exists
next.c:
int global_var = 2; // Define and initialize global_var
and in try.c do:
#include "next.h" // Include next.h to know what the unit next.c
// makes available for use in try.c
The above is for a global variable defined by the unit next.c. For functions is pretty much the same.
Assume that next.c implements a function foo that you want try.c to call... Then you do the same, i.e. you write the functions source code in next.c and use next.h to tell other units that the function is available. Like:
next.h:
extern int global_var; // Tell other c-files that include next.h
// that a int-variable with name global_var
// exists
void foo(int a, int b); // Tell other c-files that include next.h
// that a function with name foo
// exists
next.c:
int global_var = 2; // Define and initialize global_var
void foo(int a, int b) // Define foo
{
... source code ...
}
and in try.c use it like:
#include "next.h" // Include next.h to know what the unit next.c
// makes available for use in try.c
#include "next.h" // Include next.h to know what the unit next.c
// makes available for use in try.c
int bar()
{
int x = 0;
int y = 42;
foo(x, y); // Call function foo in unit next.c
....
}
extern is used to tell compiler that variable is declared out of scope.
first.c
#include <stdio.h>
#include "second.h"
int main(){
extern const float pi;
printf("pi : %f\n" , pi);
return 0;
}
second.h
const float pi = 3.148;
output
pi : 3.148000
why to use extern?
to prevent local redeclaration of variable and make code more readable and understandable
example error
first.c
#include <stdio.h>
#include "second.h"
int main(){
extern const float pi;
const float pi;
printf("pi : %f\n" , pi);
return 0;
}
output
first.c: In function 'main':
first.c:7:17: error: redeclaration of 'pi' with no linkage
7 | const float pi;
| ^~
In file included from first.c:2:
second.h:1:13: note: previous definition of 'p
' with type 'float'
1 | const float pi = 3.148;
| ^~
extern tells the compiler that the extern declared symbol is defined in a different source file or rather translation unit .
When you assign a value to an extern symbol, you basically say " the definition is somewhere else, but the definition is [x]"
To fix that, you should "define" the variable somewhere without "extern".

How to make GCC warn unmatched number of arguments in function calls and function definition?

I have two files.
The first file contains the function prototype and the main function calls myfunc with only one argument:
int myfunc (int x);
int main ()
{
int x =5;
myfunc(x);
}
and the second file contains the function definition but with 2 arguments:
int myfunc (int x, int y)
{
return x+y;
}
When I tried to compile this two files using GCC I got no errors or warnings.
How to force GCC to warn about something like this??
Put your prototypes in a header file, and #include the header file in all source files which use the functions.
GCC compiles each file independently, so it cannot know that the definition of the function does not correspond to the declaration unless the declaration is also included in the file with the definition.
It should look like this:
myfunc.h
#ifndef MYFUNC_H
#define MYFUNC_H
int myfunc (int x);
#endif
myfunc.c
#include "myfunc.h"
int myfunc (int x, int y)
{
return x+y;
}
main.c
#include "myfunc.h"
int main ()
{
int x =5;
myfunc(x);
}
Because the two source files are two different translation units that are compiled completely separately, it's impossible for the compiler to know about this. And as C symbols doesn't really have information about arguments, the linker can't warn about this either.
The only solution is to put function prototypes in header files that are included in all relevant source files.

Error when building c code with -D

I get the following errors when I'm trying to build my c code files with -D. But, if I build it without -D, it works. I don't know why. Thanks. (My machine is ubuntu12.10, 32bit)
gcc c1.c c2.c -D DEBUG
/tmp/ccX04EIf.o:(.data+0x0): multiple definition of `g'
/tmp/cc0j9MoU.o:(.data+0x0): first defined here
collect2: ld returned 1 exit status
Here is my source code:
global.h
#ifdef DEBUG
int g = 23;
static int init = 1;
#else
int g;
static int init = 0;
#endif
c1.c
#include "global.h"
int f() {
return g + 1;
}
c2.c
#include <stdio.h>
#include "global.h"
int main() {
if (!init) {
g = 37;
}
int t = f();
printf("calling f yields %d\n", t);
return 0;
}
You define the variable g in the header file, that means it will be defined in all source files that includes the header file.
Instead declare it, like
extern int g;
and then define it in a single source file.
The difference between the two code paths (with and without DEBUG) is the initialization of the g variable. Without it, it is only a "tentative" definition, and so the symbol is only generated in the file that really uses it, namely c2.o.
With initialization it is a real definition of the symbol, and so it is also generated in c1.o.
As a rule of thumb, header files should never contain data definitions, only declarations. Data "declarations-only" should be made with the keyword extern. You'd then need to define any such symbol in exactly one of your .c files.

Duplicate symbol in C using Clang

I am currently working on my first "serious" C project, a 16-bit vm. When I split up the files form one big source file into multiple source files, the linker (whether invoked through clang, gcc, cc, or ld) spits out a the error:
ld: duplicate symbol _registers in register.o and main.o for inferred
architecture x86_64
There is no declaration of registers anywhere in the main file. It is a uint16_t array if that helps. I am on Mac OS 10.7.3 using the built in compilers (not GNU gcc). Any help?
It sounds like you've defined a variable in a header then included that in two different source files.
First you have to understand the distinction between declaring something (declaring that it exists somewhere) and defining it (actually creating it). Let's say you have the following files:
header.h:
void printIt(void); // a declaration.
int xyzzy; // a definition.
main.c:
#include "header.h"
int main (void) {
xyzzy = 42;
printIt();
return 0;
}
other.c:
#include <stdio.h>
#include "header.h"
void printIt (void) { // a definition.
printf ("%d\n", xyzzy);
}
When you compile the C programs, each of the resultant object files will get a variable called xyzzy since you effectively defined it in both by including the header. That means when the linker tries to combine the two objects, it runs into a problem with multiple definitions.
The solution is to declare things in header files and define them in C files, such as with:
header.h:
void printIt(void); // a declaration.
extern int xyzzy; // a declaration.
main.c:
#include "header.h"
int xyzzy; // a definition.
int main (void) {
xyzzy = 42;
printIt();
return 0;
}
other.c:
#include <stdio.h>
#include "header.h"
void printIt (void) { // a definition.
printf ("%d\n", xyzzy);
}
That way, other.c knows that xyzzy exists, but only main.c creates it.

warning in extern declaration

I declared a variable i in temp2.h
extern i; which contains just one above line
and made another file
temp3.c
#include<stdio.h>
#include<temp2.h>
int main ()
{
extern i;
i=6;
printf("The i is %d",i);
}
When I compiled above as
cc -I ./ temp3.c I got following errors
/tmp/ccJcwZyy.o: In function `main':
temp3.c:(.text+0x6): undefined reference to `i'
temp3.c:(.text+0x10): undefined reference to `i'
collect2: ld returned 1 exit status
I had declared extern in temp3.c above as K R page 33 says as I mentioned in above post.
I tried another way for temp3.c with same header file temp2.h
#include<stdio.h>
#include<temp2.h>
int main ()
{
i=6;
printf("The i is %d",i);
}
and compiled it cc -I ./ temp3.c and got following error
/tmp/ccZZyGsL.o: In function `main':
temp3.c:(.text+0x6): undefined reference to `i'
temp3.c:(.text+0x10): undefined reference to `i'
collect2: ld returned 1 exit status
I also tried
#include<stdio.h>
#include<temp2.h>
int main ()
{
extern i=6;
printf("The i is %d",i);
}
compiled this one
cc -I ./ temp3.c
got same error as in post 1
temp3.c: In function ‘main’:
temp3.c:5: error: ‘i’ has both ‘extern’ and initializer
So I have tried at least 3 different ways to use extern but non of them worked.
When you declare a variable using extern , you are telling the compiler that the variable was defined elsewhere and the definition will be provided at the time of linking. Inclusion is a different thing altogether.
extern
An external variable must be defined, exactly once, outside of any function; this sets aside storage for it. The variable must also be declared in each function that wants to access it; this states the type of the variable. The declaration may be an explicit extern statement or may be implicit from context.
-The C Programming Language
A variable must be defined once in one of the modules(in one of the Translation Units) of the program. If there is no definition or more than one, an error is produced, possibly in the linking stage (as in example 1 and 2).
Try something like the following
a.c
int i =10; //definition
b.c
extern int i; //declaration
int main()
{
printf("%d",i);
}
Compile, link and create an executable using
gcc a.c b.c -o executable_name
or
gcc -c a.c // creates a.o
gcc -c b.c // creates b.o
Now link the object files and create an executable
gcc a.o b.o -o executable_name
extern is declaration mechanism used to tell the compiler that the variable is defined in another file.
My Suggestion is that you define a variable in a ".c" file and then add the extern declaration in the corresponding ".h" file. In this way, the variable declaration will be available to all the source files which includes this header file and also it will be easier for one to identify in which ".c" it is actually defined.
The first program said:
The variable i (implicitly of type int) is defined somewhere else - but you didn't define it anywhere.
The second program tried to use a variable for which there was no declaration at all.
The third program tried to declare a variable without an explicit type (used to be OK; not allowed in C99), and said:
The variable i is defined somewhere else, but I want to initialize it here.
You are not allowed to do that.
So, the compiler is correct in all cases.
The declaration in the header 'temp2.h' should be fixed to extern int i; first. The implicit int is long obsolete.
You could fix the first example in several ways:
#include <stdio.h>
#include <temp2.h>
int main()
{
extern int i;
i=6;
printf("The i is %d",i);
return 0;
}
int i;
This defines the variable after the function - aconventional but legitimate. It could alternatively be in a separate source file that is separately compiled and then linked with the main program.
The second example could be fixed with:
#include <stdio.h>
#include <temp2.h>
int main()
{
int i=6;
printf("The i is %d",i);
return 0;
}
It is important to note that this example now has two variables called i; the one declared in temp2.h (but not actually referenced anywhere), and the one defined in main(). Another way of fixing it is the same as in the first possible fix:
#include <stdio.h>
#include <temp2.h>
int main()
{
i=6;
printf("The i is %d",i);
return 0;
}
int i;
Again, aconventional placement, but legitimate.
The third one can be fixed by similar methods to the first two, or this variant:
#include <stdio.h>
#include <temp2.h>
int i;
int main()
{
extern int i;
i=6;
printf("The i is %d",i);
return 0;
}
This still declares i in <temp2.h> but defines it in the source file containing main() (conventionally placed - at the top of the file). The extern int i; insides main() is doubly redundant - the definition in the source file and the declaration in the header mean that it does not need to be redeclared inside main(). Note that in general, the declaration in the header and the definition in the source file are not redundant; the declaration in the header provides a consistency check with the definition, and the other files that also use the variable and the header are then assured that the definition in the file containing main() is equivalent to the definition that the other file is using too.

Resources