This question already has answers here:
Is "inline" without "static" or "extern" ever useful in C99?
(3 answers)
What does extern inline do?
(7 answers)
Closed 2 years ago.
divide.h
#pragma once
#include <assert.h>
inline int divide(int a, int b)
{
assert(b != 0);
return a / b;
}
main.c
#include <divide.h>
int main(void)
{
divide(10, 2);
return 0;
}
I am unable to compile the following solely because of the assert. If I remove the assert, everything works fine.
$ gcc --version
gcc (GCC) 8.1.0
$ gcc main.c
main.c:(.text+0xf): undefined reference to `divide'
$ gcc main.c -O3 # Compilation with optimization works as asserts are removed.
When placing the defintion of divide inside a .c file, everything works fine. However, shouldn't the following also work since the function is declared as inline?
The C99 standard says this about inline functions in 6.7.4 "Function specifiers":
An inline definition provides an alternative to an external definition, which a translator may use to implement any call to the function in the same translation unit. It is unspecified whether a call to the function uses the inline definition or the external definition.
So an implementation can choose to not inline a function call in which case there needs to be an external definition of the function. I'd guess that since the assert is a debugging tool, GCC doesn't want to inline functions that have active asserts to aid in debugging.
Related
This question already has answers here:
What is a "static" function in C?
(11 answers)
Closed 2 years ago.
What's the difference between the following scenarios?
// some_file.c
#include "some_file.h" // doesn't declare some_func
int some_func(int i) {
return i * 5;
}
// ...
and
// some_file.c
#include "some_file.h" // doesn't declare some_func
static int some_func(int i) {
return i * 5;
}
// ...
If all static does to functions is restrict their accessibility to their file, then don't both scenarios mean some_func(int i) can only be accessed from some_file.c since in neither scenario is some_func(int i) put in a header file?
A static function is "local" to the .c file where it is declared in. So you can have another function (static or nor) in another .c file without having a name collision.
If you have a non static function in a .c file that is not declared in any header file, you cannot call this function from another .c file, but you also cannot have another function with the same name in another .c file because this would cause a name collision.
Conclusion: all purely local functions (functions that are only used inside a .c function such as local helper functions) should be declared static in order to prevent the pollution of the name space.
Example of correct usage:
file1.c
static void LocalHelper()
{
}
...
file2.c
static void LocalHelper()
{
}
...
Example of semi correct usage
file1.c
static LocalHelper() // function is local to file1.c
{
}
...
file2.c
void LocalHelper() // global functio
{
}
...
file3.c
void Foo()
{
LocalHelper(); // will call LocalHelper from file2.c
}
...
In this case the program will link correctly, even if LocalHelpershould have been static in file2.c
Example of incorrect usage
file1.c
LocalHelper() // global function
{
}
...
file2.c
void LocalHelper() // global function
{
}
...
file3.c
void Foo()
{
LocalHelper(); // which LocalHelper should be called?
}
...
In this last case we hava a nema collition and the program wil not even link.
The difference is that with a non-static function it can still be declared in some other translation unit (header files are irrelevant to this point) and called. A static function is simply not visible from any other translation unit.
It is even legal to declare a function inside another function:
foo.c:
void foo()
{
void bar();
bar();
}
bar.c:
void bar()
{ ... }
What's the difference between declaring a function static and not including it in a header?
Read more about the C programming language (e.g. Modern C), the C11 standard n1570. Read also about linkers and loaders.
On POSIX systems, notably Linux, read about dlopen(3), dlsym(3), etc...
Practically speaking:
If you declare a function static it stays invisible to other translation units (concretely your *.c source files, with the way you compile them: you could -at least in principle, even if it is confusing- compile foo.c twice with GCC on Linux: once as gcc -c -O -DOPTION=1 foo.c -o foo1.o and another time with gcc -c -O -DOPTION=2 -DWITHOUT_MAIN foo.c -o foo2.o and in some cases be able to link both foo1.o and foo2.o object files into a single executable foo using gcc foo1.o foo2.o -o foo)
If you don't declare it static, you could (even if it is poor taste) code in some other translation unit something like:
if (x > 2) {
extern int some_func(int); // extern is here for readability
return some_func(x);
}
In practice, I have the habit of naming all my C functions (including static ones) with a unique name, and I generally have a naming convention related to them (e.g. naming them with a common prefix, like GTK does). This makes debugging the program (with GDB) easier (since GDB has autocompletion function names).
At last, a good optimizing compiler could, and practically would often, inline calls to static functions whose body is known. With a recent GCC, compile your code with gcc -O2 -Wall. If you want to check how inlining happened, look into the produced assembler (using gcc -O2 -S -fverbose-asm).
On Linux, you can obtain using dlsym the address of a function which is not declared static.
I have a main code wich uses some libraries and I been compiling it like this:
gcc importedCFile1.c importedCFile2.c mainCode.c -O3 -lm -Wall -o maincode -lrt
Now I have added CUDA code in mainCode and changed its extension to .cu... So, how can I compile the whole thing?
I tried:
nvcc importedCFile1.c importedCFile2.c mainCode.cu -o maincode
but I got a lot of "undefined reference" to my functions in the imported C files.
To include my C files I am using:
extern "C" {
#include "importedCFile1.h"
#include "importedCFile2.h"
}
And ´importedCFile1.c´ is using some functions and variables declared in ´importedCFile2.c´ and ´mainCode.cu´. Like this:
extern int **se; // Variables from mainCode
extern int *n;
extern int numNodes;
extern int *getVector(int n); // Function from mainCode
extern int iRand(int high); // Function from importedCFile2
This functions are the cause of the undefined references. What should I do?
Also, how do I add the flags I need for the C code, such as -lrt, O3, lm and Wall??
EDIT: You can find a reduced example of the problem here:
https://github.com/mvnarvaezt/cuda/tree/master/minimalExample
If you compile the mainCode.c and importedCFile.c with gcc it works fine. If you compile mainCode.cu and importedCFile.c with nvcc you will get an undefined reference to anExample() (the function in importedCFile.c).
And you comment the header importing importedCFile.c and the call to anExampled() function it would work find.
Your problem is that the C code in importedFile.c is trying to call back C++ functions in mainCode.cu.
In order to be callable from C, C++ functions must have C linkage. Declare getVector() as
extern "C" int *getVector(int n) {
in mainCode.cu, and your example will compile fine.
i'm trying to compile a program for image deblurring.
I try to run
mex apply_blur_kernel_mex.c
where the file apply_blur_kernel_mex.c have the following code
#include <mex.h>
#include <stdlib.h>
#include <math.h>
#include <matrix.h>
#include "ow_homography.h"
...
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
...
compute_homography_matrix(Ksharp, &theta_list[k*3], invKblurry, H);
...
}
The problem is in the function compute_homography_matrix that is in another file ow_homography.h
#ifndef OW_HOMOGRAPHY_H
#define OW_HOMOGRAPHY_H
#include "ow_mat3.h"
INLINE void compute_homography_matrix(const double *Ksharp, const double *theta, const double *invKblurry, double *H) {
double R[9];
/* Compute homography */
cp3(invKblurry,H);
rot3(theta[0],theta[1],theta[2],R);
mmip3(R,H);
mmip3(Ksharp,H);
}
This last operations (cp3, rot3...) are in another file ow_mat3.h that contains all the operations for the program.
So when i try to call
mex apply_blur_kernel_mex.c
i have the following problem:
Error using mex
Undefined symbols for architecture x86_64:
"_compute_homography_matrix", referenced from:
mexFunction in apply_blur_kernel_mex.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Any suggestions to solve this problem?
Thank you all.
http://clang.llvm.org/compatibility.html#inline
C compatibility C99 inline functions
By default, Clang builds C code in GNU C11 mode, so it uses standard
C99 semantics for the inline keyword. These semantics are different
from those in GNU C89 mode, which is the default mode in versions of
GCC prior to 5.0. For example, consider the following code:
inline int add(int i, int j) { return i + j; }
int main() { int i = add(4, 5); return i; }
In C99, inline means that a function's definition is provided only for
inlining, and that there is another definition (without inline)
somewhere else in the program. That means that this program is
incomplete, because if add isn't inlined (for example, when compiling
without optimization), then main will have an unresolved reference to
that other definition. Therefore we'll get a (correct) link-time error
like this:
Undefined symbols: "_add", referenced from:
_main in cc-y1jXIr.o
By contrast, GNU C89 mode (used by default in older versions of GCC)
is the C89 standard plus a lot of extensions. C89 doesn't have an
inline keyword, but GCC recognizes it as an extension and just treats
it as a hint to the optimizer.
There are several ways to fix this problem:
1) Change add to a static inline function. This is usually the right solution if only one translation unit needs to use the function.
static inline functions are always resolved within the translation
unit, so you won't have to add a non-inline definition of the function
elsewhere in your program.
2) Remove the inline keyword from this definition of add. The inline keyword is not required for a function to be inlined, nor does it
guarantee that it will be. Some compilers ignore it completely. Clang
treats it as a mild suggestion from the programmer.
3) Provide an external (non-inline) definition of add somewhere else in your program. The two definitions must be equivalent!
4)Compile in the GNU C89 dialect by adding -std=gnu89 to the set of Clang options. This option is only recommended if the program source
cannot be changed or if the program also relies on additional
C89-specific behavior that cannot be changed.
All of this only applies to C code; the meaning of inline in C++ is
very different from its meaning in either GNU89 or C99.
It is challenging to port from Linux to OS/X. I have an inline function embedded inside another function body. On Linux, gcc happily compiled the code, but on OS/X, clang reports error.
Here is the code snippet,
$ cat inline.c
void func() {
inline int max(int a, int b) { return (a>b) ? a : b; }
int c = max(11,22);
}
On Linux, everything is fine,
Linux $ gcc -c inline.c
Linux $$ gcc --version
gcc (Ubuntu 5.2.1-22ubuntu2) 5.2.1 20151010
However, clang on OS/X complains,
OSX $ cc -c inline.c
inline.c:2:38: error: function definition is not allowed here
inline int max(int a, int b) { return (a>b) ? a : b; }
^
inline.c:3:17: warning: implicit declaration of function 'max' is invalid in C99
[-Wimplicit-function-declaration]
int c = max(11,22);
^
1 warning and 1 error generated.
OSX $ cc --version
Apple LLVM version 7.3.0 (clang-703.0.31)
Target: x86_64-apple-darwin15.5.0
Is this a gcc "feature" or there is a clang flag to enable this capability?
GCC extensions not implemented yet
clang does not support nested functions; this is a complex feature which is infrequently used, so it is unlikely to be implemented anytime soon.
Just move the max out the function and make it static.
Here, "inline" means "inline substitution", rather than "inline definition".
According to N1570:
6 A function declared with an inline function specifier is an inline
function. Making a function an inline function suggests that calls to
the function be as fast as possible.138) The extent to
which such suggestions are effective is
implementation-defined.139)
138) By using, for example, an alternative to the usual function
call mechanism, such as ''inline substitution''. ...
And you shouldn't define another function in a function definition. Also, use static inline instead of inline would make your life easier.
Anyone knows why this c program compiles and uses the sqrt of math.h?
this would output 2.236068
main.c
#include <stdio.h>
#include "math_utils.h"
int main(void){
printf("%f\n", sqrt(5));
return 0;
}
math_utils.h
#ifndef MATH_UTILS_Hs
#define MATH_UTILS_Hs
double sqrt(double number){
return number + 5;
}
#endif // MATH_UTILS_Hs
I am currently using mingw GCC on windows
gcc performs an optimization where it expects standard library functions to behave like the standard says to turn calls into the C standard library into more efficient machine code. For example, it's likely that gcc emits a single fsqrt instruction for your sqrt() call, never calling your custom sqrt() at all.
You can turn off this behaviour by supplying -fno-builtin to turn this optimization off for all recognized functions or by supplying -fno-builtin-function to turn off this optimization for function only. For example, -fno-builtin-sqrt would make gcc honour your non-standard sqrt().