If I declare static const variable in header file like this:
static const int my_variable = 1;
and then include this header in more than one .c files, will compilator make new instance per each file or will be "smart" enough to see it is const and will make only one instance for all the files?
I know I can make it extern and define it in one of .c files that include this header but this is what I am trying not to do.
I answered this at length here. That answer is for C++, but it holds true for C as well.
The translation unit is the individual source file. Each translation unit including your header will "see" a static const int. The static, in this context, means the scope of my_variable is limited to the translation unit. So you end up with a separate my_variable for each translation unit (".c file").
The compiler would not be "smart" to create only one instance for all files, it would be faulty, because you explicitly told it not to do so (static).
If you use address of that object - compiler surely creates one instance per each translation unit. If you use only value - it is probably smart enough to avoid creating of object at all - value will be inlined where need.
I guess it will make only one instance for all files. But you can verify it by calling it in different files and check its value
Related
I understand the static keyword is used for creating functions or variables which are "private" to the translation unit (the source file).
However, as far as I understand, in order to make sure a particular function or variable is not accessible from outside the .c file that it was declared in, I can simply not declare it in the corresponding .h file.
For example:
f.c
void public_func() {
// ...
}
void private_func() {
// ...
}
f.h
void public_func();
// no declaration of private_func
So why should I also declare private_func as static? Is that simply a convention or does it have a technical benefit over simply not declaring it in the .h file?
The problem is that compilers work on "translation unit" basis, meaning one .c file and all the .h files it includes. So it is traditionally not able to detect naming collisions across the whole project.
So if you don't make it static, the function has "external linkage" per default. Meaning if have a function private_func and another translation unit in the same project is using the same name, you get namespace collisions during linking and linker errors.
It is also a matter of correctness - private functions/variables should simply not be accessible from the outside, neither intentionally nor accidentally.
I understand the static keyword is used for creating functions or variables which are "private" to the translation unit (the source file).
That's true.
Is that simply a convention or does it have a technical benefit over simply not declaring it in the .h file?
There is a technical point here. Once compiler is done doing it's job it produces an object file. That file has a symbol table, which is later used by linker when the linker puts a program together from separate object files. static functions will not get into that table, so that direct references to that function from other object files will fail with "unresolved reference" error in the linking stage.
Benefits? Well you save some tiny space in you object file, linking stage will go faster, since there will be a smaller table to process. But that's tiny enough to not make a difference, unless we're talking about a made up case of thousands of functions with loooong names.
If you have a non-static function and you omit it's declaration in the header file, the function name still gets into a symbol table. And if I happen to know the declaration somehow (other than from the header) I can still call/reference the function directly from another translation unit, no linker error will happen.
Let's say you write a library that consists of several .c and .h files. The clients of your library will need to use some of the header files to use your library. They should only see the public functions.
But for the implementaiton of your library, you might also use header files so functions in your library can call other (internal) functions.
So you end up with two types of declarations:
For clients of your library
void public_func();
For internal use
static void private_func();
Preferrably, the private and public declarations are in separate header files and the clients of your library only need to include the header files with public functions.
In a multi-source file C application, which is the best place to put constant values, source file itself or in its header file? Provided that constant will be used in that source file only.
Is it a good way to keep static const in header files?
Don't expose information you don't need to. If constant is an implementation detail of single compilation unit, there is no need to pollute global namespace. You can always add it to header later if needed.
Depends on the nature of constant. static creates new constant for each compilation unit header is included in. If constant is huge, it's better to define it once in source file, and declare it with extern in the header.
In my program, I have a file called constants.h that declares the following matrix in a global scope (the matrix should be fully constant - if anyone sees a potential problem, let me know):
static unsigned char const MY_MATRIX[66][9] = {...};
In another file, let's call it main.c, I can actually reference this constant:
doSomething(var1, count, MY_MATRIX[42], TRUE, FALSE, thing);
But then I just read the definition of the keyword static and it's supposed to mean that the variable cannot be accessed outside the file it's defined in. (In this case, the desired behavior is that it should be accessed, but then it seems the extern keyword is the one to use!)
So, can anyone tell me why this works? Why is the variable not invisible? Thanks!
This is because you are declaring a static variable in a header: when you include the header in a C file, you get a brand-new definition independent of the other definitions. If you include the header in two files, you get two independent copies; if you include it in three C files, you get three independent copies, and so on. The copies do not conflict with each other, because the static definition hides them from the linker.
A proper way to make use of a shared piece of data allocated in a static memory is to make the declaration extern in the header, and then add a non-static definition in exactly one C file.
If it's in a header, it's defined in every single source file you include it in (though each source file will have their own instantiation of it - they don't access the same one).
There are two uses of the static keyword:
A static variable inside a function block keeps its value between subsequent calls.
A static global variable or a function is "visible" only in the file it has been declared in.
Here, you define the matrix in a header file, hence it is visible to all the .c files which include that header file. To restrict its visibility, define it in a .c file instead.
Usually when a static variable is declared in a header file its scope is not limited to .h file meaning nothing like header file scope. The translation unit includes the text from header file in source file. Therefore every translation unit including header file gets its own individual variable though it is static scope.
I develop an embedded application which uses the MindTree Bluetooth SDK.
I have the following in a header file:
typedef struct {
UCHAR outputDir;
UCHAR reset;
UCHAR nack;
UCHAR startCondition;
UCHAR stopCondition;
UCHAR busy;
} USCI_ConfigurationFlags;
static USCI_ConfigurationFlags usciConfigFlags = { UCTR, UCSWRST, UCNACKIFG, UCTXSTT, UCTXSTP, UCBBUSY };
Later in two .c files I include the above header and use the usciConfigFlags on different occasions sometimes from within an interrupt.
Is this legal?
I'm trying to understand why(and if it is related to the question) the values of the struct change at runtime, after calling the BT_bluetooth_on method in the SDK.
Thanks,
Adam.
static here doesn't mean what you think it means. It means that the declaration and variable will only be visible in one compilation unit. That is, you have two independent instances of usciConfigFlags.
If you want a global variable, you need to use extern not static and make the actual declaration (without extern) with the initial value in one of your c files.
Also be weary of changing the values in the struct without proper locking. Read-only concurrent access is usually fine.
There is no problem you include the header in two .c file. The static modifier limits the accessible scope of the variable in the file including the header only. The two usciConfigFlags in two different files are not identical.
Also static does not mean constant. So you can modify the value of the structure in whatever way you want.
The following is from wikipedia
In computer programming, a static variable is a variable that has been
allocated statically — whose lifetime extends across the entire run of
the program. This is in contrast to the more ephemeral automatic
variables (local variables), whose storage is allocated and
deallocated on the call stack; and in contrast to objects whose
storage is dynamically allocated.
Prepending a static keyword to a variable makes it visible only in the current translation unit (i.e. if within a function, only that function and if within a file, only that file).
It is never a good idea to define a variable in a header file. Even if you need two static variables in two different files with the same name, it is better that you put in the .c file itself as it helps in better maintaince and readability as you will be clear in which all files it is actually present and is being used.
If you add it in a header file, then at a later point, if some other .c file includes this header, then unneccessarily this variable will included for that translation unit.
Epsalon had suggested other good points which you can consider.
I have a little project in which I named two same name function in two different source file, but while I building the project, the compiler failed with 'func_name already defined in filename.obj'.
Why could not I have two functions with the same name in two different source files? I thought the function should be local to the source file only if when we declared it in the header file will it become global.
And except for changing the filename, are there any other elegant solution to duplicated function name in the C programming language?
In C, a function has global scope by default. To restrict its scope, use the static keyword to make it private to a the module.
The role of the header file is just to publicize the function along with its signature to other modules.
All global names must (with some caveats) be unique. This makes sense because that name is what is used by the linker to connect a function call to implementation of the function itself.
Names with static and local scope need only be unique within their scope.
Whether some thing is declared in header file or in source file makes absolutely no difference for the compiler. In fact, the compiler proper knows absolutely nothing about any "header files", since header files are embedded into source files by so called preprocessor, which does its work before the compiler proper. By the time the source files (with embedded header files) get to the actual compiler, there's no way to tell what was there originally and what was inserted from header files. The source file with all the header files embedded into it is called translation unit. I.e. the compiler proper works with translation units, not with some "source" or "header" files.
In C language all objects and functions declared at file scope have external linkage by default, which means that they are global, unique for the entire program. So, you thought incorrectly. Functions are not local to one source file only.
If you want to make a function (or an object) local to a single translation unit, you have to take some explicit steps. You have to declare it as static. Declaring it as static will give it internal linkage, which essentially means that it becomes internal to its translation unit.
Declaring your functions static will only work if both of them really have to be local to their own translation units. If this is not the case, i.e. if at least one of the functions should be a globally accessible (linkable) function, then you have no other choice but to rename one of functions.
Why could not I have two function with the same name in two differenct source file?
Because the linker needs to know which is meant when you reference it.
Imagine that a.h and b.h both declare my_function(). The compiler generates code for both. Now, imagine that c.c calls my_function() - how does the linker know which of the two versions of the function should be called?
Declare the function static to make it local to the file. In C, every identifier name must be unique.
The elegant solution is namespaces introduced in C++. The solution, if there are few calls to func_name is take one, rename it and recompile.
Something hackerous but quick solution might be this:
//In one of the two source files and any file that calls it
//if your functions is something like this
//void func_name(int) { ... }
//Add the following line
#define func_name SOME_UNIQUE_FUNC_NAME