Default argument type for function without prototype?

classic Classic list List threaded Threaded
4 messages Options
Reply | Threaded
Open this post in threaded view
|

Default argument type for function without prototype?

Richard Smith via cfe-dev
Hi, 

I am a beginner to C and I previously asked this question on SO (and it was marked as duplicate :-) ) I still do not understand the problem to the end. I understand the need of function prototypes and the default argument promotion machinery. But I am still confused with the obtained warning and final result for this example:

#include <stdio.h>

void impl();

int main(void){

impl(3.0);

return 0; 

}

void impl(val){

printf("%.2f", val);

}

I get the following warning: format specifies type 'double' but the argument has type 'int' [-Wformat].I can not understand why it is supposed by a compiler that val should be treated as int and not to skip the number and types of arguments and then perform default argument promotion at run time. Also I read that if you don't provide argument types in ANSI C:
An ANSI C compiler will assume that you have decided to forego function prototyping, and it will not check arguments.

The result which is printed to the console is 0.00, but as I understood the caller should place double on the stack and %f also means double in printf so it reads double off the stack, and the result should not be affected. 

So I'm still confused what is happening here. Also I can't find where it is stated that the argument without a type should be treated by a compiler as type intI understand that the question is stupid in nature, for this I apologize in advance, but it somehow sat down in my head and I nowhere can I find why it happens. Thank you!

p.s.: Compiled with clang 6.0 and --std=c89 flag under Windows 10. Apologies if this question is off-topic for this list, but i can't find any other.

With kind regards,

-gdg


_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|

Re: Default argument type for function without prototype?

Richard Smith via cfe-dev
Hi Kirill,

On Sat, Jan 20, 2018 at 11:21 AM, Kirill Balunov via cfe-dev
<[hidden email]> wrote:
> Hi,
>
> I am a beginner to C and I previously asked this question on SO (and it was
> marked as duplicate :-) ) I still do not understand the problem to the end.

What is your question that is related to the development of the clang compiler?

> I understand the need of function prototypes and the default argument
> promotion machinery. But I am still confused with the obtained warning and
> final result for this example:
>
> #include <stdio.h>
>
> void impl();
>
> int main(void){
>
> impl(3.0);
>
> return 0;
>
> }
>
> void impl(val){
>
> printf("%.2f", val);
>
> }
>
> I get the following warning: format specifies type 'double' but the argument
> has type 'int' [-Wformat].I can not understand why it is supposed by a
> compiler that val should be treated as int

Because the C standard says so. Read this StackOverflow answer:
https://stackoverflow.com/a/13950800

especially the part that says:  "If no variable type is in front of a
variable in the parameter list, then int is assumed"

When the compiler compiles the "impl" function, it has to assign a
type to the variable "val". The standard says this type has to be
"int". The compiler can't take into account that in main() you're
passing a double to "impl".

> and not to skip the number and
> types of arguments and then perform default argument promotion at run time.
> Also I read that if you don't provide argument types in ANSI C:
>>
>> An ANSI C compiler will assume that you have decided to forego function
>> prototyping, and it will not check arguments.
>
> The result which is printed to the console is 0.00, but as I understood the
> caller should place double on the stack and %f also means double in printf
> so it reads double off the stack, and the result should not be affected.


You wrote "void impl();". This told the compiler not to check the type
of arguments passed to the "impl" function.

Later you wrote "impl(3.0)". The compiler dutifully passed the double
value to the impl function: it loaded the value into the xmm0
register, because the x86-64 calling convention passes the first few
arguments in registers.
(line 7 in https://godbolt.org/g/puW5b1)

Later you wrote "void impl(var)" and called printf. The compiler
passed the string "%.2f" to the printf function as the first argument
(lines 19 and 22), then it passed the integer it received in the rdi
register as the second argument to printf (lines 20 and 21). It also
passed the number of floating point arguments in vector registers
passed to printf  in the al register (zero, line 23).

impl expected an int argument in the rdi register. Unfortunately,
because you called impl with a double, the value of rdi contained
garbage. This got passed to printf. I have no idea what printf did
when instructed to print a double (with "%f") and then it was told
that no floating-point values were given to it.

>
> So I'm still confused what is happening here. Also I can't find where it is
> stated that the argument without a type should be treated by a compiler as
> type int.

See the StackOverflow answer.

> I understand that the question is stupid in nature, for this I
> apologize in advance, but it somehow sat down in my head and I nowhere can I
> find why it happens. Thank you!
>
> p.s.: Compiled with clang 6.0 and --std=c89 flag under Windows 10. Apologies
> if this question is off-topic for this list, but i can't find any other.

I don't understand this. A google search for "mailing list" returns
almost eight million results. You could have sent your question to any
of them.

Csaba
--
GCS a+ e++ d- C++ ULS$ L+$ !E- W++ P+++$ w++$ tv+ b++ DI D++ 5++
The Tao of math: The numbers you can count are not the real numbers.
Life is complex, with real and imaginary parts.
"Ok, it boots. Which means it must be bug-free and perfect. " -- Linus Torvalds
"People disagree with me. I just ignore them." -- Linus Torvalds
_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|

Re: Default argument type for function without prototype?

Richard Smith via cfe-dev
Thank you Csaba for the answer and the time spent!
One more time I apologize for an off topic question.

2018-01-22 2:07 GMT+03:00 Csaba Raduly <[hidden email]>:

I don't understand this. A google search for "mailing list" returns
almost eight million results. You could have sent your question to any
of them.

I googled "clang mailing list" :-) and there are two options: 'cfe-dev' and 'cfe-commits'.
And 'cfe-dev' - This list is for everything else Clang related (questions and answers, design discussions, etc).

With kind regards,
-gdg


_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|

Re: Default argument type for function without prototype?

Richard Smith via cfe-dev


On 22 January 2018 at 07:41, Kirill Balunov via cfe-dev <[hidden email]> wrote:
Thank you Csaba for the answer and the time spent!
One more time I apologize for an off topic question.

2018-01-22 2:07 GMT+03:00 Csaba Raduly <[hidden email]>:

I don't understand this. A google search for "mailing list" returns
almost eight million results. You could have sent your question to any
of them.

I googled "clang mailing list" :-) and there are two options: 'cfe-dev' and 'cfe-commits'.
And 'cfe-dev' - This list is for everything else Clang related (questions and answers, design discussions, etc).

I think the point is that this question is not for the Clang mailing list, as it isn't a decision made by the Clang developers. What happens in your example piece of code is dictated by a combination of calling convention (which registers contain what when calling functions) combined with the behaviour described in the C standard (why untyped arguments are `int`). You may want to use a more modern C standard, the code you posted won't compile as C++, nor will it compile with `-ansi` or `-std=c99`.

The code exhibits undefined behaviour, and you'll almost certainly get a completely different result on x86-32 machine, yet a different result on an ARM processor, and in some cases it may well crash or cause some other "interesting" behaviour. And if you change the code a little bit, for example add a variable in your `impl` function that uses floating point calculations, it will do something completely different. Or maybe not... It's undefined behaviour, so "anything can happen".

--
Mats

With kind regards,
-gdg


_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev



_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev