Static variables end up in Doxygen docs when they shouldn't - c

I've started using Doxygen for a C project. I have set both EXTRACT_ALL and EXTRACT_STATIC to NO. Still, some of my file-level static variables show up in the documentation that Doxygen generates.
Of this block of definitions, fps_ypos and fps_height are included in the docs:
/* properties of the frames per second text */
static int fps_xpos, fps_ypos;
static int fps_length, fps_height;
static bool show_fps = FALSE;
bool is a typedef for unsigned char, if that matters. This is MSVC C, not C99.
Anyone know what can cause this or what I can do to fix it?
By the way, I'm using Doxygen 1.7.5.1 on Windows.

I'm unsure if it's intended behaviour or not, but as the two variables that are documented are second on the line, I'd suggest changing your code to this, i.e. splitting the declarations up to one per line, if you care enough about it:
/* properties of the frames per second text */
static int fps_xpos;
static int fps_ypos;
static int fps_length;
static int fps_height;
static bool show_fps = FALSE;

Related

Static functions declared in "C" header files

For me it's a rule to define and declare static functions inside source files, I mean .c files.
However in very rare situations I saw people declaring it in the header file.
Since static functions have internal linkage we need to define it in every file we include the header file where the function is declared. This looks pretty odd and far from what we usually want when declaring something as static.
On the other hand if someone naive tries to use that function without defining it the compiler will complaint. So in some sense is not really unsafe to do this even sounding strange.
My questions are:
What is the problem of declaring static functions in header files?
What are the risks?
What the impact in compilation time?
Is there any risk in runtime?
First I'd like to clarify my understanding of the situation you describe: The header contains (only) a static function declaration while the C file contains the definition, i.e. the function's source code. For example
some.h:
static void f();
// potentially more declarations
some.c:
#include "some.h"
static void f() { printf("Hello world\n"); }
// more code, some of it potentially using f()
If this is the situation you describe, I take issue with your remark
Since static functions have internal linkage we need to define it in every file we include the header file where the function is declared.
If you declare the function but do not use it in a given translation unit, I don't think you have to define it. gcc accepts that with a warning; the standard does not seem to forbid it, unless I missed something. This may be important in your scenario because translation units which do not use the function but include the header with its declaration don't have to provide an unused definition.
Now let's examine the questions:
What is the problem of declaring static functions in header files?
It is somewhat unusual. Typically, static functions are functions needed in only one file. They are declared static to make that explicit by limiting their visibility. Declaring them in a header therefore is somewhat antithetical. If the function is indeed used in multiple files with identical definitions it should be made external, with a single definition. If only one translation unit actually uses it, the declaration does not belong in a header.
One possible scenario therefore is to ensure a uniform function signature for different implementations in the respective translation units. The common header leads to a compile time error for different return types in C (and C++); different parameter types would cause a compile time error only in C (but not in C++' because of function overloading).
What are the risks?
I do not see risks in your scenario. (As opposed to also including the function definition in a header which may violate the encapsulation principle.)
What the impact in compilation time?
A function declaration is small and its complexity is low, so the overhead of having additional function declarations in a header is likely negligible. But if you create and include an additional header for the declaration in many translation units the file handling overhead can be significant (i.e. the compiler idles a lot while it waits for the header I/O)
Is there any risk in runtime? I cannot see any.
This is not an answer to the stated questions, but hopefully shows why one might implement a static (or static inline) function in a header file.
I can personally only think of two good reasons to declare some functions static in a header file:
If the header file completely implements an interface that should only be visible in the current compilation unit
This is extremely rare, but might be useful in e.g. an educational context, at some point during the development of some example library; or perhaps when interfacing to another programming language with minimal code.
A developer might choose to do so if the library or interaface implementation is trivial and nearly so, and ease of use (to the developer using the header file) is more important than code size. In these cases, the declarations in the header file often use preprocessor macros, allowing the same header file to be included more than once, providing some sort of crude polymorphism in C.
Here is a practical example: Shoot-yourself-in-the-foot playground for linear congruential pseudorandom number generators. Because the implementation is local to the compilation unit, each compilation unit will get their own copies of the PRNG. This example also shows how crude polymorphism can be implemented in C.
prng32.h:
#if defined(PRNG_NAME) && defined(PRNG_MULTIPLIER) && defined(PRNG_CONSTANT) && defined(PRNG_MODULUS)
#define MERGE3_(a,b,c) a ## b ## c
#define MERGE3(a,b,c) MERGE3_(a,b,c)
#define NAME(name) MERGE3(PRNG_NAME, _, name)
static uint32_t NAME(state) = 0U;
static uint32_t NAME(next)(void)
{
NAME(state) = ((uint64_t)PRNG_MULTIPLIER * (uint64_t)NAME(state) + (uint64_t)PRNG_CONSTANT) % (uint64_t)PRNG_MODULUS;
return NAME(state);
}
#undef NAME
#undef MERGE3
#endif
#undef PRNG_NAME
#undef PRNG_MULTIPLIER
#undef PRNG_CONSTANT
#undef PRNG_MODULUS
An example using the above, example-prng32.h:
#include <stdlib.h>
#include <stdint.h>
#include <stdio.h>
#define PRNG_NAME glibc
#define PRNG_MULTIPLIER 1103515245UL
#define PRNG_CONSTANT 12345UL
#define PRNG_MODULUS 2147483647UL
#include "prng32.h"
/* provides glibc_state and glibc_next() */
#define PRNG_NAME borland
#define PRNG_MULTIPLIER 22695477UL
#define PRNG_CONSTANT 1UL
#define PRNG_MODULUS 2147483647UL
#include "prng32.h"
/* provides borland_state and borland_next() */
int main(void)
{
int i;
glibc_state = 1U;
printf("glibc lcg: Seed %u\n", (unsigned int)glibc_state);
for (i = 0; i < 10; i++)
printf("%u, ", (unsigned int)glibc_next());
printf("%u\n", (unsigned int)glibc_next());
borland_state = 1U;
printf("Borland lcg: Seed %u\n", (unsigned int)borland_state);
for (i = 0; i < 10; i++)
printf("%u, ", (unsigned int)borland_next());
printf("%u\n", (unsigned int)borland_next());
return EXIT_SUCCESS;
}
The reason for marking both the _state variable and the _next() function static is that this way each compilation unit that includes the header file has their own copy of the variables and the functions -- here, their own copy of the PRNG. Each must be separately seeded, of course; and if seeded to the same value, will yield the same sequence.
One should generally shy away from such polymorphism attempts in C, because it leads to complicated preprocessor macro shenanigans, making the implementation much harder to understand, maintain, and modify than necessary.
However, when exploring the parameter space of some algorithm -- like here, the types of 32-bit linear congruential generators, this lets us use a single implementation for each of the generators we examine, ensuring there are no implementation differences between them. Note that even this case is more like a development tool, and not something you ought to see in a implementation provided for others to use.
If the header implements simple static inline accessor functions
Preprocessor macros are commonly used to simplify code accessing complicated structure types. static inline functions are similar, except that they also provide type checking at compile time, and can refer to their parameters several times (with macros, that is problematic).
One practical use case is a simple interface for reading files using low-level POSIX.1 I/O (using <unistd.h> and <fcntl.h> instead of <stdio.h>). I've done this myself when reading very large (dozens of megabytes to gigabytes range) text files containing real numbers (with a custom float/double parser), as the GNU C standard I/O is not particularly fast.
For example, inbuffer.h:
#ifndef INBUFFER_H
#define INBUFFER_H
typedef struct {
unsigned char *head; /* Next buffered byte */
unsigned char *tail; /* Next byte to be buffered */
unsigned char *ends; /* data + size */
unsigned char *data;
size_t size;
int descriptor;
unsigned int status; /* Bit mask */
} inbuffer;
#define INBUFFER_INIT { NULL, NULL, NULL, NULL, 0, -1, 0 }
int inbuffer_open(inbuffer *, const char *);
int inbuffer_close(inbuffer *);
int inbuffer_skip_slow(inbuffer *, const size_t);
int inbuffer_getc_slow(inbuffer *);
static inline int inbuffer_skip(inbuffer *ib, const size_t n)
{
if (ib->head + n <= ib->tail) {
ib->head += n;
return 0;
} else
return inbuffer_skip_slow(ib, n);
}
static inline int inbuffer_getc(inbuffer *ib)
{
if (ib->head < ib->tail)
return *(ib->head++);
else
return inbuffer_getc_slow(ib);
}
#endif /* INBUFFER_H */
Note that the above inbuffer_skip() and inbuffer_getc() do not check if ib is non-NULL; this is typical for such functions. These accessor functions are assumed to be "in the fast path", i.e. called very often. In such cases, even the function call overhead matters (and is avoided with static inline functions, since they are duplicated in the code at the call site).
Trivial accessor functions, like the above inbuffer_skip() and inbuffer_getc(), may also let the compiler avoid the register moves involved in function calls, because functions expect their parameters to be located in specific registers or on the stack, whereas inlined functions can be adapted (wrt. register use) to the code surrounding the inlined function.
Personally, I do recommend writing a couple of test programs using the non-inlined functions first, and compare the performance and results to the inlined versions. Comparing the results ensure the inlined versions do not have bugs (off by one type is common here!), and comparing the performance and generated binaries (size, at least) tells you whether inlining is worth it in general.
Why would you want a both global and static function? In c, functions are global by default. You only use static functions if you want to limit the access to a function to the file they are declared. So you actively restrict access by declaring it static...
The only requirement for implementations in the header file, is for c++ template functions and template class member functions.

how compiler will identify which static variable to read or update?

Below is my code:
#include <stdio.h>
static int a; // this static variable scope is through out the file
int main()
{
static int a; // this static variable scope is only in main()
}
Now in this program compiler will store both variable a to data segment(bss segment to be precise), so if both variables goes to same segment, how compiler will identify which one to access when user wants to change or read any one of them.
For example, if user wants to change the value of variable a which is inside main(), how compiler will identify which 'a' to change in data segment memory.
The compiler knows which static variable you need by context. One way to differentiate the actual variables is by mangling the names. I tried a slightly modified version of your program:
#include <stdio.h>
static int a; // this static variable scope is through out the file
int main()
{
static int a; // this static variable scope is only in main()
a=1;
}
void f()
{
a = 2;
}
If you run the source through the ELLCC demo page (don't forget to turn off optimization!), you can look at what the compiler generates for your favorite target processor. In the assembly language, you can see that the compiler creates two variables: a and main.a. The ELLCC compiler is based on clang/LLVM, but other compilers will do similar tricks.
Looking at a compiler's assembly output is a great way to answer questions like this.

What is the purpose of an external static variable?

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.

Possible to initialize static variable by calling function

Is this possible?
static bool initialize()
{
TRC_SCOPE_INIT(...);
...
}
static bool initialized = initialize();
To make a very long story short, I need to call a series of macros (to initialize debugging messages) as early as possible (before thread X is started, and I don't have the ability to know when thread X is started).
If you're using GCC (or clang), you can use __attribute__((constructor)):
static bool initialized = false;
__attribute__((constructor))
static void initialize(void) {
initialized = true;
// do some other initialization
}
int main(int argc, char **argv) {
// initialize will have been run before main started
return 0;
}
When I originally looked at the question, it was tagged both C and C++. The code could be C or C++ because bool is a type in C99 and C11, just as it is in C++ (almost; in C, you need the <stdbool.h> header to get the name bool).
The answers for the two tags are:
In C++, yes.
In C, no.
They are not the same language. If you need a demonstration, this is as good an example as any.
This should be alright provided the "stuff" you are initializing is defined in the same translation unit as the call to the function that initializes it. In addition, it must be defined above the call site. Otherwise you risk undefined behavior due to use of uninitialized values.
One way to get around this is to use a pointer instead. A statically initialized pointer is compiled into the executable image, so there's no risk of undefined behavior if it's used by statics defined in other translation units. In your static initialization function you dynamically allocate the "stuff" and set the pointer to point to it so you can access it later.
(Since you mentioned threads, I'm going to assume you have POSIX thread functions at your disposal.)
The pthread_once function exists for this exact purpose. Anywhere you need to be sure initialize has already been called, write:
pthread_once(&init_once, initialize);
where init_once is defined with static storage duration, and possibly with external linkage if needed, as pthread_once_t init_once.

c compilation error

These are my errors:
error: static declaration of doct follows non-static declaration
error: previous declaration of doct was here.
And my code is:
int doct(int*); /* <- Second error points here */
private int doct(int *a)
{
static int a=0; /* First error points here */
a++;
*a=a;
return 0;
}
Any suggestions?
Your prototypes should match your actual functions. Yours do not:
int doct(int*);
private int doct (int *a)
Either change the prototype to:
private int doct(int*);
or change the function to:
int doct (int *a)
You should also bear in mind that private is not part of the C language, but people often use it to replace static. This can be made possible by the line:
#define private static
with the only proviso being that that macro must be active wherever you use the private name. If it's not working on your prototype, that's probably because it's not defined at that point. My advice would be to ditch private altogether and use static (if indeed that's how private is defined). People should learn the language, not adopt unnecessary crutches (in my opinion).
Other favourites which I also despise are:
#define global extern
#define begin {
#define end }
The private and global are used to mean local to this file and global to all files respectively. The begin and end are particularly nasty abominations from people who should go back to Pascal where they belong :-)
In addition to that problem, your line:
static int a = 0;
will actually hide the parameter that you're passing into the function (since it has the same name) and:
*a = a;
will cause an error (since it has a different type). It's rarely a good idea to do that. Rename one of them.
This error happens when a function was declared as non-static, then defined static, such as:
void foo(void);
static void foo(void) {}
Make static match on both, either by removing it from both or adding it to both. Make sure you understand what static does.
If your function is marked static, it is only visible in that translation unit. In your case, your declaration has no static meaning "this function will be available, non-statically.", but then you define it statically.
There are other errors. The a in your function will hide the a in the parameter list. You need to give them different names. *a = a won't work because, in that scope, a is an integer, not a pointer. Use a descriptive name like counter for the integer.

Resources