2

I've an strage behaviour in a simple C code that I'm doing for educational purposes.

If I compile it with something lower than -O2 it breaks during link-edition with this output.

$ make
clang -Wall -march=native -pipe -c -g -D_DEBUG_ main.c
clang -Wall -march=native -pipe -c -g -D_DEBUG_ functions.c
clang -Wall -o main main.o functions.o 
Undefined symbols for architecture x86_64:
  "_getbit", referenced from:
      _getValueFromMatrix in functions.o
  "_setbit", referenced from:
      _populateMatrix in functions.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make: *** [main] Error 1

I don't know if this helps but, here are the implementation of setbit(); and getbit();

inline void setbit(uint64_t *inteiro, unsigned char pos) {
    *(uint64_t*)inteiro |= (uint64_t)1 << pos;
}

inline bool getbit(uint64_t inteiro, unsigned char pos) {
    return (inteiro & ((uint64_t)1 << pos));
}

EDIT:

functions.h

#ifndef __FUNCTIONS_H__
#define __FUNCTIONS_H__

/* Funções para manipulação de bits */

inline void setbit(uint64_t *, unsigned char);

inline void clearbit(uint64_t *, unsigned char);

inline bool getbit(uint64_t, unsigned char);

inline unsigned char getbitChar(uint64_t, unsigned char);

char *uint64_t2bin(uint64_t, char *, int);

#endif

Includes in main.c

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include <string.h>

#include "errors.h"
#include "const.h"
#include "types.h"
#include "functions.h"
  • setbit and getbit are defined in main.c or functions.c ? Or in one of the header files included by functions.c ? – Charlie Burns Sep 22 '13 at 02:05
  • Yep, they are in functions.h: inline void setbit(uint64_t *, unsigned char); inline bool getbit(uint64_t, unsigned char); – Vinícius Ferrão Sep 22 '13 at 02:35
  • And where are the implementations of these functions defined? I think for anyone to give you a definitive answer you'd need to show all the code. But it seems like the compiler is not seeing the definitions of setbit and getbit. Maybe they are not in the files you gave the compiler, maybe they are hidden by some #ifdefs, but the compiler is not seeing the definitions of setbit an getbit. – Charlie Burns Sep 22 '13 at 02:54
  • I will edit the first post... If you need something more let me know! – Vinícius Ferrão Sep 22 '13 at 02:57
  • 1
    We need all the code. Again, where are setbit and getbit defined? – Charlie Burns Sep 22 '13 at 03:12
  • see also http://stackoverflow.com/questions/10243018/inline-function-undefined-symbols-error – Christoph Sep 22 '13 at 09:34

2 Answers2

1

inline only is the right thing to use, if there is a definition of the function in the .h file. It basically tells the compiler that it shouldn't produce a code for the function in every compilation unit (your .c files).

If there is no such definition in the .h file, as it seems here, just don't use inline at all, it just makes no sense.

If your worry is the efficiency of the other functions in the unit where you define your inline functions, you really don't need that. The compiler will inline any function that it has its hands on and where its criteria say that it is worth to do so.

If you really want to put the definitions to appear in the header file such that all units can see the definition, then use inline. In that case you'd have to include an "instantiation" of your function in just one unit, to ensure that the code is issued exactly once:

extern inline void setbit(uint64_t *, unsigned char);
extern inline void clearbit(uint64_t *, unsigned char);
extern inline bool getbit(uint64_t, unsigned char);
extern inline unsigned char getbitChar(uint64_t, unsigned char);
Jens Gustedt
  • 76,821
  • 6
  • 102
  • 177
  • Thanks! I've declared all those functions as extern inline in my functions.c file and function.h file. Now it compiles successfully. Just in case: what is the difference between extern inline and static inline? – Vinícius Ferrão Sep 22 '13 at 13:52
  • @ViníciusFerrão, that is not good. Don't declare them `extern inline` in your `.h` file: `inline` in the `.h` file, `extern inline` in the `.c`. With `static inline` you could have a distinct copy of the function generated in every compilation unit. Perhaps have a look at http://gustedt.wordpress.com/2010/11/29/myth-and-reality-about-inline-in-c99/ – Jens Gustedt Sep 22 '13 at 14:36
0

The inline functions don't have any external definition, so when the compiler fails to inline them (which it won't do at -O0), the linker fails to find a definition, and an error results. The easiest fix is to change inline to static inline. Non-static inline is hard to use, confusing, and usually not useful.

R.. GitHub STOP HELPING ICE
  • 208,859
  • 35
  • 376
  • 711
  • I disagree. `inline` is the right thing to use, if there is a definition in the `.h` file. If there is no such code in the .h file, as it seems here, just don't use `inline` at all, it just makes no sense. – Jens Gustedt Sep 22 '13 at 07:08
  • In OP's case, there is code in the header file. If you use `inline` without `static`, you must arrange for there to be some translation unit that declares the function with `extern` so that a definition will be emitted. Unfortunately there are historic compilers that handle this horribly wrong (aka "GNU inline"), making it a major hassle to deal with. Using `static inline` ensures that you never have to deal with this. The code will be inlined once per use, and/or emitted once per translation unit that uses it, at the compiler's discretion. – R.. GitHub STOP HELPING ICE Sep 22 '13 at 17:05