2

Working in a new to me code base and I have come across some C code that looks like this:

static int* functionA(int* anInt);
#define functionA(anInt) ( <a 1 line '? :' function>)

Maybe this is obvious to people who’s C coding is a bit more fresh in their head than mine, but it looks a little odd to me. The compiler seems to agree as it spits out a message stating

error: ‘functionA’ declared ‘static’ but never defined.

(I am using gcc 4.8.2.)

As this is has turned up in some library code that we are evaluating I assume that for some compilers, some of the time, this is valid. Please could someone help explain when it is valid?

My best guess is this some old fashioned way of doing inline static function definitions. However there is every chance I am missing something subtle. An explanation of what is being achieved would also be helpful but really I want to know when this code is valid.

TafT
  • 2,764
  • 6
  • 33
  • 51
  • The `#define` thing is a pre-processor macro definition, not a function definition. The pre-processor will then replace all instances of `functionA` (all instances found after the macro definition) with the "body" of the macro. A function definition would be e.g. `static int* functionA(int* anInt) { ... }` – Some programmer dude Apr 30 '15 at 10:48
  • https://ideone.com/hDFhbJ shows that gcc has no trouble compiling code with an undefined function which was declared before. You must have an instance where `functionA` *is* being called throug some mechanism, or something else. Provide a minimal complete example... – Peter - Reinstate Monica Apr 30 '15 at 11:10
  • Further down in the same .c file there is: int * aValue = functionA(aVariable); Though I do not see why this could not be: int * aValue = (); provided by the macro. – TafT Apr 30 '15 at 11:26

3 Answers3

2

Your compiler is right, you declared a static function

static int* functionA(int* anInt);

but there is no definition for it, you then added a macro, that will replace every occurrence of functionA(value); in your code with (<a 1 line '? :' function>), hence you can't use the static function anymore even if it had a definition.

A function definition would be

static int *functionA(int* anInt)
{
    /* do something with `aInt' */
}

while using the macro, the preprocessor will take this code

#define addnumbers(x, y) ((x) + (y))

double x = addnumbers(1.5, 6.7);

with

double x = ((1.5) + (6.7));
Iharob Al Asimi
  • 52,653
  • 6
  • 59
  • 97
  • So you are saying that the code in this library will have never compiled? – TafT Apr 30 '15 at 10:52
  • No I didn't say that, it would compile, because you never use the `static` function anyway so at the linking phase there is no need for it. – Iharob Al Asimi Apr 30 '15 at 10:53
  • Well, does that mean that gcc issues an error where other compilers wouldn't? – Peter - Reinstate Monica Apr 30 '15 at 10:57
  • So perhaps things would be happy if we didn't treat warnings as errors. I can see that a declared but undefined function should be warned of. Your explanation matches what I had expected, which is somewhat reassuring. Thank you. – TafT Apr 30 '15 at 10:59
  • @TafT You should absolutely treat this as an error. That macro stinks, replace it with a real function if possible. – Lundin Apr 30 '15 at 11:38
  • @Lundin you are very right, warnings should be treated as errors because if they are warnings then something is not 100% right about it, and in this case I see absolutely no need for the macro either, since if the content is very simple, the function might be inlined anyway. – Iharob Al Asimi Apr 30 '15 at 12:25
  • @Lundin As it comes from 3rd party code, I cannot change it. I can file a bug note with them but nothing more. (OK I can change it in our copy, but you know what I mean.) – TafT May 05 '15 at 10:27
2

As this is has turned up in some library code that we are evaluating I assume that for some compilers, some of the time, this is valid. Please could someone help explain when it is valid?

If there is no actual definition of functionA in the source file where it is declared it is also not used, the compiler should issue "declared ‘static’ but never defined" as a warning.

However, if you are using the -Werror option the compiler would issue all warnings as errors... check if you are using that option.

https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html

traveh
  • 2,700
  • 3
  • 27
  • 44
  • 1
    I am using that option. That explains why it is coming out as an error and possibly why the authors of the library code left it as it was. – TafT Apr 30 '15 at 11:10
  • Well then, that answers "when it was valid" :) – traveh Apr 30 '15 at 13:59
  • 1
    You are technically correct. When not using the -Werror option it will not be an error. That is as valid as this code was ever likley to be by the sound of things. – TafT May 05 '15 at 10:29
0

The #define does not define a function, it replaces apparent function calls in the code with an inlined expression. (The expression is ill-formed though unless I miss something; perhaps it is only a placeholder?) The only time the actual compiler sees functionA is in the static declaration; it complains that the function is never defined.

That compiler error comes unexpected to me -- I'd have assumed that the static declaration is ignored if the function is never called. (It is never called because the #define causes those "calls" to be replaced.) One should probably simply #define the static declaration away using an #if/#else construction if the "inlining by #define" is in effect.

By the way, with modern compilers and common optimization levels this should be unnecessary; the compiler would inline the function for you.

Peter - Reinstate Monica
  • 15,048
  • 4
  • 37
  • 62
  • It looks like the only use of 'fucntionA' in the code base is later on in the same .c file. It is only used in a normal way though, no attempt is made to take the address of the function. – TafT Apr 30 '15 at 10:56