Why do conflicting types for functions occur in C?

I am using the code below:

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 above, I get these two exceptions:

error: conflicting types for 'do_something' (when calling printf)
Error: The previous implicit declaration of 'do_something' was here (in the prototype line)

Why?

+49
c arrays
Oct 11 '09 at 1:57
source share
10 answers

You are trying to call do_something before declaring 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 cannot use a function until it is declared.

+90
Oct 11 '09 at 2:01
source share

In the “classical” C language (C89 / 90), when calling an undeclared function, C assumes that it returns int , and also tries to get the types of its parameters from the types of the actual arguments (no, it does not assume that it has no parameters, as suggested earlier).

In your specific example, the compiler will look at the call to do_something(dest, src) and implicitly output the declaration for do_something . The latter would be 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 ads are different from each other. This is what the compiler does not like.

+16
Oct 11 '09 at 2:33
source share

You did not declare it before using it.

You need something like

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

before printing.

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 entire do_something function before printf.

+6
Oct 11 '09 at 2:00
source share

You must declare a function before using it. If the function name appears before the declaration, the C compiler will follow certain rules and make the declaration itself. If this is not the case, you will get this error.

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

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

Note the semicolon at the end.

+6
Oct 11 '09 at 2:02
source share

C Memorization No. 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

+3
Oct 11 '09 at 10:46
source share

See 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 are declaring the function after that you are using.

You will need to change this part using this code:

 char *do_something(char *dest, const char *src) { return dest; } printf("String: %s\n", do_something(dest, src)); 

Greetings;)

+3
Aug 08 '15 at 11:00
source share

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

So, in your case, when you actually declare the function later, C does not allow function overloading, so it becomes pissy because you declared two functions with different prototypes, but with the same name.

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

+2
Oct 11 '09 at 2:05
source share

A C-declaration of functions

In C, function declarations do not work like in other languages: the C compiler itself does not search back and forth in the file to find the function declaration from the place you call it, and it does not scan the file several times to find out the relationship: 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 job and only runs after the file has been compiled before the original build instructions.

This means that as the compiler looks ahead the file, the first time the compiler encounters a function name, there should be one of two things: it either sees the function declaration itself, in which case the compiler knows exactly what the function is and what it takes types as arguments, and what types it returns - or it is a function call, and the compiler must guess how the function will be declared.

(There is a third option where the name is used in the function prototype, but this time we will ignore it, because if you see this problem in the first place, you probably are not using prototypes.)

History lesson

In the earliest days of C, the fact that the compiler had to guess the types was not really a problem: all types were more or less the same - almost 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 a pointer, and its type was determined solely by how you used it!) Thus, the compiler could safely assume the behavior of any function, based only on the number of parameters passed: if you passed two parameters, the compiler would move two things to the call stack, and presumably the caller would have two arguments declared, and that would all align. If you passed only one parameter, but the function expected two, this will still work, and the second argument will just be ignored / garbage. If you pass three parameters and the function expected by two, it will also sort the work, and the third parameter will be ignored and replaced with local variables of the function. (Some old C code still expects these rules for inappropriate arguments to work as well.)

But having a compiler allows you to pass something on to something; this is not a very good way to program a programming language. It worked well in the early days because the early C programmers were mostly wizards, and they knew that they didn't pass the wrong type to functions, and even if they were really wrong, there were always tools like lint that could double check deeper your C code and a warning about such things.

Go quickly to today, and we're not all in the same boat. C has grown, and there are many programmers who are not wizards, and to accommodate them (and to accommodate everyone who regularly used lint ) in any case, the compilers took over many of the capabilities that were previously part of lint - especially part, where they check your code to ensure it's safe type. Early C compilers would let you write int foo = "hello"; , and it just blithely assigns a pointer to an integer, and it's up to you not to do anything stupid. Modern C compilers complain out loud when you're wrong, which is good.

Type Conflicts

So, what is all this connected with a mysterious conflict error in the function declaration line? As I said above, C compilers should either know or assume that the name means that the first time they see this name when scanning forward through the file: they can know what this means if it is the declaration of the function itself ( or the "prototype" function "is more about this briefly), but if it is just a function call, they should guess. And, unfortunately, the assumption is often erroneous.

When the compiler saw your call to do_something() , he looked at how it was called, and he concluded that do_something() would eventually be declared as follows:

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

Why did he do this? Because, as you called it! (Some C compilers may conclude that it was int do_something(int arg1, int arg2) or just int do_something(...) , both of which are still far from what you want, but the important thing is that no matter as the compiler guesses types, he guesses about them differently what your actual function uses.)

Later, when the compiler scans ahead in the file, it sees your actual char *do_something(char *, char *) declaration. The declaration of this function is not even close to the declaration that the compiler suggested, which means that the line in which the compiler compiled the call was compiled incorrectly, and the program simply does not work. Therefore, it correctly displays an error message indicating that your code will not work as it is written.

You might be wondering: "Why am I assuming I am returning an int ?" Well, he assumes this type, because there is no information to the contrary: printf() can accept any types in its variable arguments, so without a better answer, int will guess as well as any other. (Many early C compilers always assumed an int for every undefined type, and suggested that you had in mind ... for arguments for each function declared, f() is not void - which is why many modern code standards recommend always putting void in for arguments, if they really shouldn't be.)

Correction

There are two common errors for function declaration errors.

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

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

Having set the prototype first, the compiler will then find out what this function will look like, therefore it does not need to be guessed. By convention, programmers often place prototypes at the top of the file, simply under the #include statements, to ensure that they are always defined before their potential use.

Another solution that also appears in some kind of real code is to simply reorder your functions so that the function declarations are always before what they call! You can move the entire function char *do_something(char *dest, const char *src) { ... } above the first call to it, and then the compiler knows exactly what the function looks like, and there was no need to guess.

In practice, most people use function prototypes because you can also use function prototypes and move them to header files ( .h ) so that code in other .c files can call these functions. But any 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 earlier versions (C89 and K & R), the compiler really guessed the types when the function was called (and the K & R compilers often didn’t even warn you if they were wrong ) C99 and C11 require that the function declaration / prototype must precede the first call, and this is an error if it is not. But many modern C compilers - mainly for backward compatibility with earlier code - will only warn about a missing prototype and not consider it a mistake.

+1
Apr 6 '17 at 16:20
source share

Be sure to declare the types in the function declaration first.



/* start of the header file */
.
.
.

struct intr_frame{...}; //must be first!
.
.
.

void kill (struct intr_frame *);
.
.
.

/* end of the header file */

0
Mar 22 '12 at 15:37
source share

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

0
Jul 07 '16 at 21:59
source share



All Articles