Say we have a library that defines the following internally used function skip_comments, that is used only by the translation unit it is defined in
void skip_comments(...)
{
}
void another_function()
{
skip_comments(...) //calls the above function --- (1)
}
Now this library is used by another process which also has a function with the same name skip_comments.
This will cause a function name conflict between the library function vs the function defined in the process. So at the point (1) I might expect it to call the process's function instead of the library function which clearly is a bug.
As a possible fix, I made the skip_comment function static and now the bug seems to be fixed. But I'm not sure if this is a proper fix
My question is, would defining the skip_comment as static ensure that at (1) such a name conflict will not occur? ie.
static void skip_comments(...)
{
}
void another_function()
{
skip_comments(...) // will it always call the internal function?
}
Or the only solution is to make sure we define a unique name for functions such as adding prefixes?
Declaring a function as static means that it will only be accessible by the translation unit where it is declared. (Translation unit meaning the .c file and all .h files included by that .c file.)
So yes, declaring it as static will solve your name conflicts. Given that you do this consistently everywhere and not just in one file.
However, it is good practice to prefix all identifiers based on the module where they belong, so that is perhaps the best solution regardless.
Related
I am making a low level library that requires initialization to work properly which I implemented with a init function. I am wondering if there is a way to make the init call be called once the user calls a library function ideally without:
Any overhead
No repeated calls
No exposed global variables. (my current solution does this, which I don't quite like)
my current solution as per comment request:
bool isinit = 0;
void init()
{
isinit = 1;
// init code
}
void lib_function()
{
if(!isinit) init();
// function code
}
The compiler seems to be smart enough (using -0fast on gcc) to not make that comparison each time a lib_function is called, but this still exposes a global variable which I don't like.
Best way to abstract away an init function?
Surely your library has some state. Typically, a library exposes functions that work on a specific structure. Do not use global variables - do not write spaghetti code. Expose the structure that holds the state of your library, and make all functions of your library take a pointer to the structure as an argument. Use a namespace - prepend all exported symbols with a prefix. An init function is just like int lib_init(struct lib_the_struct *t); - it will be self-understandable that users need to initialize the structure with that function before use. For example: fopen(), pthread_create.
Write an init function in your library. Write clear documentation stating, that the user of your library has to call the function once before calling any other function. For example: https://curl.se/libcurl/c/curl_global_init.html .
If you're happy with a solution that is a common extension rather than part of the C standard, you can mark your init function with the constructor attribute, which ensures it will be called automatically during program initialization (or during shared library load if you eventually end up using that).
I would fix this with assert so that the if will dissappear in release build and if you forget to call the init_function somewhere you get the error while developing.
Also turn isinit into a static so every library can have its own variable with the same name.
#include <assert.h>
#ifndef NDEBUG
static int isinit = 0;
#endif
void lib_function()
{
assert(isinit && "library: init not called");
}
There will be overhead if you run if(!isinit) init(); each time you call a function. At least an extra branch.
As for removing global variables, do in your example but static bool isinit = 0;. This reduces the scope of the variable to the local translation unit (.c file and all .h files it includes). It's no longer "global". Note that this isn't ideal in multi-threaded scenarios - you will have to protect the variable with a mutex then.
Overall though, what you are trying to do isn't a good idea. It is very common convention for C libraries to have an init function and the user of the library is expected to call it before calling anything else or they are to blame, not your library. Naturally you have to make this clear to them with source code documentation. It is common to have a list of prerequisites in source code comments together with every function declaration placed in the header file of the library.
I'm currently practicing a unit test with GTest, and noticed that I didn't declare all functions written on the target source code (target.c) to its header (target.h). Since I didn't do the test for those undeclared functions, I couldn't notice until now.
Now, it seems that those header-undeclared functions work as 'private' functions since they are not callable from the test code (which includes header of the target source code).
Can I consider this as a way to declare a private function or should I be aware of something else for safety?
No. that does not make your function private. It just then requires the caller to extern that function themselves. Using the static key word is the appropriate way to create a private function. Eg:
static void myfunc ()
{
...
}
Not including it in the header doesn't make it a private function, since any other C file could add an extern void myfunc() in either their header or C code and gain access to that function. At compile time, all of that is going to be linked (assuming you are compiling all the files).
BUT all static objects will only have module level (or file scope) visibility
The same goes for variables you only want in the filescope.
I am coding in the Cypress PSoC IDE (C99 ARM_GCC). When I use an identically named function in two *.c modules (for example void MyClear()) I get the error:
Build error: multiple definition of `Clear'
MyClear() is not mentioned in any header, and I presumed that it is private to the .C file but I'm obviously wrong.
Point 1:
In C, functions are global by default.
There is no concept of private in C. FWIW, there is static, however, which limits the scope of the function to the translation unit only . See this previous question and the answers for some clarifiction.
Point 2
You get this error in linking state. When all the translation units have been compiled and about to be linked together, linker can see more than one definition of the function and hence throws the error.
Point to note: You don't define functions in header files. you declare them, and as long as declarations don't conflict, you can have any number of declarations even inside a single translation unit.
Functions are public (meaning their name gets exposed to the linker) if not defined with static.
functions can't be private in C. try defining it with static
You are linking both the files to create one executable binary isn't? And hence there cannot be a duplicate definition of a function.
Compiler will resolve the function names (symbols) to unique addresses in the executable binary. If it sees two definitions, it has a dilemma which one to choose for when the function is called during run, the execution can jump to one location and that needs to be pre-determined. As such compilers aren't happy with multiple definitions.
To get over you could use static with that function.
And here is the best answer to what is static in c.
In our project, we have pretty big C file of around 50K lines, written in 90's.
I wanted to split the file based on the functionality. But, all the functions in this file are declared as static. So, file scoped. If I split the file, then the function in file1 cannot call function in file2 and vice-versa.
But, My TL feels like that there could be memory optimization by using static functions.
I wrote some sample code to see if the stacks are different for different threads.
It seemed like it was. Could someone please enlighten me the difference between static function and a normal one other an file scope?
In C, while defining a function, the static keyword has the following 2 major consequences :
Prevents the function name from being exported (i.e. function does NOT have external linkage). Thus, preventing linkage / direct calls from other parts of the code.
As the function is clearly marked private to the file, the compiler is in a better position to generate a complete call-graph for the function. This may result in the compiler deciding to automatically in-line the function for better performance.
All functions are implicitly declared as extern, which means they're visible across translation units. But when we use static it restricts visibility of the function to the translation unit in which it's defined. So we can say Functions that are visible only to other functions in the same file are known as static functions.
The most important difference is you cannot call the static function in any other files. i think so ,yeah?
How can I declare and define a function so that it is only accessible from a single function? I can declare a function in another function. But since local function definitions are illegal (according to Visual C++) I must define the function at global scope, making it possible for other functions to call it.
void f1() {
void f1_private();
f1priv();
}
void f1_private() {
}
void f2() {
f1_private(); // Legal
}
Is it possible to make f1_private only accessible from f1? If not, what are the uses for locally declared functions?
You can put both functions into a single separate file and make the one you want to be less visible static. A static function in C is only accessible from the same source file in which it was declares (sort of a poor-man's namespace concept).
You then just expose the visible function in your header files as you'd normally do.
The best you can do is to put the two functions in their own file, and declare the "private" one to have static linkage (by prefixing the declaration with the word 'static'). Functions with static linkage are accessible only withing their compilation unit (usually meaning the same file, in most build systems).
If the non-private function has to be called from elsewhere, you would then have to either write its prototype in each file it is called from, or create a header file containing the prototype which is included in each file it is called from.
No.
But you can write in C++, declare method inside class, make method private, and make another class friend of first class.
Put a comment on it.
//For use only by foo.
If someone is really gung-ho about using it, they will find a way despite your best efforts. Even if it means just copying and pasting the code, or refactoring the code. The best thing to do is let them know they shouldn't.
You can also encapsulate it by making it private, if it's in a class. Or static if it isn't.
// at the bottom of your .c file
static void foo()
{
}
void dude()
{
// foo only accessible here, unless you have forward
// declared it higher up in the file
foo();
}
However, note that even static methods can be called outside file scope through a function pointer.
You can declare a separate class, with a public member for one function, and a private member function for the one you want only accessible from the other. If this is only used within a class you can make it an internal class.