92

I'm using the below code:

char dest[5];
char src[5] = "test";

printf("String: %s\n", do_something(dest, src));

char *do_something(char *dest, const char *src)
{
    return dest;
}

The implementation of do_something is not important here. When I try to compile the above I get these two exception:

error: conflicting types for 'do_something' (at the printf call)
error: previous implicit declaration of 'do_something' was here (at the prototype line)

Why?

fat
  • 6,435
  • 5
  • 44
  • 70
goe
  • 5,207
  • 14
  • 45
  • 49
  • 4
    I was getting this same error but I wasn't calling the function anywhere yet (neither before nor after its definition) so the selected answer wasn't applicable in my case. Turns out the problem was a naming conflict- my function's name was "mergesort" (I'm following along with Skiena's "Algorithm Design Manual") and there's already an identically-named function in stdlib.h. Renaming my function as "merge_sort" did the trick. – Richie Thomas Jul 22 '18 at 19:05

11 Answers11

156

You are trying to call do_something before you declare it. You need to add a function prototype before your printf line:

char* do_something(char*, const char*);

Or you need to move the function definition above the printf line. You can't use a function before it is declared.

James McNellis
  • 348,265
  • 75
  • 913
  • 977
27

In "classic" C language (C89/90) when you call an undeclared function, C assumes that it returns an int and also attempts to derive the types of its parameters from the types of the actual arguments (no, it doesn't assume that it has no parameters, as someone suggested before).

In your specific example the compiler would look at do_something(dest, src) call and implicitly derive a declaration for do_something. The latter would look as follows

int do_something(char *, char *)

However, later in the code you explicitly declare do_something as

char *do_something(char *, const char *)

As you can see, these declarations are different from each other. This is what the compiler doesn't like.

AnT stands with Russia
  • 312,472
  • 42
  • 525
  • 765
  • Are there some cases where you can legally call an undeclared function? What is the reasoning behind a "conflicting types" error for this problem rather than a "function not declared before called" error? – intcreator Feb 09 '16 at 18:20
  • 3
    @brandaemon: The original C language (C89/90) did not have "function not declared before called" error. It was perfectly legal to call undeclared functions in C. Instead of issuing an error the language was required to analyze the call and "deduce" the *implicit* declaration for the function. That's how the language was originally designed. So, yes in C89/90 you could legally call an undeclared function, as long as the "deduced" function declaration was *compatible* with the actual one. – AnT stands with Russia Feb 09 '16 at 18:27
  • 3
    @brandaemon: C99 prohibited calling undeclared functions. Meaning that starting with C99, there's "function not declared before called" error in C. However, even in C99 (and later) it is possible to declare a function without a prototype. I.e. it is enough to do `int foo()` to make function `foo` officially *declared*. In C (as opposed to C++) `()` in function declaration still means that function parameter list is *unspecified* and has to be "deduced" by the compiler exactly as described above. I.e. C compilers no longer deduce function return types, but parameter lists can still be deduced. – AnT stands with Russia Feb 09 '16 at 18:30
  • Ok, I think I understand. So was this specific compiler error left intentionally to refer to types or could it have been reworded (and possibly has been in some compilers? I've just seen it this way on gcc) for special cases when the problem lies with function declarations? I'm mostly trying to see how to interpret this particular error better as at least in this case it doesn't seem very intuitive. – intcreator Feb 09 '16 at 18:39
  • 1
    @brandaemon: The compiler error in the original post actually refers to *function types*. It says that the *deduced* function type is `int (char *, char *)` while the *actual* function type is `char *(char *, const char *)`. However, the general rule that's violated in this case applies to all kinds of declarations (not only "deduced" ones, not only function declarations). For example, you can declare `extern double a;` and then define `int a;` and you will get the same error about conflicting types. And, apparently, GCC authors did not think that functions deserve being treated separately. – AnT stands with Russia Feb 09 '16 at 18:55
21

A C Function-Declaration Backgrounder

In C, function declarations don't work like they do in other languages: The C compiler itself doesn't search backward and forward in the file to find the function's declaration from the place you call it, and it doesn't scan the file multiple times to figure out the relationships either: The compiler only scans forward in the file exactly once, from top to bottom. Connecting function calls to function declarations is part of the linker's job, and is only done after the file is compiled down to raw assembly instructions.

This means that as the compiler scans forward through the file, the very first time the compiler encounters the name of a function, one of two things have to be the case: It either is seeing the function declaration itself, in which case the compiler knows exactly what the function is and what types it takes as arguments and what types it returns — or it's a call to the function, and the compiler has to guess how the function will eventually be declared.

(There's a third option, where the name is used in a function prototype, but we'll ignore that for now, since if you're seeing this problem in the first place, you're probably not using prototypes.)

History Lesson

In the earliest days of C, the fact that the compiler had to guess types wasn't really an issue: All of the types were more-or-less the same — pretty much everything was either an int or a pointer, and they were the same size. (In fact, in B, the language that preceded C, there were no types at all; everything was just an int or pointer and its type was determined solely by how you used it!) So the compiler could safely guess the behavior of any function just based on the number of parameters that were passed: If you passed two parameters, the compiler would push two things onto the call stack, and presumably the callee would have two arguments declared, and that would all line up. If you passed only one parameter but the function expected two, it would still sort-of work, and the second argument would just be ignored/garbage. If you passed three parameters and the function expected two, it would also still sort-of work, and the third parameter would be ignored and stomped on by the function's local variables. (Some old C code still expects these mismatched-argument rules will work, too.)

But having the compiler let you pass anything to anything isn't really a good way to design a programming language. It worked well in the early days because the early C programmers were mostly wizards, and they knew not to pass the wrong type to functions, and even if they did get the types wrong, there were always tools like lint that could do deeper double-checking of your C code and warn you about such things.

Fast-forward to today, and we're not quite in the same boat. C has grown up, and a lot of people are programming in it who aren't wizards, and to accommodate them (and to accommodate everyone else who regularly used lint anyway), the compilers have taken on many of the abilities that were previously part of lint — especially the part where they check your code to ensure it's type-safe. Early C compilers would let you write int foo = "hello"; and it would just blithely assign the pointer to the integer, and it was up to you to make sure you weren't doing anything stupid. Modern C compilers complain loudly when you get your types wrong, and that's a good thing.

Type Conflicts

So what's all this got to do with the mysterious conflicting-type error on the line of the function declaration? As I said above, C compilers still have to either know or guess what a name means the first time they see that name as they scan forward through the file: They can know what it means it if it's an actual function declaration itself (or a function "prototype," more on that shortly), but if it's just a call to the function, they have to guess. And, sadly, the guess is often wrong.

When the compiler saw your call to do_something(), it looked at how it was invoked, and it concluded that do_something() would eventually be declared like this:

int do_something(char arg1[], char arg2[])
{
    ...
}

Why did it conclude that? Because that's how you called it! (Some C compilers may conclude that it was int do_something(int arg1, int arg2), or simply int do_something(...), both of which are even farther from what you want, but the important point is that regardless of how the compiler guesses the types, it guesses them differently from what your actual function uses.)

Later on, as the compiler scans forward in the file, it sees your actual declaration of char *do_something(char *, char *). That function declaration isn't even close to the declaration that the compiler guessed, which means that the line where the compiler compiled the call was compiled wrong, and the program is just not going to work. So it rightly prints an error telling you that your code isn't going to work as written.

You might be wondering, "Why does it assume I'm returning an int?" Well, it assumes that type because there's no information to the contrary: printf() can take in any type in its variable arguments, so without a better answer, int is as good a guess as any. (Many early C compilers always assumed int for every unspecified type, and assumed you meant ... for the arguments for every function declared f() — not void — which is why many modern code standards recommend always putting void in for the arguments if there really aren't supposed to be any.)

The Fix

There are two common fixes for the function-declaration error.

The first solution, which is recommended by many other answers here, is to put a prototype in the source code above the place where the function is first called. A prototype looks just like the function's declaration, but it has a semicolon where the body should be:

char *do_something(char *dest, const char *src);

By putting the prototype first, the compiler then knows what the function will eventually look like, so it doesn't have to guess. By convention, programmers often put prototypes at the top of the file, just under the #include statements, to ensure that they'll always be defined before any potential usages of them.

The other solution, which also shows up in some real-world code, is to simply reorder your functions so that the function declarations are always before anything that calls them! You could move the entire char *do_something(char *dest, const char *src) { ... } function above the first call to it, and the compiler then would know exactly what the function looks like and wouldn't have to guess.

In practice, most people use function prototypes, because you can also take function prototypes and move them into header (.h) files so that code in other .c files can call those functions. But either solution works, and many codebases use both.

C99 and C11

It is useful to note that the rules are slightly different in the newer versions of the C standard. In the earlier versions (C89 and K&R), the compiler really would guess the types at function-call time (and K&R-era compilers often wouldn't even warn you if they were wrong). C99 and C11 both require that the function declaration/prototype must precede the first call, and it's an error if it doesn't. But many modern C compilers — mainly for backward compatibility with earlier code — will only warn about a missing prototype and not consider it an error.

Sean Werkema
  • 5,810
  • 2
  • 38
  • 42
9

You didn't declare it before you used it.

You need something like

char *do_something(char *, const char *);

before the printf.

Example:

#include <stdio.h>
char *do_something(char *, const char *);
char dest[5];
char src[5] = "test";
int main ()
{
printf("String: %s\n", do_something(dest, src));
 return 0;
}

char *do_something(char *dest, const char *src)
{
return dest;
}

Alternatively, you can put the whole do_something function before the printf.

6

You have to declare the function before you use it. If the function name appears before its declaration, C compiler will follow certain rules and makes the declaration itself. If it is wrong, you will get that error.

You have two options: (1) define it before you use it, or (2) use forward declaration without implementation. For example:

char *do_something(char *dest, const char *src);

Note the semicolon at the end.

Viliam
  • 4,404
  • 3
  • 28
  • 30
4

C Commandment #3:

K&R #3 Thou shalt always prototype your functions or else the C compiler will extract vengence. 

http://www.ee.ryerson.ca:8080/~elf/hack/God.vs.K+R.html

brtc
  • 51
  • 1
4

Watch again:

char dest[5];
char src[5] = "test";

printf("String: %s\n", do_something(dest, src));

Focus on this line:

printf("String: %s\n", do_something(dest, src));

You can clearly see that the do_something function is not declared!

If you look a little further,

printf("String: %s\n", do_something(dest, src));

char *do_something(char *dest, const char *src)
{
return dest;
}

you will see that you declare the function after you use it.

You will need to modify this part with this code:

char *do_something(char *dest, const char *src)
{
return dest;
}

printf("String: %s\n", do_something(dest, src));

Cheers ;)

EKons
  • 887
  • 2
  • 20
  • 27
  • You mentioned "you will see that you declare the function after you use it." which is a bit confusing. it should be like this "you will see that you define the function after you called it." – shashank arora Apr 22 '21 at 11:04
3

When you don't give a prototype for the function before using it, C assumes that it takes any number of parameters and returns an int. So when you first try to use do_something, that's the type of function the compiler is looking for. Doing this should produce a warning about an "implicit function declaration".

So in your case, when you actually do declare the function later on, C doesn't allow function overloading, so it gets pissy because to it you've declared two functions with different prototypes but with the same name.

Short answer: declare the function before trying to use it.

mrduclaw
  • 3,965
  • 4
  • 36
  • 37
  • 3
    No, it assumes it takes any number of parameters and returns an int. In C, there's a big difference between `int foo()` (takes any number of parameters) and `int foo(void)` (takes no parameters). – Adam Rosenfield Oct 11 '09 at 02:36
1

This often happens when you modify a c function definition and forget to update the corresponding header definition.

  • I had something similiar happen. I was writing bindings for openCL against the Khronos cl.h header file. I was copying and pasting from the online documentation to create typedefs for function prototypes/signatures. Turns out the documentation for clGetContextInfo for openCL 1.0 is incorrect. The last parameter was supposed to be "size_t*" but was "size_t". – KANJICODER Mar 24 '19 at 20:04
0

Make sure that types in the function declaration are declared first.

/* start of the header file */
.
.
.
struct intr_frame{...}; //must be first!
.
.
.
void kill (struct intr_frame *);
.
.
.
/* end of the header file */

Dávid Natingga
  • 839
  • 3
  • 13
  • 30
-1

#include <arpa/inet.h>

for objective-c Conflicting types for 'inet_ntoa'

Ferer Atlus
  • 256
  • 2
  • 6