Suppose I have a function that I want to use internally such as private in Java or C++, but I am writing in C. In this case, I have a header file and a c file implementation and the c file has several functions that should not be available to the end user. Is it ok for me to not declare these functions in the header file in order to prevent access to them or is this bad practice / is there a better way?
That's pretty much what you would do in this case and add static to the declared functions. You would declare your public functions in the .h file and the private functions in the .c file.
Let's say you had a .h and .c file as such:
SomeFile.h
void doSomething1(void);
void doSomething2(void);
SomeFile.c
static void doSomething3(void);
static void doSomething4(void);
//These functions can be called by anyone
void doSomething1(void)
{
//function guts here
}
void doSomething2(void)
{
//function guts here
}
//These functions can only be called inside this file
static void doSomething3(void)
{
//function guts here
}
static void doSomething4(void)
{
//function guts here
}
Yes its ok to make some of the functions not available in the header file.
The other options are to separate the header files into 2. One for internal use and other for external user.
Apart from that also you can declare the functions static making them not visible outside the file scope
Declare these functions directly in the .c file as static functions and provide the definitions of the functions in the same file:
Ìn the .c file:
static void internal_func1(void);
static int interal_func2(int a);
static void internal_func1(void)
{
/* body of internal_func1 */
}
static int interal_func2(int a)
{
/* body of internal_func2 */
}
Adding the static keyword makes these functions invisible to other source files (the function identifier will have internal linkage).
Make such internal function static and keep it just in .c file.
See static functions:
If a function is to be called only from within the file in which it is declared, it is appropriate to declare it as a static function. When a function is declared static, the compiler will now compile to an object file in a way that prevents the function from being called from code in other files.
Or in the C standard:
6.2.2 Linkages of identifiers...
If the declaration of a file scope identifier for an object or a function contains the storage-class
specifier static, the identifier has internal linkage.1
1 A function declaration can contain the storage-class specifier static only if it is at file scope ....
Related
I have a static function in a source file that is used by other functions in that same source file. Is it fine to put the declaration for that static function in the header file, even though that header file will be included into other source files? Example:
/* foo.c */
#include "foo.h"
/* exported function; calls g */
void f(void) {
g();
}
static
void g(void) {
/* do something... */
}
/* foo.h */
void f(void);
void g(void);
/* main.c */
#include "foo.h"
int main(void) {
f();
}
Is it fine to put the declaration for that static function in the header file, even though that header file will be included into other source files?
No. Consider the conflict the other source files would have if they had a function/object/macro of the same name.
Even without conflict, an "unused function" warning may occur. #Adrian Mole
By putting static void g(void) in the .h file, it adds an unnecessary potential name conflict.
Simply declare/define that static function at the top of the .c in which it is used.
Is it fine to put the declaration for that static function in the
header file, even though that header file will be included into other
source files?
No. becuse it does not make any sense. and why?
In C, functions are global by default. Unlike global functions in C, access to static functions is restricted to the file where they are declared! Therefore, when we want to restrict access to functions, we make them static.
Another reason for making functions static can be reuse of the same function name in other files. so declaring them static in the header file can cause to name collisons in other source files.
In header files we declare our API functions those we want to expose only. in c files we declare usually auxilary functions as static functions for restricting the scope of those aux functions to the c file only
I have a function which is initially declared in a header file my.h to have external linkage(no storage class specified)
int myfunc(int);
And this function definition and it's call is present in source file my.c
my.c includes my.h
This all is fine.
But now I wanted to make this function myfunc inline
So I declare a new prototype in my.c
as
__attribute__((always_inline)) static inline int myfunc(int)
and define it so in same function as before,
as expected I keep getting an error saying
static declaration of 'myfunc' follows non-static declaration
I need to keep the non-static,non-inline version of this function for a C reference version of code , and the static inline version for a optimized version of the code.
How can I work around this problem , as I need a static declaration of that function., within this existing source/header files setup I have
One way is I change the name of the static inline function to myfuncinline and work with it!
But is there any way within current setup.
A function defined with static storage-class specifier has internal linkage. You cannot refer to it outside that translation unit.
If you cannot change the declaration of myfunc in the header, then write two
functions in the source file. One called myfuncreal, which does all the work and is defined with static inline:
__attribute__((always_inline)) static inline int myfuncreal(int a)
{
//uses parameter a and returns the result
}
And the other called myreal that wraps around myfuncreal, defined as:
int myfunc(int a)
{
return myfuncreal(a);
}
#ifndef DEBUG
static inline
#endif
int myfunc(int);
Assuming DEBUG is defined in your debug builds but not in your optimized builds. Note that this example is for a declaration in a .c file or a definition in a .h file; for a declaration in a .h and a definition in a .c do
/* foo.h */
#ifdef DEBUG
int myfunc(int);
#endif
/* foo.c */
#ifndef DEBUG
static inline int myfunc(int);
#endif
/* code that uses myfunc() */
#ifndef DEBUG
static inline
#endif
int myfunc(int) {/* definition */}
In my application I have a build config for pseudo unit testing (this is more a kind of manual debugging a dedicated function).
In those unit tests I'd like to access functions declared as static in their translation unit.
Is there an option of GCC that would allow me to call static functions from anywhere?
I'd like to avoid:
#if UNIT_TEST_MODE
void myfunction(void)
#else
static void myfunction(void)
#end
{
// body
}
Everywhere!
Thanks for your help :).
There is not need to be verbose. Use a prefix define for every static function:
#if UNIT_TEST_MODE
#define UNIT_TEST_STATIC
#else
#define UNIT_TEST_STATIC static
#end
UNIT_TEST_STATIC void myfunction(void)
{
// body
}
Another option is to move all static function from that .c file to a separate header. That header is included only in that .c file, but it can be included in the unit test .c file if needed. The functions will remain invisible in other files, unless the header is manually included.
(They will have to be defined as static inline. )
As applied to a function or file-scope variable, the static keyword means that the declared function or object has internal linkage. That means such a function or object can be directly referenced only from within the same translation unit. GCC has no option to alter this core provision of the C language, nor should it have.
Your alternatives, then, are either
to give the functions in question external linkage instead of internal linkage, perhaps conditionally, or
to make them available to the test code via an indirect mechanism, such as function pointers initialized and provided to the test code by some facility (another function, a global variable) inside the translation unit.
The first alternative is simpler, but using it means that the code under test is not wholly equivalent to code built for ordinary use. Additionally, this option is not viable if the names of any of the erstwhile-static functions collide with the names of other global objects. This option has been adequately demonstrated in other answers, so I won't go into further detail here.
The pros and cons of the second alternative are more or less the mirror image of those of the first. It is more complicated, but the functions can be tested in the same form that they have in the production build, and you can avoid name collisions by this route. There are many possible variations on this approach; here's one:
test_header.h
#ifndef TEST_HEADER_H
#define TEST_HEADER_H
struct test_pointers {
int (*function_to_test)(const char *);
};
void initialize_test_pointers(struct test_pointers *pointers);
#endif
module_under_test.c
static int function_to_test(const char *);
#ifdef ENABLE_TESTING
#include "test_header.h"
extern void initialize_test_pointers(struct test_pointers *pointers) {
pointers->function_to_test = function_to_test;
}
#endif
static int function_to_test(const char *s) {
// ... whatever
}
the_test.c
#include "test_header.h"
int test_it(void) {
struct test_pointers pointers;
char test_input[] = "test THIS!";
const int expected_result = 42;
int result;
initialize_test_pointers(&pointers);
result = pointers.function_to_test(test_input);
return result == expected_result;
}
No, it can not. This keyword specifies visibility of a function to be translation-unit only, as defined by launguage standard. Ignoring it by a compiler would render it non-conformant.
UPD. To solve your problem, you can indeed do the preprocessor directive trick, as mentioned in comments to your question.
This does not answer your question about GCC, but as a solution to your unit testing problem, you could conditionally compile a wrapper function in the same module,
static void myfunction(void)
{
// body
}
#if UNIT_TEST_MODE
void myfunction_test(void)
{
myfunction();
}
#endif
Or, you could #include the module from a unit test wrapper file,
// unit_test.c
#include "myfunction.c"
void unit_test()
{
myfunction();
}
I want to create a library in C using MPLAB X IDE(ide for PIC developing).
My library ABCLib has one simple source file like this:
file abc.c
void abcTest(int n){
// I want store n as global variable
}
To using this library in MyProject i have to create abc.h inside MyProject header folder:
file abc.h
#ifndef _ABC_H
#define _ABC_H
void abcTest(int n);
#endif;
file MyProject.c(main file)
#include "abc.h"
void main(void) {
abcTest(10);
}
Now, i want to store n as global variable, so, after a call to abcTest() i can retrieve the value of n whereever i want.
I'm developing a library with intention to reuse it in all my projects.
You'll need to declare the variable as external in all files you want to use his global value.
Example:
file abc.c
extern int global_a;
void abcTest(int n){
global_a+=n;
}
file abc.h
#ifndef _ABC_H
#define _ABC_H
void abcTest(int n);
#endif;
file MyProject.c(main file)
#include "abc.h"
int global_a = 0; // always initialize global variables
void main(void) {
abcTest(10);
}
Regards
After compiling the MyProject.c, the abc.h file will be included in the translation unit, so a global static variable should remain visible within that translation unit. In order to access it from external objects you'll have to have a function in the translation unit that can pass the value to the outside.
Otherwise just name it anywhere in your file without scope, it will be global. In order to have a global carry across multiple files, use the extern keyword to tell the compiler that you're referring to a global variable already existent in another linker symbol.
For the first time i was trying to write an actual professional C code for a simple program.
1)I made a header file name Essential_data.h and declared all my functions and global variables in that. I had declared all my variables as extern.. And all function declaration were made normally
eg:
void test ();
extern int x;
2)Then i made another header file named main_data.h and defined all my global variables there.
for eg:int x;
3)I then made corresponding source files containing the definition of the respective functions and included main_data.h in sourcefiles that needed that global variable.
thats all. After when i compiled the project i got many warnings for all functions as
Implicit declaration of function test [-Wimplicit-function-declaration]
so after that i did the following
1) I put an extern in front of the functions declarations in Essential_data.h.
for eg:
extern void test();
2) in the main_data.h i declared the functions normally and wrote
void test ();
both the times my Essential_data.h was in the main function only and no where else.
And then recompiled and later all the warnings disappeared.
So was that the right method or is there any other way of organising them more efficiently?
You should have:
One or more .h files containing extern declarations (functions and objects). These files needs to be included by the .c files that need those symbols. You shouldn't have multiple declarations (each identifier should be declared exactly once)
One or more .c files in which you define the functions and objects
In your example:
/* essential_data.h */
void test ();
extern int x;
/* something.c */
#include "essential_data.h"
int x;
void test()
{
/* ... */
}
/* main.c */
#include "essential_data.h"
/* ... */