1

I'm new to C, just a question on strlen. I know that it is defined in <string.h>. But if I don't include <string.h> as:

#include <stdio.h>

int main()
{
     char greeting[6] = { 'z', 'e', 'l', 'l', 'o', '\0' };
     printf("message size: %d\n", strlen(greeting));
    return 0;
}

it still works and prints 5, I did receive a warning which says warning: incompatible implicit declaration of built-in function ‘strlen’ but how come it still compile? and who provides strlen()?

  • 1
    As a side point, you can replace the string declaration with `char greeting[] = "zello";`. The behavior is the same. – Daniel Walker Jun 08 '20 at 03:23
  • Note that you might run into problems on a big-endian machine. The function returns a `size_t` which would be 8 bytes long; without the declaration, the compiler probably assumes that the result is an `int` (and the `%d` format expects an `int`), and the result for a big-endian machine would probably be 0 for any string under 4 GiB — the value printed would effectively be divided by 2^32. – Jonathan Leffler Jun 08 '20 at 17:56
  • See also [Are prototypes required for all functions in C89, C90 or C99?](https://stackoverflow.com/a/437763/15168) and [Why `#include ` is not required to use `printf()`?](https://stackoverflow.com/a/341974/15168). – Jonathan Leffler Jun 08 '20 at 18:03

2 Answers2

3

There are several things going on here.

As of the 1990 version of C, it was legal to call a function without a visible declaration. Your call strlen(greeting) would cause the compiler to assume that it's declared as

int strlen(char*);

Since the return type is actually size_t and not int, the call has undefined behavior. Since strlen is a standard library function, the compiler knows how it should be declared and warns you that the implicit warning created by the call doesn't match.

As of the 1999 version of the language, a call to a function with no visible declaration is invalid (the "implicit int" rule was dropped). The language requires a diagnostic -- if you've told the compiler to conform to C99 or later. Many C compilers are more lax by default, and will let you get away with some invalid constructs.

If you compiled with options to conform to the current standard, you would most likely get a more meaningful diagnostic -- even a fatal error if that's what you want (which is a good idea). If you're using gcc or something reasonable compatible with it, try

gcc -std=c11 -pedantic-errors ...

Of course the best solution is to add the required #include <string.h> -- and be aware that you can't always rely on your C compiler to tell you everything that's wrong with your code.

Some more problems with your code:

int main() should be int main(void) though this is unlikely to be a real problem.

Since strlen returns a result of type size_t, use %zu, not %d, to print it. (The %zu format was introduced in C99. In the unlikely event that you're using an implementation that doesn't support it, you can cast the result to a known type.)

Keith Thompson
  • 254,901
  • 44
  • 429
  • 631
0

The C standard library is linked automatically. That's what gives you access to the strlen function.

Including the header file helps the compiler out by telling it what kind of function strlen is. That is, it tells it what kind of value it returns and what kind of parameters it takes.

That's why your compiler is warning you. It's saying, "You're calling this function but I haven't been told what kind of function it is." Often a compiler will make a guess. You're passing in a char[] so the compiler figures the function must take a char* as an argument. As for the return type, the compiler makes the guess that the return value is an int.

Daniel Walker
  • 6,380
  • 5
  • 22
  • 45
  • thanks for your answer. So you mean the compiler will try to find a function in C standard library whose name matches 'strlen '? –  Jun 08 '20 at 03:34
  • 1
    Exactly. You can instruct your compiler **not** to link the standard library. If you did that, you would see a linker error. – Daniel Walker Jun 08 '20 at 03:35
  • 1
    This isn't a linker error, it's a compiler error. The compiler knows how `strlen` is supposed to be declared because it's a standard library function. – Keith Thompson Jun 08 '20 at 03:54
  • 1
    @DanielWalker It is **not the compiler** who does the linking to the standard library, it is **the linker**. Please correct your answer. – the busybee Jun 08 '20 at 06:22
  • 2
    The compiler does not “guess” what kind of function it is. In this situation (allowing function calls per pre-1999 rules), there is an implicit declaration of the function as returning `int` and having no prototype for the arguments. And the compiler does not “figure” the function must take a `char *`. It applies the default argument promotions. – Eric Postpischil Jun 08 '20 at 13:43
  • @thebusybee, I know. I meant it in a loose sense in that typically the user invokes the compiler which then kicks off the rest of the process (i.e., assembling, linking). – Daniel Walker Jun 11 '20 at 15:57