How does splint know my function isn't used in another file? - c

Splint gives me the following warning:
encrypt.c:4:8: Function exported but not used outside encrypt: flip
A declaration is exported, but not used outside this module. Declaration can
use static qualifier. (Use -exportlocal to inhibit warning)
encrypt.c:10:1: Definition of flip
Since I called splint only on this file how does it know that?
#include <stdio.h>
#include <stdlib.h>
int flip( int a)
{
int b;
b = a;
b ^= 0x000C;
return b;
}
int blah(int argc, char *argv[]) {
FILE *fp = NULL, *fpOut=NULL;
int ch;
ch = 20; flip(20); return (ERROR_SUCCESS);
}
I even got rid of main so that it could not figure out that the file is complete in any way. I am totally stumped!

You might find that if you included a header that declared flip() - as you should, of course - then splint would not complain. You should also declare blah() in the header as well.
I'm not wholly convinced that this is the explanation because blah() is not used at all (though it uses flip()) and you don't mention splint complaining about that.
However, it is a good practice to make every function (in C) static until you can demonstrate that it is needed outside its source file, and then you ensure that there is a header that declares the function, and that header is used in the file that defines the function and in every file that uses the function.
In C++, the 'every function should be static' advice becomes 'every function should be defined in the anonymous namespace'.

Since I called splint only on this file how does it know that?
You have answered your question. You've fed in one file to lint, so lint knows there is only file to be taken care of (apart from the standard header includes, of course).

int flip() is not declared as static, so it can be potentially used externally. Since you invoked splint with only one source file, it correctly says that your function, if not used externally, must be declared static

It can only report on what it sees. Ignore the warning or follow the instructions to inhibit it if you know better than what it says. Don't assume that a tool like this necessarily knows your program better than you do.
If it really is not intended to be used outside of the file, you can declare it static and it should correct the problem, but it will be inaccessible from other files.

Related

C: Linking functions works without sharing headers or extern declaration

I am currently "playing" around in a quite big and old codebase and, quite unfortunately, it has no fixed style attached to it. So it was just made to work but that also means that quite a lot of it can be described as spaghetti code.
I came across something that I do not fully undersand. Compiler is from ARM/KEIL and it is for an embedded system.
first file:
fileA.c
// prototype
int GetSomething( int a );
// implementation
int GetSomething( int a) {
DoSomething();
}
second file:
fileB.c
// prototype
int GetSomething( int a )
void main ( void ) {
GetSomething(10);
}
There are no headers which have a declaration for the function GetSomething but the function is still correctly linked. Originally, there are a extern keyword in the second file in the declaration of GetSomething, but with or without that results in the same binary. The code has been tests and works.
I've seen Stackoverflow Question but that doesn't seem to cover my case as it seems to have nothing to do with the extern keyword.
I hope that somebody can explain that to me or tell me what is going on. Thanks.
Using header files and #include directives are just a more organized and neater way to use various parts of code in a program at different places.
When you do something like #include "header.h" a copy of header.h is put into the file.
So when you write
GetSomething( int a );
you are essentially doing an alternative to what
#include would normally do.
Another important detail is that function prototypes have the extern storage class specifier by default.
One thing you should keep in mind is that declaring function prototypes across your files manually can result in error prone and hard to maintain code. So it is best to utilize header files and #include directives.

Multiple Inheritance in C

