I am calling a function in one file
a = fun(a,b);
I am having the #define of that function in other file
#define fun fun1
I am defining that function in another file
static int fun1(int a, int b)
{
-------------
-------------
}
But compiler complaints
'fun1' defined but not used [-Wunused-function]
Its strange for me that compiler complaints about this.
static int fun1(int a, int b)
staticmeans that this function can be only used in this file. Remove the static and try again.
You have two problems here: The first about that warning, because in the other source file you don't actually use the function. The second problem is that you marked the function as static, which means that it will only be available in that specific source file.
If you want to be able to call functions defined in other source files (translation units as they are really called) then you can't make functions static.
Related
below is my code:
//main.c
//I'm not using header file here,I know it is bad practice, it is just for demo purpose.
int main()
{
func();
return 0;
}
//test.c
void func()
{
...
}
we can see that above code compiles and can be linked by linker, but the same thing doesn't apply to variables as:
//main.c
int main()
{
sum += 1;
return 0;
}
//test.c
int sum = 2020;
then this code won't compile and can't be linked, and we have to add extern int sum; before main function in main.c.
But why we don't need to add extern in main.c as:
//main.c
extern void func(); //or `void func();` since functions are by default external
// without above line, it still compile
int main()
{
func();
return 0;
}
is it a little bit inconsistent here?
Note: by saying " Functions are by default external.",my understanding is: we can save some keystokes without typing extern , so void func(); == extern void func();, but we still need to add void func(); before main function in main.c, isn't it?
Both programs are incorrect since C99 and may be rejected by the compiler. An identifier may not be used in an expression without previously being declared.
In C89 there was a rule that if you write something that resembles a function call, and the function name has not previously been declared, then the compiler inserts a function declaration int f(); . There was not a similar rule for use of other identifiers that aren't followed by parentheses.
Some compilers (depending on compiler flags) will, even if set to C99 or later mode, issue a diagnostic and then perform the C89 behaviour anyway.
Note: your program still causes undefined behaviour in C89 because the implicit declaration is int func(); but the function definition has void func() which is incompatible type.
The compiler doesn't need to know anything about a function, in order to generate code to call it. In the absence of a prototype, it might generate the wrong code, but it can generate something (in principle, at least -- standards-compliance might forbid it by default). The compiler knows the calling convention for the platform -- it knows to put the function arguments onto the stack or into registers as required. It knows to write a symbol that the linker can later find and fix up, and so on.
But when you write "sum++", the compiler has no clue, lacking a declaration, how to generate code for that. It doesn't even know what kind of thing "sum" is. The code needed to increment a floating-point number will be completely different to that needed to increment an integer, and may be different from that needed to increment a pointer. The compiler doesn't need to know where "sum" is -- that's the linker's job -- but it needs to know what it is, to produce meaningful machine code.
But we don't need to add extern for the function in main.c as extern void func(); or void func();(as functions are implicitly extern prefixed) and the code still compile?
That's correct. Functions are by default external.
To make functions specific to a local source file (translation unit), you need to specific static for them.
Variables, on the other hand, are visible in the source file only. If you want to make some variable visible outside the source file where it is defined, you need extern for it.
There are two completely different topics - function prototypes and linkage.
void foo(void);
provides the extern function prototype needed by compiler to know the number and type of parameters and the type of the return value. Function has an external linkage - ie can be accessed by other compilation units
static void foo(void);
provides the static function prototype. Function has an no external linkage - ie it cannot be accessed by other compilation units
By default functions have an external linkage.
Objects (global scope).
int x;
Defines the object x having the external linkage and type int.
If you define another x object in another compilation unit the linker will complain and emit an error.
extern int x;
Only declares the object x without defining it. The object x has to be defined in other compilation unit.
This question already has answers here:
Must declare function prototype in C? [duplicate]
(10 answers)
Closed 7 years ago.
I have two source files test1.c and test2.c.
In test1.c:
#include <stdio.h>
void main() {
checks(); }
In test2.c:
#include <stdio.h>
void checks(){
printf("This is a sample Text");
}
In this case I can successfully build and run this program.
So why should I use:
void checks();
To declare the function?
It seems perfectly fine now.
I am Using C99.
In your case, the check() function has a very simple prototype and the default prototype applied by the C compiler is to accept anything as argument and to return an int. It is probably what is done here (except that, as you do not store the result of the function it is optimized out without noticing it).
If you want to check my theory, try to write this (and it should work until it reaches the linking phase):
int result = check();
At the end, your code work because the linker finally find something that work to plug for the check() function (yet, it should still expect an int at some point).
In fact, the declaration of a function prototype is only useful in two cases:
The code of the function and the use of the function are in the same file.
When you use the function before its declaration (code source), then you need to tell the compiler what to expect when trying to statically type the function you are writing (the compiler read a source code file from top to bottom).
For example:
int bar (int a, int b, bool c);
int foo (int a, bool b) {
int result = bar (a, a, c);
...
}
int bar (int a, int b, bool c) {
...
}
The code of the function the use of the function are not in the same file.
Then, you usually get the definition of the function through a header file which collect all the information needed by the compiler to know how to statically type your code. The header file (*.h) contains all the prototypes of the functions of the module you are using. The implementation of the functions will come after at linking time.
Note that, I usually try to avoid the first case because it is really not logical. When you read a source code, you go from top to bottom, just as the compiler do, and you expect to find the function definition before its usage... So, it is much more logical to structure your code in a way that do not need to require such artifacts. In my humble opinion...
K&R c page 83 says the following:
The static declaration, applied to an external variable or function, limits the scope of that object to the rest of the source file being compiled. External static thus provides a way to hide names like buf and bufp in the getch-ungetch combination, which must be external so they can be shared, yet which should not be visible to users of getch and ungetch.
How could any external variable be visible in another file without an extern modifier on the variable in the new file anyway? Is there some type of added protection for variables with the static storage class?
What is the purpose of using static on an external variable? Any simple examples?
Edit:
I think I'm confusing people with my question, so I'm going to write it out as code. I'm expanding the idea to include functions as well:
contents of file 1
void somefunc(void);
int x;
int main()
{
....
}
void somefunc(void)
{
....
}
file 2
int x;
void somefunc(void);
void somefunc(void)
{
....
}
Notice that int x and somefunc() in file 1 are not visible in file 2, and vice versa. That is, unless we include an extern modifier on int x and/or somefunc() in either file, the matching function and variable names from the files will be invisible to one another.
Why would we need to put static on one of these variables or functions to prevent the variable or function from being visible in the other file if we already have to knowingly use an extern to make the function or variable visible in the other file?
The code would need to look like this for contents of file 2 to be visible in file 1:
extern void somefunc(void);
extern int x;
int main()
{
....
}
void somefunc(void)
{
....
}
file 2
int x;
void somefunc(void);
void somefunc(void)
{
....
}
There is a difference of terminology between K&R2 and the C Standard.
K&R2 uses the wording external variable for a file-scope variable, and uses the wording external static to specify a file-scope variable declared with the static storage class specifier. In the C Standard the word external is usually reserved for linkage and not for lexical scope.
Quoting what you quoted:
External static thus provides a way to hide names like buf and bufp in the getch-ungetch combination, which must be external so they can be shared, yet which should not be visible to users of getch and ungetch.
It just means that the static variables are not function scoped static variables. They are external to functions but they are static in the file.
Making them static in a file makes them visible to getch and ungetch but not to other functions in other files.
Update, in response to edited question
You said,
Notice that int x and somefunc() in file 1 are not visible in file 2, and vice versa. That is, unless we include an extern modifier on int x and/or somefunc() in either file, the matching function and variable names from the files will be invisible to one another.
That is an erroneous conclusion.
The line
int x;
equivalent to:
extern int x;
int x;
The line
void somefunc(void);
is equivalent to:
extern void somefunc(void);
If you compile the "file 1" and "file 2" and link the resulting object files to create an executable, you will get linker errors to the effect that int x and void somefunc(void) are multiply defined.
In order to keep them visible only in the respective files, you will have to make them static in the file scope.
static int x;
static void somefunc(void);
What are the uses of the keyword static?
This simple question is rarely answered completely. Static has three distinct uses in C:
(a) A variable declared static within the body of a function maintains its value between function invocations.
(b) A variable declared static within a module1, (but outside the body of a function) is accessible by all functions within that module. It is not accessible by functions within any other module. That is, it is a localized global.
(c) Functions declared static within a module may only be called by other functions within that module. That is, the scope of the function is localized to the module within which it is declared.
Most candidates get the first part correct. A reasonable number get the second part correct, while a pitiful number understand answer (c).
From A āCā Test: The 0Ć10 Best Questions for Would-be Embedded Programmers
Think about such a situation:
If you have three files, file1 and file 2 both have int x, but with different values, then in file3 you have extern int x. How could the compiler know which x you want? That's when you need extern.
I am writing a code in C which has the following basic structure:
Part A: Starting/Init of the main module, calling of various sub-modules and final compliation of the results from the sub-modules.
Part B: Actual execution of the sub-modules.
Now, part A has its own main.c and main.h file
Part B has three modules:
sub1.c/sub1.h
sub2.c/sub2.h
sub3.c/sub3.h
There are a lot of common variables and functions that are used in the sub-modules.
I would like to have a common module which could be #included in all the sub-modules and all the common functions/variables be used. (common.c and common.h)
Now, for the common functions, I can declare them in common.h and then define in common.c and then they could directly be used in all the sub-modules.
But there are a lot of common data variables/members also which i want to 'common' out.
What would be the most efficient way of doing this, so that i could directly use them in all the sub-modules?
In c++, it could just be added to common.h and then could be used with any file that includes common.h but i believe that it is a little different in c.
Could someone please help explain the difference?
thanks
In C or C++:
Should go in a .h:
// declaration, means it's defined somewhere else
// can declare it as many times as you want
extern int yourVariable;
Every object (as in the intermediate file generated during the compilation process for a .c or .cpp file, not an object in OOP) that wants to use a variable needs to know about it (thus have a definition somewhere).
Should go in a .c/.cpp:
int yourVariable = 3; // definition, should only define it once
int yourVariable2; // also a definition
The extern keyword is optional for functions.
int square(int num); // function declaration (.h)
extern int square(int num); // same as above
int square(int num) { return num*num; } // function definition (.c)
In C++:
Should go in a .h:
// this is a declaration
class yourClass
{
int yourVariable;
}
Should go in a .cpp:
int yourClass::yourVariable = 3;
I could be wrong, but I'm not aware of difference between C and C++ in this regard (except that C++ has classes).
Does the order in which C objects appear on the file matter?
For example, in functions, if I create two functions and the one above references the other one will it work? (Yes it will, I've tried it.)
Is the same in effect for static functions, INLINE functions, etc.?
Is the same in effect for structs? What happens if I reference a struct which is defined further down on the .c file?
Is this to any extend compiler-specific? How does the compiler work in this case? Does it first scan the whole file for all declarations/definitions and then attempts to dereference functions/symbols?
First, if by "if I create two functions and the one above references the other one will it work?" you mean something like this:
int foo()
{
return bar();
}
int bar()
{
return 0;
}
Then the compiler may do educated guesses at what bar() is, but it will at least spit a warning if bar() wasn't already declared. For symbols that can't be called (like variables or types), it's an outright error if they're used before they're declared.
In C, whenever you use an identifier (and no matter the kind of the identifier: it may be a function, a variable, a type, etc.), it should be declared beforehand. The various modifiers you may add to any identifier (like you said, static, inline and all the others) have no impact on this.
Do not confuse declaration and definition. A declaration is just telling the compiler that a name exists; a definition actually tells the compiler what it is.
For instance, this is a definition:
int bar() { return 4; }
Notice how it has a body, with (simple) code inside.
This is the matching declaration:
int bar();
The compiler will gladly accept the use of a function as soon as it sees either the declaration or the definition for it. For organization reasons and better flexibility, it's often better to write declarations for all your functions at the top of your C file (or inside an included header file) then the definitions.
So, my first example should look like this:
int foo();
int bar();
int foo()
{
return bar();
}
int bar()
{
return 0;
}
With the declarations above the C code, I can change the order of the functions in any way I like.
Typically something must be defined above where you use it. You can avoid this in different ways for different situations.
For functions, just provide a prototype above where it's called and all will be well.
int trol(int a, int b);
// use trol(int, int)
int trol(int a, int b) { }
If you have two functions, a and b, and they call each other and are defined in the order of: a, b, then you must provide b's prototype above the definition of a. a's prototype is not required because it is defined above where it is used inside b. Then the compiler will have no problems.
One other special case for functions is that you can use a function without declaring it and the compiler will try to infer the signature from the call. This answer explains it pretty well I think: Must declare function prototype in C?
For structs, you can use pointers to them before they are actually defined (but you can't access any of the fields) by providing a forward declaration:
struct s;
// use s*'s
struct s { };
(The above scenario facilitates recursive data structures like linked lists and trees; you can use pointers to structs before they are fully defined because the size of any type of pointer is constant.)
It matters, because if the compiler doesn't know what the function is - it will try to 'guess' (create a default int foo() prototype with matching parameters), and if your call is incorrect - you'll have mismatches (build errors, implicit castings, whatever).
It is common practice (if not even required) to declare the function before calling it (through prototypes aka forward declarations).
For functions with variable parameter lists (like printf) you must have a forward declaration for them to work properly. For example this code will not compile:
int foo(int a)
{
b(a);
b("hello", "kitty");
}
void b(int a, ...)
{
printf("%d", a);
}
But this - will:
#include <stdio.h>
int foo(int a)
{
return b(a);
}
int b(int a)
{
return printf("%d", a);
}
(with warning about the implicit forward declaration)
So in order to avoid dealing with the order of the objects in the file - use prototyping (forward declarations) to let the compiler know what's following.
From my experience, everything in C has to be written with the referenced "object" before the reference is made. I don't think this is specific to any compiler, but maybe there are some which I haven't found. Basically, everything always has to be:
Object Declaration
...
Object Reference