------------------blah.h------------------------
#pragma once
namespace SomeNamespace{
static void someMethod(){}
}
-----------------blah.c--------------------------
#include “blah.h”
int main(int argc, char**argv){
SomeNamespace::someMethod();
return 0;
}
The above works fine but if I omit ‘static’ I get:
>stdafx.obj : error LNK2005: "void __cdecl SomeNamespace::someMethod(void)"
(?someMethod#SomeNamespace##YAXXZ) already defined in Dude.obj
1>...\Debug\Dude.exe : fatal error LNK1169: one or more multiply defined
symbols found
I read about what ‘static’ does to non-member functions –
http://www.velocityreviews.com/forums/t284052-static-functions.html
…
...give it internal linkage so that it won't be visible outside the compilation unit -- i.e., (over-simplified) the linker will not see it.
This use of 'static' is deprecated, and imposes the limitation that the function cannot be used as a template argument.
The modern way is to instead place the function in an anonymous namespace…
But the thing is I want the method to be exposed. What am I doing wrong?
Declare your function in .h (i.e. void foo(int x);)
Define then in .c (i.e. void foo(int x) { ... })
Related
gcc (Ubuntu 9.3.0-17ubuntu1~20.04) 9.3.0
I'm experimenting with inline and external definitions and here are 2 source files linked together:
foo.c:
#include <stdio.h>
void foo(void){
printf("Test external definition\n");
}
main.c:
#include <stdio.h>
inline void foo(void){
printf("Test\n");
}
int main(void){
foo();
}
Compiling an linking 2 files together Test is printed in console.
N2346::6.7.4/p6 provides that:
It is unspecified whether a call to the function uses the inline
definition or the external definition.
and
If all of the file scope declarations for a function in a translation
unit include the inline function specifier without extern , then the
definition in that translation unit is an inline definition. An inline
definition does not provide an external definition for the function,
and does not forbid an external definition in another translation
unit.
So in the example there are inline definition and external definition. And it's unspecified which one is called.
I ran tests and in my case the inline definition was called. Is there a way to force gcc to call external definition? Maybe there is some flag?
Citing from 6.7.4/10:
A file scope declaration with extern creates an external definition.
For the external definition to be available to choose from (however the compiler chooses) there must actually be an extern function declaration.
From the example:
inline double fahr(double t) { ... }
...
extern double fahr(double); // creates an external definition
I'm trying to declare a global function accessible through different *.c files.
I have declared it in param.hxx, defined it in param.cxx and I would like to access it in compute_grid.c.
Unfortunately, during the compilation I have the following error :
compute_grid.c:(.text+0x5) : undefined reference to « grid_create »
I'm not very familiar with such functions declarations in C. Actually I'm building a module part of a big program, I've copied those declaration from another file of the code witch seems to work ?!
Unfortunately, the program is hugely confidential, I don't have access to all the sources but I will do my best to give you expurged parts...
param.hxx :
typedef struct grid_t
{
int *test;
} grid_t;
void
grid_create(void);
extern grid_t *grid;
param.cxx :
#include <malloc.h>
#include "param.hxx"
grid_t *grid;
void grid_create(void)
{
grid = (grid_t*)malloc(sizeof(grid_t));
grid->test = (int*)malloc(sizeof(int));
*grid->test = 123;
}
compute_grid.c :
#include "param.hxx"
void
compute_grid()
{
grid_create();
return;
}
Thank you for your help !
.cxx is one of the extensions used for C++ files. Your compiler may be using the extension of the file to compile the source as C++. When the C file is compiled, it generates an unresolved reference to the C symbol grid_create, but the compiled C++ file defines grid_create as a C++ symbol. Thus, the linker will leave the C symbol reference to grid_create unresolved, since there is only a C++ symbol associated with void grid_create(void).
You can try to guard the header file so that the C++ compiler will generate a C symbol rather than a C++ one.
#ifdef __cplusplus
extern "C" {
#endif
void
grid_create(void);
#ifdef __cplusplus
}
#endif
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 */}
I have a weird problem in my Geany project. The project is extremely simple and contains 3 files all in the same directory: main.c, foo.h and foo.c.
Compiler error:
In file included from main.c:1:0:
foo.h:4:12: warning: ‘bar’ used but never defined
static int bar(void);
^
/tmp/cc0zCvOX.o: In function `main':
main.c:(.text+0x12): undefined reference to `bar'
Compilation failed.
collect2: error: ld returned 1 exit status
What is going wrong?
main.c:
#include "foo.h"
int main(int argv, char* argc[])
{
bar();
return 0;
}
foo.h:
#ifndef _FOO_H_
#define _FOO_H_
static int bar(void);
#endif // _FOO_H_
foo.c:
#include "foo.h"
#include <stdio.h>
static int bar(void)
{
printf("Hello World\n");
return 1;
}
If a function is declared as static, the function is in file scope, means the scope of the function is limited to the translation unit only (in this case, the source file). Other functions which are present in the same compilation unit can call the functions, but no functions present outside the compilation unit can see the definition (presence) or call the function.
Related: From C11 standard document, chapter , linkage 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.(30)
and, footnote (30),
A function declaration can contain the storage-class specifier static only if it is at file scope;
Solution: Remove the static in the function definition and declaration.
FWIW, there is not much meaning of putting the forward declaration of a static function in a header file. Anyway, the static function can not be called from other source files.
I was told that a function defined as static in one .c file is not accessible from other files. But in the following program, I can access the static void show() function from another file. Is my understanding of static functions in C wrong?
a.h (first file):
static void show()
{
printf("I am in static show function in a.c");
}
b.c (another file):
#include"a.h"
void main()
{
show();
}
Remember that #includes work by copy-and-pasting the content of the included file. So in your example, after the #include has been processed, you get this:
static void show()
{
printf("I am in static show function in a.c");
}
void main()
{
show();
}
So clearly main can see show.1
The solution is to not #include .c files. In general, you should only #include header (.h) files. Your static functions shouldn't be declared or defined in the header file, so main will not be able to see it.
1. However, you now actually have two definitions of the show function, one in a.c and one in b.c. For static functions, this isn't a problem, but for non-static functions you would get a linker error.
static keyword changes the linkage specification to Internal Linkage.
A function marked as static will only be visible in that Translation Unit(TU).
Perhaps, You have same named symbols available in that particular TU, where you access the function. The how part of it can be only answered after you show us the code.
EDIT:
When you define a static function in header file, A copy of the same function gets created in every Translation Unit where you include it.Each instance of such a function is treated as a separate function(address of each function is different) and each instance of these functions have their own copies of static local variables & string literals.
Clearly, this will work but this might as well increase the size of your generated binary.
The other answers are correct, but it's not quite accurate to say that the static function is not accessible from another file. It is possible to access the function through a function pointer. It would be more accurate to say that the name of the function is not accessible in another translation unit.
Remember that converting C source code to an executable program consists of conceptual stages, including:
preprocessing (in which #include directives are replaced with the contents of the included file
compilation (which processes one translation unit at a time)
linking (in which the translation units are put together into the final program)
Suppose we have three files. foo.h:
typedef void (*void_function_p)(void);
extern void_function_p foo(void);
foo.c:
#include "foo.h"
#include <stdio.h>
static void baz(void) {
printf("worked!\n");
}
void_function_p foo(void) {
return baz;
}
bar.c:
#include "foo.h"
#include <stdio.h>
int main(void) {
(*foo())();
return 0;
}
This program compiles and prints "worked!" when it runs.
There are two translation units here. One is the code in the preprocessed foo.c (which, because of how #include works also includes the code in foo.h and stdio.h). The other is the code in the preprocessed bar.c (which, again, has its own copy of the code in foo.h and stdio.h).
By having the function foo return a pointer to the static function baz, we are able to call baz from the main function.
Now, consider what happens if we modify main to look like this:
int main(void) {
(*foo())();
baz();
return 0;
}
This code will result in a linker error because the name baz in this translation unit cannot be linked to the definition of baz in the other translation unit.
This is the first advantage of static functions: another programmer cannot accidentally access our baz function from another translation unit.
Now, consider what happens if we modify bar.c to look like this:
#include "foo.h"
#include <stdio.h>
static void baz(void) {
printf("still works!");
}
int main() {
(*foo())();
baz();
return 0;
}
This code will compile, and print "worked!" followed by "still works!"
This is the second advantage of static functions: we've defined two functions (in different translation units) with the same name.
If you try to put both static definitions in the same translation unit, you will get a compiler error about defining baz twice.
As a final note, if you take the program as it now stands and remove all the statics, it will result in a linker error because baz has been defined twice (with external linkage), which is not permitted.