I am stuck with a classical Multiple Inheritance problem in C.
I have created source files Stack.c and Queue.c. Both of them #include a file Node.c (which containing functions to allocate and deallocate memory). Now, I am trying to implement another program in a single file, for which I need to include both Stack.c and Queue.c.
I tried to #include both the files, but the compiler is throwing a conflicting type error.
What is the most correct way to do so?
Thanks in advance!!
Calling this "multiple inheritance" may be confusing because multiple inheritance is an object-oriented programming issue that doesn't arise in C.
It appears to me that your difficulty may be that you are trying to #include executable code (i.e. .c files) instead of linking the .c files and #including header (.h) files that provide declarations for the functions in the .c files.
This will happen if you #include source files (.c)... you are supposed to (for the most part) #include headers (.h). Headers generally provide function prototypes, typedefs, macros, etc. but leave out the actual implementation.
The actual implementation of functions, definitions of variables, etc. should happen exactly once per-compilation unit and usually in a .c file.
If you have other code that needs to re-use functions or variables defined in another compilation unit (e.g. Stack.c), you would #include Stack.h which would provide the function prototypes, global variable names, etc. that you might need.
Once you compile all of your compilation units, it is the linker's job to figure out which object file or library a function or variable is defined in. You drastically complicate its job when you #include "X.c" in another compilation unit, because then you wind up with multiple locations for the same thing (symbols, as the linker likes to call them).
In short, use headers and let the linker do its job.
On a related note, this has nothing to do with multiple-inheritance. That is an object-oriented issue, for languages like C++. The proper name for what you are describing is "symbol collision" or "duplicate symbols".
Without seeing details of your program, it is difficult to say. However, conflicting type errors can often be fixed simply by rearranging your code or adding function prototypes.
You see, functions need to be described before they are invoked when reading the source file top to bottom. e.g.:
char foo1 ()
{
char blah = foo2();
return blah;
}
char foo2 ()
{
return 'a';
}
You'd get a conflicting type error because when it's inside foo1, it hasn't seen the declaration for foo2 yet. Thus it assumes that whatever foo2 is, it will return an int. But in actuality it returns a char. These two aren't the same, so... a conflicting type error is reported.
You can fix this by having foo2 come first in the source code, or by inserting a function prototype:
char foo2 (); // function prototype
char foo1 ()
{
char blah = foo2();
return blah;
}
char foo2 ()
{
return 'a';
}
You can also get a conflicting type error if you include source files, for the same reason. #include "Node.c" is essentially a copy-paste. It would be a good idea to switch from including Node.c to including Node.h with externalized functions. You can also avoid a lot of problems if you give prefixes to your function names in source files you plan to include, like.... nodeInsert, nodeDelete, nodeCompare, etc.

C - Including variable (struct) declarations and functions in separate files

