My project has the following 4 files: main.c, rcm.h, rcm.c and queue.c.
In rcm.h I'm declaring all functions implemented in rcm.c and queue.c.
rcm.c looks like:
#include "rcm.h"
void rcm (void) {
Queue *Q = init(10);
/* Some other stuff */
}
queue.c` looks like:
#include "rcm.h"
extern inline Queue* init(int n) {
return malloc(sizeof(Queue*);
}
and rcm.h:
#ifndef __RCM__
#define __RCM__
typedef struct queue { /*...*/ } Queue;
void rcm( void );
inline Queue* init( int n );
#endif
When compiling I get the the warnings
gcc-7 -O0 -c rcm.c -o rcm.o
In file included from rcm.c:15:0:
rcm.h:58:15: warning: inline function 'init' declared but never defined
inline Queue* init(int size);
^~~~
gcc-7 -c queue.c -o queue.o
gcc-7 main.c lib/rcm.o queue.o -o main
In file included from main.c:4:0:
inc/rcm.h:58:15: warning: inline function 'init' declared but never defined
inline Queue* init(int size);
^~~~
But, when I am not declaring init() as inline compiles normally.
inline Queue* init( int n );
In order for a compiler to be able to inline a function, it must know he code of a function. Without that knowledge, the compiler must emit a call to that function1. Hence the warning. In order to use an inline function in several modules, you can define it in the header as:
static inline Queue* init (int n)
{
/* code here */
}
Cf. for example the GCC documentation for inline.
The reason for the warning is that you want the function to be inline, but you are hiding the code from the compiler: main.c includes the header that declares an inline function but in that compilation unit, init is defined (implemented) nowhere.
1 Except for functions built-in the compiler. In that case, you don't have to provide the code yourself, it compiler has build-in knowledge about it.
Related
when I try to compile C code that includes another C header I get this error:
x86_64-uefi/../../libk/string.h:9:10: error: function declared 'ms_abi' here was
previously declared without calling convention
KABI int memcmp(const void *d1, const void *d2, uint64_t len);
^
x86_64-uefi/../../libk/string.h:9:10: note: previous declaration is here
The compiler is clang and the involved files are the following:
memcmp.c
#include "../string.h"
KABI int memcmp(const void *d1, const void *d2, uint64_t len) {
const uint8_t *d1_ = d1, *d2_ = d2;
for(uint64_t i = 0; i < len; i += 1, d1_++, d2_++){
if(*d1_ != *d2_) return *d1_ < *d2_ ? -1 : 1;
}
return 0;
}
string.h
#pragma once
#include "systemapi.h"
#include "typedefs.h"
KABI int memcmp(const void *d1, const void *d2, uint64_t len);
systemapi.h (typedefs just define the uintx_t types)
#pragma once
#define KABI __attribute__((ms_abi))
Another header that includes string.h, libk.h
#pragma once
#include "string.h"
#include "systemapi.h"
#include "typedefs.h"
And the file that includes lib.h and that reports the error when compiling, main.c (but all files report the error when linking with lib.h)
KABI void arch_main(void)
{
// The function does not uses memcmp, just uses the KABI part of lib.h
// Calling the whole lib.h is a convention
}
Flags of the compiler: -I/usr/include/efi -I/usr/include/efi/x86_64 -I/usr/include/efi/protocol -fno-stack-protector -fpic -fshort-wchar -mno-red-zone -DHAVE_USE_MS_ABI -c main.c -o main.o
Without having your build environment, an educated guess would be that you are redefining the built in functions that have prototypes that are incompatible with the ms_abi function attribute. If you are compiling with -ffreestanding and supplying your own functions like memcpy, memset, etc., you should consider compiling with -fno-builtin option so that CLANG/GCC doesn't use its built in forms of the functions that may conflict with your own.
How do I make a C function visible for functions only in other certains .c files?
Let's suppose I have a foo1 function wich calls other foo2 function (in differents .c files) and I want to call foo1 from my main function, but I want foo2 to be invisible for any function other than foo1, like this:
/**
foo1.c
*/
void foo1()
{
if (condition_is_true){
foo2();
}
}
/**
foo2.c
*/
#include <stdio.h>
void foo2()
{
printf("Hello world!\n");
}
/**
main.c
*/
void foo1(void);
void foo2(void);
int main()
{
foo1();
foo2(); /*unresolved external*/
}
And when compiling
$ cc -omain main.c foo1.c foo2.c
I want the linker to complain "undefined reference to `foo2'".
Usually, if you want to make a function in one .c source code file visible in another .c source file, you place the definition of that function into a .h file and include it into the .c file you want it visible in. For example:
file foo1.c
int somefunc1(some parameters)
{
Do some stuff.
}
file foo1.h
int somefunc1(some parameters);
file foo2.c
#include "foo1.h"
int foo2(Some parameters)
{
Do some stuff.
foo1(asdfasdf)
Do some more stuff.
}
That is generally what you do. However, what you are asking for is the exact opposite. I'm not sure why you want an undefined reference when the linker runs, but the way that you have set your compile, those files will get passed to the linker. So the only thing that you can do is not have foo2.c on the file list. If you are using something from one of the main libraries, it still gets linked in even if you don't specify the include file. For instance:
$$$ ->more test3.c
int main(void)
{
printf("hello world\n");
return(0);
}
$$$ ->clang -std=c11 -Wall -Wextra -o test3 test3.c
test3.c:8:5: warning: implicitly declaring library function 'printf' with type 'int (const char *, ...)'
printf("hello world\n");
^
test3.c:8:5: note: please include the header <stdio.h> or explicitly provide a declaration for 'printf'
1 warning generated.
So what you are asking for I don't really think can or should be done.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
In a C program, where do you define a function?
Why?
I suppose that the function definition is generally written outside the main function and after the function declaration. It's correct? Why?
Thank you all!
You have to define a function outside main(), because main() is a function itself and nested functions are not supported in C.
Declaring a function is in modern C not necessary, because a function definition implies a function declaration. There are still two reasons to do it:
A function declaration can be exported in a header file and then used by other translation units that import the header file.
C is usually translated one-pass that means that you cannot use a function before it is declared without warning. If you have a function a() calling a function b()and vice versa, you cannot define both functions before declaring at least one.
The only real requirement is that a function be declared before it is first called in a statement, and that it be defined somewhere before everything is linked together (either in another source file that gets translated, or in a previously translated object file or library).
If your program is small and you have everything in a single source file, my recommended practice is to define the function before it is used, like so:
void foo( void )
{
// body of foo
}
void bar( void )
{
...
foo();
...
}
int main( void )
{
...
bar();
...
}
The function definition also serves as a declaration (specifying the return type as well as the number and types of parameters to the function). You could put the definitions after main, but you will still need to declare them before they're called:
int main( void )
{
void bar( void );
...
bar();
...
}
void bar( void )
{
void foo( void );
...
foo();
...
}
void foo ( void )
{
// body of foo
}
You don't have to declare foo within the body of bar, or bar within the body of main; you could declare them both before `main:
void foo( void );
void bar( void );
int main( void )
{
...
bar();
...
}
void bar( void )
{
...
foo();
...
}
The only problem with this style is that if you change the return type of the function or change any of the parameters, you have to chase down any declarations and change them as well. The first way (defining before use) reads "backwards", but it's less of a maintenance headache.
If your program is divided up among multiple source files, the usual practice is to create a separate header file for each source file, and #include that header in any other source file that uses those functions, like so:
/**
* foo.h - Header file for function foo
*/
#ifndef FOO_H // Include guards; prevents the file from being processed
#define FOO_H // more than once within the same translation unit
void foo( void ); // declaration of foo
#endif
/**
* foo.c - Source file for function foo
*/
#include "foo.h"
...
void foo( void ) // definition of foo
{
// body of foo
}
/**
* bar.h - Header file for bar.h
*/
#ifndef BAR_H
#define BAR_H
void bar( void ); // declaration of bar
#endif
/**
* bar.c - Source file for bar.h
*/
#include "foo.h" // necessary because bar calls foo
void bar( void )
{
...
foo();
}
/**
* main.c - Source file for main
*/
#include "bar.h" // necessary because main includes bar
int main( void )
{
...
bar();
}
Note that the header files only contain the declarations of foo and bar, not their actual code. In order for this to work, both foo.c and bar.c must be compiled along with main.c, and the resulting object files must all be linked together. You could do them all at once, like:
gcc -o blah main.c foo.c bar.c
Or you could compile each separately and link the object files together:
gcc -c foo.c
gcc -c bar.c
gcc -c main.c
gcc -o blan main.o foo.o bar.o
Or you could build a library out of foo.c and bar.c and link against that (useful if you want to use foo and bar in other programs):
gcc -c foo.c
gcc -c bar.c
ar cr libblurga.a foo.o bar.o
gcc -o blah main.c -lblurga
Standard C does not support nested functions (that is, defining a function within the body of another function). Some implementations such as gcc support nested functions as an extension, but it's not the usual practice.
Good question. Languages in the Pascal family usually do have the concept of scoped functions, like any other declaration/definition.
I think the answer lies in the origins of C as, heaven forgive me, a better macro assembler of sorts (with a standard library). Functions are mere jump addresses with a little stack magic for parameter and return value handling; function "scope" is just too abstract a concept in that world.
That said, a similar effect can be achieved by grouping "helper functions" together with a globally visible function which needs them in the same file; the helper functions would be declared static and could then only be used in that source file. The net effect is quite similar to scoped functions.
Private declaration goes on top of your .c file:
static int your_function();
Private declaration can be emitted if it is defined above where you are attempting to call it, although for maintainability it's always better to declare your private interface, just like your public, in one place.
Public declaration in your .h file:
extern int your_function();
Keyword 'extern' in header files is always implicitly added to your function declaration, although I tend to attach it explicitly for clarity.
Function definition works for both private and public declarations:
int your_function() {
return 5;
}
Or for private only:
static int your_function() {
return 5;
}
If you mark extern function definition as static, GCC will fail with the following:
error: static declaration of ‘your_function’ follows non-static declaration
When compiler builds your code, it pretty much replaces all your #include statements with the content of the file you are including and the parsing goes from top to bottom as one large file. Once you understand that, most of these things simply start to make sense.
I am implementing an implementation of queues in C. My interface consists of five simple function to access the queue:
#ifndef QUEUE_H
#define QUEUE_H
#include <stdbool.h>
#include <stddef.h>
struct queue {
struct cell* first;
struct cell* last;
};
typedef struct queue queue;
extern queue newQueue(void);
extern bool isEmpty(queue);
extern queue enqueue(queue,void*);
extern queue dequeue(queue);
extern void* front(queue);
extern void freeQueue(queue);
Since two of them (newQueue and isEmpty) are so trivial that I believe that a compiler can do many good optimizations with them, I decided to write inline declarations for them:
/* replacing the two lines
extern queue newQueue(void);
extern bool isEmpty(queue);
in the original header */
extern inline queue newQueue(void) {
queue q = { NULL, NULL };
return q;
}
extern inline bool isEmpty(queue q) {
return q.first == NULL;
}
This compile fine with gcc. But when I compile it with clang, it gives me an error. A quick research shows, that the official way of doing these inline declarations is different from the GNU style. I could either pass -std=gnu89 or change the function signatures according to the link above. I chosed the second option:
inline queue newQueue(void) {
queue q = { NULL, NULL };
return q;
}
inline bool isEmpty(queue q) {
return q.first == NULL;
}
But now, both clang and gcc say something about duplicate function declarations, when compiled in c99 mode. This is the accompanying definition in queue.c:
#include "queue.h"
/* ... */
queue newQueue() {
queue q = { NULL, NULL };
return q;
}
bool isEmpty(queue q) {
return q.first == NULL;
}
What am I doing wrong? How can I get what I want without needing to switch into gnu89 mode?
These are the error messages I get with the second style:
$ gcc -std=c99 queue.c
queue.c:12:7: error: redefinition of ‘newQueue’
queue.h:14:21: note: previous definition of ‘newQueue’ was here
queue.c:17:6: error: redefinition of ‘isEmpty’
queue.h:19:20: note: previous definition of ‘isEmpty’ was here
$ clang -std=c99 queue.c
queue.c:12:7: error: redefinition of 'newQueue'
queue newQueue() {
^
In file included from queue.c:5:
./queue.h:14:21: note: previous definition is here
extern inline queue newQueue(void) {
^
queue.c:17:6: error: redefinition of 'isEmpty'
bool isEmpty(queue q) {
^
In file included from queue.c:5:
./queue.h:19:20: note: previous definition is here
extern inline bool isEmpty(queue q) {
^
2 errors generated.
If you are defining functions in headers make them static. This should be enough for compiler to inline them (inline is just an additional hint).
Non static functions in headers will result in multiple definitions, if you include that header more than one time in your whole program.
I have done some research and have more info:
You can use inline that way. At least in C99. You just cannot have both inline and non-inline definitions in queue.c. You need wrap inline definitions in #ifdef or move them to header not included in queue.c.
You need to write the functions twice and play with the preprocessor, but it should work exactly as you want. When function is not inlined, it will be emitted only once.
You should not be declaring them in queue.c
The proper way of doing this in c99 and onward is to merely have an external declaration of an inline function in the .c file instead of a definition of it. This will force standalone code to be created for that function so that it will link properly if inlining is not possible for some reason. See: http://www.greenend.org.uk/rjk/tech/inline.html
Since functions default to extern this is sufficient:
queue.c
#include "queue.h"
/* ... */
queue newQueue();
bool isEmpty(queue q);
I'm writing a library in C99, and there are some parts of the library that would benefit significantly from the use of a macro / inline function. Inline functions are a better fit for my library.
However, very specifically I do not want to externally expose these inline functions.
Everything appears to work, but when I link against the library to create an executable I get the error: "undefined reference to `na_impl_gfx__draw'"
I have reproduced the problem to a minimal test case which does exactly what I do:
lib.h:
void somefunc();
lib.c:
#include <stdio.h>
#include "lib.h"
inline void someinline(char *value);
void somefunc() {
someinline("Hi!");
}
inline void someinline(char *value) {
printf("%s\n", value);
}
main.c:
#include "lib.h"
int main(int argc, char *argv[]) {
somefunc();
}
Now we compile:
doug#Wulf:~/test$ gcc -c -std=c99 lib.c
doug#Wulf:~/test$ gcc -c -std=c99 main.c
doug#Wulf:~/test$ gcc -std=c99 lib.o main.o
lib.o: In function `somefunc':
lib.c:(.text+0xe): undefined reference to `someinline'
lib.c:(.text+0x1a): undefined reference to `someinline'
lib.c:(.text+0x26): undefined reference to `someinline'
collect2: ld returned 1 exit status
It would appear that when compiling the library, the inline function is not being substituted into the object code for the function somefunc() in lib.h
Why?
The inline function is not externally visible. I would expect that when the library is compiled, the inline function is inlined into the function, just like the macro is (Nb. using only a macro this code compiles file).
What am I doing wrong? Or is this a restriction of inline functions?
The reason that you can't see the inline function in the same source file is that you haven't made them static.
All you need to do is make the prototype static with:
inline static void someinline(char *value);
and the function definition static with:
inline static void someinline(char *value) {
printf("%s\n", value);
}
[Sorry for kicking in as lately, you should have tagged your question with C and not only C99.]
I think with your question you are completely on the wrong track. Inline functions only make sense when you put them in a ".h" file. The whole concept is about making the function definition visible to all callers.
If you'd do so you should just put the definition (with the inline) in the header and an external declaration (with extern inline) in one compilation unit.
If you just want to have functions put in place in your "lib.o" compilation unit, forget about all that inline or static and let the compiler do that for you. gcc does that if you switch on optimization:
`-finline-small-functions'
Integrate functions into their callers when their body is smaller
than expected function call code (so overall size of program gets
smaller). The compiler heuristically decides which functions
are
simple enough to be worth integrating in this way.
Enabled at level `-O2'.