3

I tried to using two different functions from sting.h header file (without including it) strlen() and strtok(). Strlen executed successfully without any error (but some warnings), strtok failed at runtime. Why is it that strlen() function worknig gine but not strtok() if I don't include the header file? I suppose there is something in the linking process that I don't understand. Please clarify for such behavior. However, the program terminates successfully if I print a as '%c' instead of '%s' (strtok returns a garbage value).

CODE:

int main()
{
    char string[] = "This is a String";
    printf("\nLength of sting is %d\n",strlen(string));
}

WARNINGS: hello.c: In function ‘main’: hello.c:4:2: warning: incompatible implicit declaration of built-in function ‘printf’ [enabled by default] hello.c:4:37: warning: incompatible implicit declaration of built-in function ‘strlen’ [enabled by default] hello.c:4:2: warning: format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘long unsigned int’ [-Wformat]

OUTPUT: $ ./a.out

Length of sting is 16

CODE:

int main()
{
    char string[] = "This is a String";
    printf("\nLength of sting is %d\n",strlen(string));
    char *a = strtok(string," ");
    printf("%s",a);
}

WARNINGS: $ gcc hello.c hello.c: In function ‘main’: hello.c:4:2: warning: incompatible implicit declaration of built-in function ‘printf’ [enabled by default] hello.c:4:37: warning: incompatible implicit declaration of built-in function ‘strlen’ [enabled by default] hello.c:4:2: warning: format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘long unsigned int’ [-Wformat] hello.c:5:12: warning: initialization makes pointer from integer without a cast [enabled by default]

OUTPUT: $ ./a.out

Length of sting is 16
Segmentation fault (core dumped)
2
  • If you can execute your program then the linking process was successful. Commented Mar 30, 2017 at 5:17
  • If that that's true then there is something in the implementation of the strtok() function that I don't understand. It returns a garbage character if string.h is not included, where as strlen() works fine. However, if I include the header file strtok() also works as expected. Commented Mar 30, 2017 at 5:24

2 Answers 2

5

The linking is done implicitly for most of the C standard library. You just have to include the headers of what you use (that's the warnings).

When you don't, your compiler (which is compiling your code as ANSI C) assumes the functions return int, instead of their documented return types. Your program has undefined behavior because of that. Always heed warnings!
You must include the headers string.h and stdio.h.

The first program works because you were lucky enough in that strlen is supposed to return an integer (a size_t to be exact, but it appears on your system the value representation for integers and size_t lets the program slide through).

The second fails because strtok returns a char* but it's assumed an int due to your missing include directives. int and char* are not compatible types, so the "pointer" you get isn't valid.

Sign up to request clarification or add additional context in comments.

3 Comments

Clear as a crystal! Thanks!
Just out of curiosity can we safely use functions returning int without including header files , even with warnings.
@PratyushRaizada - Not if you want your code to compile as modern C (C99 or C2011 standards). The implicit int rule is abolished, a missing prototype is a hard error. It's also a good policy in general to have completely warning free build. Compilers issue warnings to help you.
3

Sting is a singer, not a C header... Still, the problem is that in C, when you use functions that were not declared, the compiler guesses them to have the types of the arguments you first pass to them and returning an int.

That's the reason why you get all these warnings: several undeclared functions you use don't actually have the deduced signature (although they are not too wrong, and end up working), and the real strtok returns a pointer, not an int (the warning in facts says that you are assigning an int to a pointer without a cast). The crash you are getting most probably comes from the fact that the original pointer is 64 bit, but is truncated to 32 bit when is erroneously considered an int before being assigned to a.

Still, the point to take home is: include headers and don't ever rely on implicit function declaration. It's a dangerous mess that exists only for backward compatibility reasons.

2 Comments

It makes one wonder why the compiler chooses to throw a warning for "implicit function declaration" rather than an error??
@Jay - One that's compiling the code as C90, where it was valid, albeit discouraged. From C99 onward the implicit int rule was abolished.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.