I am working on a C project in which part of the code is generated by a different application. The separate files would contain the following:
Type definitions, main(), and other functions
Variable declarations (whose type definition is in the file above) and functions to work with those variables
As mentioned, the information in the second file is generated by a different program, but it uses the type declarations in the main file. Similarly, the main program uses the variables and functions defined in the second file.
I have tried using the "include" and "extern" statements but have not been very successful at it. Since the two files are getting information from each other, would it be more useful to break them up in three files as follows?
1) Type definitions
2) Variable declarations (using the types defined in file 1) and related functions
3) Main() and the rest of functions that use the two above files
If this was the way to go, how would it work? Would it use include or extern, and how would I need to use these clauses?
Any help you can provide is greatly appreciated. Thank you!
There is nothing wrong with the layout you are suggesting. Perhaps some clarification on what extern and #include do would be helpful.
1) #include is a preprocessor directive which essentially says: `take the named file and pretend it is pasted in place of this directive'
2) extern is a C reserved word. Not to get into too many technicalities, but its meaning is: `the variable named in this statement is defined in a different place'. The space for a variable is reserved by the compiler exactly once, so if a function needs access to the variable in question, some information is needed before the definition is seen by the compiler. An extern declaration has enough information for the function to use the variable and the linker makes sure that a correct variable is used at a later stage.
So in your scenario, the file with type definitions will be #include'd in every file that refers to those types. If you want to collect all the variable definitions in one file, which will be compiled separately from other parts of your project, any file that uses those variables and will be compiled separately, needs to be supplied an extern declaration for each variable defined elsewhere. Note that if you simply include th file with variable definitions, the compiler will see the definition twice (first in the file with the definitions, then in the file that includes it) and assume you are trying to define each variable twice and will issue an error.
Finally, here is a simple scenario (it does not really make sense and is in bad style):
a.c---------
#include "t.h"
mytype a;
mytype b;
int f( int x, int y ) {
return (x + y)*a - b;
}
m.c---------
#include <stdio.h> // for stdout
#include "t.h"
#include "v.h"
int main () {
fprintf( stdout, "%d", a + b - f(1, 2) );
return 0;
}
t.h-----------
typedef int mytype;
v.h-----------
#include "t.h"
extern mytype a, b;
int f( int, int );
v.h and t.h can be combined (it is a question of style and the project requirements). Note that a declaration of f in v.h has an implied extern in front of it.
As outlined in a comment, you will almost certainly need a header — call it header.h — which will be included in both the file containing the main program (file 1, call it main.c) and in the generated file (file 2, call it generated.c).
The header file will contain the type definitions and shared function declarations (and, perish the thought, declarations for any global variables). It will be self-contained and idempotent (see, amongst others, the Stack Overflow questions What are extern variables in C?, Should I use #include in headers?, How to link multiple implementation files in C?, and Linking against a static library).
Both main.c and generated.c will include header.h. To ensure that header.h is self-contained, one (or both) of the files will #include "header.h" as the first header.
Finally fixed. If anybody else has the same problem, I followed Alexsh's steps but I also had to include guards in my .h files to prevent redefinitions (otherwise it wouldn't compile). Thank you very much to both Alexsh and Jonathan for their help!

How to check validity of header file in C programming language

Is there a way in C programming language to check if function prototypes from a header files corresponds to actual function definition in compile time.
For example, if I made header file, and then change signature of some function described in that header file, can I check in compile time if there is a wrong prototype in header file? Is that a job of the compiler or some other tool before compilation?
Thanks.
If you declare the same function name with two different prototypes, the compiler should catch this, i.e.:
int foo(int a, int b);
...
int foo(int a, float b) { ... }
Of course, if you actually rename the function, then the compiler cannot catch it, i.e.:
int foo(int a, int b);
...
int fee(int a, int b) { ... }
Unless, of course, you attempt to call foo from elsewhere. Then the linker will complain.
That is the job of the compiler and in my experience it does it quite well:)
If your function prototype in header file does not match it's definition in the source file, then you cannot use that function in other source file because it is not declared and the compiler will inform you so, by giving an error.
If you use the function, the compiler will give you a linker error, if an implementation for a prototype does not exists. But if you never use the function (for example when you build a library) the linker will not complain.
This is one of the reasons you should make sure you have good code coverage in your tests - if you have for example some unit tests which also gets compiled, the linker will complain. If you have some functions you can not test and will not get called from within your code, you can just write a dummy executable (which does not have to work) which will call all this functions.
The last solution would be to use the clang libraries to write your own code checkers.

Can the C main() function be static?

Can the main() function be declared static in a C program? If so then what is the use of it?
Is it possible if I use assembly code and call the static main() function myself (consider embedded programs)?
No. The C spec actually says somewhere in it (I read the spec, believe it or not) that the main function cannot be static.
The reason for this is that static means "don't let anything outside this source file use this object". The benefit is that it protects against name collisions in C when you go to link (it would be bad bad bad if you had two globals both named "is_initialized" in different files... they'd get silently merged, unless you made them static). It also allows the compiler to perform certain optimizations that it wouldn't be able to otherwise. These two reasons are why static is a nice thing to have.
Since you can't access static functions from outside the file, how would the OS be able to access the main function to start your program? That's why main can't be static.
Some compilers treat "main" specially and might silently ignore you when you declare it static.
Edit: Looks like I was wrong about that the spec says main can't be static, but it does say it can't be inline in a hosted environment (if you have to ask what "hosted environment" means, then you're in one). But on OS X and Linux, if you declare main static, then you'll get a link error because the linker can't find the definition of "main".
You could have a static function called main() in a source file, and it would probably compile, but it would not be the main() function because it would be invisible to the linker when the start-up code (crt0.o on many (older) Unix systems) calls main().
Given the code:
static int main(int argc, char **argv)
{
return(argv + argc);
}
extern int x(int argc, char **argv)
{
return(main(argc, argv));
}
GCC with -Wall helpfully says:
warning: 'main' is normally a non-static function
Yes, it can be done. No, it is normally a mistake - and it is not the main() function.
No you cannot do it. If you will do it you will be unable to compile your program. Because static function is only visible within the same file, so the linker will no be able to find it and make a call of it.
As others have said, no it can't. And that goes double if you ever intend to port your code to C++, as the C++ Standard specifies that main() need not actually be a function.
C has two meanings for 'static'...
static for a local variable means it can be used globally.
static for a global variable means is can only be used in the current file.
static for functions has the exact same impact as denoting a global variable as static ... the static function IS ONLY VISIBLE IN THE CURRENT FILE ...
Thus main can NEVER be static, because it would not be able to serve as the primary entry point for the program.

Resources