Rein Halbersma wrote:You can put function definitions in headers if you prefix them with the inline keyword.
Indeed you can. (More about 'inline' later.) But it seems that this would have the side effect of automatically inlining the code, which might not always be what you want. (Although for strcpy might be a good idea.)
However, when I run a gcc -E (but not on an Apple machine, of course) to see what the #include <string.h> expands to, the only occurrence of strcpy in the output is:
Code: Select all
char *__attribute__((__cdecl__)) strcpy (char *, const char *);
Doesn't seem to actually define the semantics, nor contain an inline directive. And indeed, the following program
Code: Select all
#include <string.h>
char *strcpy (char *a, const char *b)
{
static char buf[] = "fooled!";
char *p = buf;
while((*a++ = *p++));
return NULL;
}
int main()
{
char a[0], b[10];
strcpy(a, "Hello");
strcpy(b, a);
printf("%s\n", b);
return 0;
}
causes no errors or warnings on the re-definition of strcpy:
Code: Select all
Makro@Makro-PC ~
$ gcc -Wall test.c
test.c: In function `main':
test.c:17: let op: implicit declaration of function `printf'
Makro@Makro-PC ~
$ ./a.exe
fooled!
Makro@Makro-PC ~
$
If the Apple string.h would define strcpy as an inlined routine, it should generate error messages for conflicting declarations, however. Does the C standard allow such different behavior between compilers? Perhaps using a routine named strcpy in itself is specified as 'undefined behavior'?
Now about Apple and inlining. We received a bug report from someone trying to compile XBoard with an Apple compiler. Now the XBoard PGN parser defines two inlined routines:
Code: Select all
inline int
Match (char *pattern, char **ptr)
{
char *p = pattern, *s = *ptr;
while(*p && (*p == *s++ || s[-1] == '\r' && *p--)) p++;
if(*p == 0) {
*ptr = s;
return 1;
}
return 0; // no match, no ptr update
}
inline int
Word (char *pattern, char **p)
{
if(Match(pattern, p)) return 1;
if(*pattern >= 'a' && *pattern <= 'z' && *pattern - **p == 'a' - 'A') { // capitalized
(*p)++;
if(Match(pattern + 1, p)) return 1;
(*p)--;
}
return 0;
}
Of course these routines are only called from parser.c, where they are defined. But XBoard refuses to build, because of linker errors. In particular complaints that parser.c makes function calls to undefined symbols _Match and _Word (or something like that. I would have to look up the actual bug report). I am not sure what exactly causes this problem, so I haven't made any attempt to fix it, so far.