I was recently browsing for some examples to revisit C and came across a code where OP declared a variable as:
float Get_TMP007_Data();
What do the parenthesis in the variable name imply since this is not an array declaration?
That's not a variable, that's a function prototype. A common requirement (depending on the structure of your code/files) in gcc is to have them.
They're basically just the function header of a function you have written something else, something used for the pre-processor to determine what functions are being used/written. What you have there is a function called Get_TMP007_Data() that returns a float
float Get_TMP007_Data(); is a function declaration.
It is a declare Get_TMP007_Data as function returning float.
As a declaration of a function, there is no information as to what paremters should be passed. It could be used as
float f1 = Get_TMP007_Data();
float f2 = Get_TMP007_Data(42);
A better function declaration would list the parameters to be passed - perhaps even none as in:
float Get_TMP007_Data(void);
Related
Is it necessary to declare function before using it? Does the compiler give an error if we don't use a function declaration and call it directly. Please answer according to standard C.
If yes then what does it mean that argument of type are converted to int and float to double if arguments to function are not defined?
In ANSI C, you do not have to declare a function prototype; however, it is a best practice to use them. The only reason the standard allows you to not use them is for backward compatibility with very old code.
If you do not have a prototype, and you call a function, the compiler will infer a prototype from the parameters you pass to the function. If you declare the function later in the same compilation unit, you'll get a compile error if the function's signature is different from what the compiler guessed.
Worse, if the function is in another compilation unit, there's no way to get a compilation error, since without a a prototype there's no way to check. In that case, if the compiler gets it wrong, you could get undefined behavior if the function call pushes different types on the stack than the function expects.
Convention is to always declare a prototype in a header file that has the same name as the source file containing the function.
With prototypes, the compiler can verify you are calling the function correctly (using the right number and type of parameters).
Without prototypes, it's possible to have this:
// file1.c
void doit(double d)
{
....
}
int sum(int a, int b, int c)
{
return a + b + c;
}
and this:
// file2.c
// In C, this is just a declaration and not a prototype
void doit();
int sum();
int main(int argc, char *argv[])
{
char idea[] = "use prototypes!";
// without the prototype, the compiler will pass a char *
// to a function that expects a double
doit(idea);
// and here without a prototype the compiler allows you to
// call a function that is expecting three argument with just
// one argument (in the calling function, args b and c will be
// random junk)
return sum(argc);
}
In C, you need to define everything before you use it. I think the idea is that it can compile everything in one pass, since it always has all of the information it needs by the time it gets to it.
I'm not sure what you're asking with the second part. If the function isn't defined, it just won't work.
The short answer: in C89/90 it is not necessary, in C99 it is necessary.
In C89/90 the function does not have to be declared in order to be called. For undeclared function the compiler will make an assumption about function return type (assumes int) and about function parameter types (will derive them from the argument types at the point of the call).
In C99 the function has to be previously declared in order to be called. Note, that even in C99 there's no requirement to provide a prototype for the function, only a declaration is needed, i.e. a non-prototype declaration is OK. This means that the compiler no longer has to make any assumptions about the function return type (since the declaration always specifies it explicitly), but it still might have to make assumptions about the function parameters (if the declaration is not a prototype).
The C99 standard in 6.5.2.2 "Function call" describes what happens in a function call expression, including if no prototype has been seen by the compiler for the function:
If the expression that denotes the called function has a type that does not include a prototype, the integer promotions are performed on each argument, and arguments that have type float are promoted to double. These are called the default argument
Later, it describes what happens if the function call expression doesn't match what how the function is actually defined:
If the function is defined with a type that is not compatible with the type (of the expression) pointed to by the expression that denotes the called function, the behavior is undefined.
Clearly, to help ensure correctness, using function prototypes is the right thing to do. Enough such that C++ made requiring function prototypes one of the 'breaking' changes with c.
The Problem
I'm writing the following code, which, as excerpted below, should return the total amount of money depending on the number of each type of coin.
static int qNum = 0;
static int dNum = 0;
static int nNum = 0;
static int pNum = 0;
int main(){
float totalCost;
totalCost = totalMoneyCalc();
}
float totalMoneyCalc(void){
float total;
total = qNum*.25 + dNum*.10 + nNum*.05 + pNum*.01;
return total;
}
The Errors I'm Getting
note: previous implicit declaration of ‘totalMoneyCalc’ was here
totalCost = totalMoneyCalc();
error: conflicting types for ‘totalMoneyCalc’
float totalMoneyCalc(){
However, when I remove the "float" part of the totalMoneyCalc() function, it doesn't return any more errors. Aren't you supposed to assign functions types?
What I've Tried
I looked at this question on SO, which says something about having to pass in void as a param for functions that don't take in anything but adding that to the original code didn't work either.
I also checked out some primers on using floats for functions in C, but I followed those and it's still not working.
Am I supposed to be doing something with pointers? I don't understand why returning a value in a function to be assigned to a variable is different from ints to floats. If anyone has suggestions, fixes, or explanations, I'd really appreciate it.
Yes, all C functions have types. Prior to the 1999 standard, it was legal to omit the return type from a declaration; that would implicitly give it a return type of int. As of C99, the return type must always be specified explicitly.
Also prior to C99, it was legal to call a function with no visible declaration. The compiler would assume a function with a return type of int (that's the "previous implicit declaration" referred to in the error message). C99 dropped that rule; now all functions must be visibly declared before you can call them.
Assuming you're using gcc (that looks like a gcc error message), the compiler enforces the C90 rules by default. The problem it's reporting is that the implicit declaration of totalMoneyCalc (as a function returning int) conflicts with the later explicit declaration as a function returning float.
The solution is to declare totalMoneyCalc before the call. You can either add a separate "forward" declaration before main:
float totalMoneyCalc(void);
or you can move the entire definition above main. (This is a good idea even in C90.)
A minor point: int main() should be int main(void).
The compiler needs to know about the function before you use it. If the function is unknown to the compiler then it will not be able to know whether the function returns double or float or if it's first parameter is a pointer or a struct, so it will by default think of them all as int's.
You can to add a function prototype before main()
float totalMoneyCalc(void);
or move the entire function definition before main().
Receiving error: conflicting types for ‘six’ when attempting to compile.
void main(){
const int k = 4;
six(&k);
}
float * six(const int *x)
{
float *p = malloc(sizeof(float));
*p = (float)*x;
return p;
}
Here is what is going on.
When the compiler does not encounter a prototype for a function before a call to it, it deduces the prototype from the call itself, and assumes the return type to be int. This is what it does in your example.
Later it finds the definition of the function, and it finds that the return type is actually float, which does not match with the prototype it has deduced earlier. Hence the error of conflicting types (instead of, say, missing prototype).
The solution is to, of course, provide a prototype for the function before a call to it is made.
You didn't declare six to the compiler before you called it, so the compiler was forced to guess what the signature of six is (typically, this is something like int func()). When it saw the actual declaration, it threw an error because the actual function declaration didn't match its implicit declaration.
You need to declare functions before they are used; place a declaration like
float *six(const int *x);
before main.
Solution to your problem
Just add the following declaration before main():
float *six(const int *x);
Or put your float *six(const int *x) definition before the main() function.
Why the compiler complain conflicting types
Since there is no declaration of your six() function before the compiler compile the main function, it will deduce the prototype from the function callsite, and will assume the return type to be int. And when it compiles your six() function, the compiler will find two function with the same name but different return type, so it complain the conflicting types error.
Thanks to Ziffusion's comment.
why to adjust your code in the above way
You should declare/define each of your element before use in C.
For your currently code, you need to declare your function type before the main function, so that the compiler knows what six() is when compile the main function.
Why there should be a declaration before use in C
For variables and other data types, since C is strong typed. When the variable is used, it need to be declared first, so that the compiler knows what type the variable is, and could do data type check.
For functions, since the C compiler compiles the code function by function, and will generate a function call statement in the assembly, so the compiler need to know the function parameter and return value data type, so that it could generated correct instructions to do parameter passing, and return value restoring. Normally, the compiler will compile the function in a source code file one by one from the start of the file to the end of the file, so you need to declare the function type before use it.
first time posting here
I'm currently porting some code for an embedded device. Basically getting everything to work with a new compiler (AVR-GCC) from an out-of-date existing proprietary compiler
I've come across this strange looking (to me anyway!) variable in a struct. I can't work out what it is with the parentheses. It is in a struct which is used for raw values:
float (*tc)( float value );
My IDE highlights 'value' as a compiler keyword, just like 'float' so I don't know if this is AVR-GCC specific?
This is then used in a function which has a float argument called 'reading' and it tries to return the following:
return (raw[rCN3].tc)( reading );
The line above actually causes the program to attempt to access out of bounds memory.
I haven't seen code like this before so was wondering if anyone could help me decipher it? It worked with the old compiler but is causing a problem with AVR-GCC
Thanks in advance. Alex
This is a function pointer. It points to a function that returns a float value and that has a float parameter.
Two things:
1) float (*tc)( float value ) is a function pointer to a function taking a float as a parameter, returning a float
2) 'value' is a keyword in C# and may also be in other languages; hence its highlighting. Check your editor language settings.
That is a function pointer variable.
tc is a pointer to a function, which takes a single float as argument and returns a `float.
The reason it accesses out of bounds memory is probably because rCN3 is out of bounds for the array raw.
That is a function pointer.
It means that tc holds the address of a function accepting a single float argument, and returning a float value.
For instance, you could set it to the standard library's sinf function, like so:
somestruct.tc = sinf;
somestruct.tc(3.14159265f / 2); /* This will return roughly 1.0f. */
Also, the ever-useful cdecl says:
declare tc as pointer to function (float) returning float
How does the following code work even though the signature of the function in the declaration doesn't match with the definition? The function declaration has empty parameter list, yet the definition has one parameter. Why the compiler doesn't give error?
#include <stdio.h>
double f(); //function declaration
int main(void)
{
printf("%f\n", f(100.0));
}
double f(double param) //function definition
{
return 5 * param ;
}
It compiles and runs fine (ideone).
But if I change the type of the parameter in the definition, from double to float, it gives the following error (ideone):
prog.c:7: error: conflicting types for ‘f’
prog.c:8: note: an argument type that has a default promotion can’t match an empty parameter name list declaration
prog.c:2: error: previous declaration of ‘f’ was here
What is wrong with float? Why does it give error with float but not with double?
Here is the list of pairs of declaration and definition, along with which pair works, and which not:
Works (ideone)
double f(); //declaration
double f(double param); //definition
Does not work (ideone)
double f(); //declaration
double f(float param); //definition
Works (ideone)
float f(); //declaration
float f(double param); //definition
Does not work (ideone)
float f(); //declaration
float f(float param); //definition
So as it seems, whenever the parameter-type is float, it doesn't work!
So I've basically two questions:
Why does the first example work even though there is a mismatch in the declaration and the definition?
Why does it not work when the parameter-type is float?
I tried understanding the section §6.5.2.2 (C99), but the language is so cryptic that I couldn't clearly understand. I don't even know if I read the correct section. So please explain these behaviors in simple words.
Your assumption that declaration does not match the definition is incorrect. (That would be the case in C++, but not in C). In C language the
double f();
declaration does not fully declare the function, i.e. it does not introduce the prototype. It only announces the fact that function f exists and that its return type is double. It says absolutely nothing about the number and the types of fs arguments. The arguments can be absolutely anything. In that sense the declaration in your example does match the definition (i.e. it doesn't contradict the definition, which is good enought for C compiler).
If you really wanted the declare a function that takes no arguments, you'd have to specify an explicit void in the parameter list
double f(void);
That would indeed contradict the definition. What you have originally does not.
When you call a function that has been declared with empty parameter list (), it is your responsibility to supply the proper number of arguments of proper type. If you make a mistake, the behavior is undefined. This is what the compiler warns you about when you change the actual parameter type to float.
Your analysis of "pairs" of declaration and definition is not entirely correct. It is misguided. It is not really about the declaration and definition. It is really about the definition and the way you call your function. In the original case you call it with a double argument and the function is declared with a double parameter. So everything is matching. But when you call it with a double argument and declare it with a float parameter, you get a mismatch.
Also note, that when a function is declared without a prototype, float arguments are always promoted to double arguments. For this reason, it is not possible to pass a float argument to a function declared with () parameter list. If you want to have float arguments, always use prototypes (the same applies to char and short arguments as well).
C allows the function declaration to be empty. From C99 6.7.5.3/14:
The empty list in a
function declarator that is not part
of a definition of that function
specifies that no information about
the number or types of the parameters
is supplied.
This is distinct from a void parameter list, which is explicitly stating that the function has no arguments. From 6.7.5.3/10:
The special case of an unnamed
parameter of type void as the only
item in the list specifies that the
function has no parameters.
Note also that if the types aren't declared, then your declaration is not a prototype. From 6.2.1/2:
A function prototype is a declaration
of a function that declares the types
of its parameters.
The second question is indeed related to C99 6.5.2.2/6:
If the expression that denotes the
called function has a type that does
not include a prototype, the integer
promotions are performed on each
argument, and arguments that have type
float are promoted to double.
So in your case, float gets promoted to double whenever the function is called, and a double is put on the call stack (or in eax or whatever). But of course, if your function definition takes a float, it would read a float off the call stack, which would lead to a binary incompatibility. The compiler knows this, hence the error message.
In C, an empty parameter list in the declaration means the function can be called with 0 or more arguments.
Such functions, when called with a floating-point number, implicitly take it as a double. (And integral parameters as int.)
So when you call foo(100.0), you are calling it with a double. If you try to call it with a float, the argument will be converted to double at the time of the call.
This will not work if you define the function to take a float, because the way doubles and floats are passed is different. Hence the compiler is helpfully giving you an error.
Be glad you made this mistake in 2011 and not 1985, because compilers used to be pretty stupid and this was a nightmarish kind of bug to track down.
Bottom line: It is very bad style to declare functions with empty parameter lists in modern C. Declare the function properly, and if it to be referenced by multiple translation units, put the declaration in a header file.
[edit]
As detly points out in a comment, if you actually want to declare a function to take zero arguments, declare it to take void. (Or switch to C++...)
In C, an empty function declaration is like using ... in C++. That is it matches any number and type of arguments. The problem with using a float instead of a double is that float automatically promotes to double. When calling f(...) (to borrow C++ notation), it doesn't know what type is expected, so it gets promoted to double. Later, when you redeclare f to take a float argument, that conflicts with the implicit declaration of f as f(double).