473,398 Members | 2,343 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,398 software developers and data experts.

function calls, mandatory compiler promotion of int arguments tosize_t?

For this small test program:

#include <stdio.h>
void main(void){
char buffer[]="ABCDEFGHIJKLMNOPQRSTUVWXYZ\n";
int size, count;
size = 27; /* always a small number which will fit in an int */
count = 1; /* ditto */
(void) fwrite(buffer, size, count, stdout);
}

The int variables size and count are both used for fwrite() arguments
which are prototyped to be size_t. If size_t is bigger than int (as on
some 64 bit systems where size_t is 8 bytes and int is 4 bytes), does
the C standard require the compiler to promote these two int values to
size_t before passing them to the function, and if so, what exactly does
it say?

I know that in _practice_ the code above works, but I am curious if that
must always be the case.

Thanks,

David Mathog
Aug 1 '08 #1
20 1530
David Mathog wrote:
For this small test program:

#include <stdio.h>
void main(void){
Tut. Tut, tut, tut. Consider your wrist slapped.
char buffer[]="ABCDEFGHIJKLMNOPQRSTUVWXYZ\n";
int size, count;
size = 27; /* always a small number which will fit in an int */
count = 1; /* ditto */
(void) fwrite(buffer, size, count, stdout);
}

The int variables size and count are both used for fwrite() arguments
which are prototyped to be size_t. If size_t is bigger than int (as on
some 64 bit systems where size_t is 8 bytes and int is 4 bytes), does
the C standard require the compiler to promote these two int values to
size_t before passing them to the function, and if so, what exactly does
it say?
Yes, and 6.5.2.2p7: "If the expression that denotes the called
function has a type that does include a prototype, the arguments are
implicitly converted, as if by assignment, to the types of the
corresponding parameters, taking the type of each parameter to be the
unqualified version of its declared type."
I know that in _practice_ the code above works, but I am curious if that
must always be the case.
Yes, it is. Note that the prototype-governed conversions cut both
ways, though: If you pass a "wide" argument expression to a prototyped
function with a "narrower" parameter, the conversion from wide to narrow
may lose information silently. Similarly, if you pass a floating-point
argument to a prototyped integer parameter, the fractional part vanishes
silently. (There's the seedling of an IOCCC entry here, I think: try
`malloc(atan(42.0))' to allocate an 88-byte object ...)

--
Er*********@sun.com
Aug 1 '08 #2
Eric Sosman <Er*********@sun.comwrites:
[...]
Yes, it is. Note that the prototype-governed conversions cut both
ways, though: If you pass a "wide" argument expression to a prototyped
function with a "narrower" parameter, the conversion from wide to narrow
may lose information silently.
Or it may give you some unexpected result. Conversion to a signed
integer type, if the value can't be represented in the target type,
yields an implementation-defined result (or raises an
implementation-defined signal; the latter is new in C99).
Similarly, if you pass a floating-point
argument to a prototyped integer parameter, the fractional part vanishes
silently. (There's the seedling of an IOCCC entry here, I think: try
`malloc(atan(42.0))' to allocate an 88-byte object ...)
For certain values of 42.0.

Actually, for *no* values of 42.0; the results of atan() are in the
range [-pi/2, +pi/2] (radians).

But tan(1.5595) would do it. Note that very small changes in the
argument result in large changes in the result.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Aug 1 '08 #3
Keith Thompson wrote:
Eric Sosman <Er*********@sun.comwrites:
[...]
> Yes, it is. Note that the prototype-governed conversions cut both
ways, though: If you pass a "wide" argument expression to a prototyped
function with a "narrower" parameter, the conversion from wide to narrow
may lose information silently.

Or it may give you some unexpected result. Conversion to a signed
integer type, if the value can't be represented in the target type,
yields an implementation-defined result (or raises an
implementation-defined signal; the latter is new in C99).
Both of these qualify as "losing information," in my view.
> Similarly, if you pass a floating-point
argument to a prototyped integer parameter, the fractional part vanishes
silently. (There's the seedling of an IOCCC entry here, I think: try
`malloc(atan(42.0))' to allocate an 88-byte object ...)

For certain values of 42.0.

Actually, for *no* values of 42.0; the results of atan() are in the
range [-pi/2, +pi/2] (radians).
Oh, drat! Calculator operating in degree mode instead of radians,
brain operating in la-la mode instead of with its usual acuituity ...
But tan(1.5595) would do it. Note that very small changes in the
argument result in large changes in the result.
I'd also considered log(1E30) and pow(42.0, 2.40), but they
seemed insufficiently obfuscatory.

--
Er*********@sun.com
Aug 1 '08 #4
Eric Sosman <Er*********@sun.comwrites:
Keith Thompson wrote:
>Eric Sosman <Er*********@sun.comwrites:
[...]
>> Yes, it is. Note that the prototype-governed conversions cut both
ways, though: If you pass a "wide" argument expression to a prototyped
function with a "narrower" parameter, the conversion from wide to narrow
may lose information silently.
Or it may give you some unexpected result. Conversion to a signed
integer type, if the value can't be represented in the target type,
yields an implementation-defined result (or raises an
implementation-defined signal; the latter is new in C99).

Both of these qualify as "losing information," in my view.
But raising a signal doesn't necesssarily qualify as "silently".

[snip]

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Aug 1 '08 #5
Eric Sosman wrote:
David Mathog wrote:
>For this small test program:

#include <stdio.h>
void main(void){

Tut. Tut, tut, tut. Consider your wrist slapped.
Exit status and error checking were intentionally sacrificed for a
shorter example program. I agree that real programs shouldn't do this,
but by going with "void main" and throwing out the one status value
returned the example program was able to drop a few lines which had
nothing to do with the question at hand.
>
Yes, and 6.5.2.2p7: "If the expression that denotes the called
function has a type that does include a prototype, the arguments are
implicitly converted, as if by assignment, to the types of the
corresponding parameters, taking the type of each parameter to be the
unqualified version of its declared type."
Perfect, that was exactly what I wanted to know.

Thanks,

David Mathog
Aug 1 '08 #6
David Mathog <ma****@caltech.eduwrites:
Eric Sosman wrote:
>David Mathog wrote:
>>For this small test program:

#include <stdio.h>
void main(void){

Tut. Tut, tut, tut. Consider your wrist slapped.

Exit status and error checking were intentionally sacrificed for a
shorter example program.
In fact, C99 permits the return <exp>; to be omitted (zero is assumed)
so int main(void)... is even shorter (OK, by only one character) /and/
letter-of-the-law correct.

--
Ben.
Aug 1 '08 #7
On 1 Aug 2008 at 22:29, David Mathog wrote:
Eric Sosman wrote:
>David Mathog wrote:
>>void main(void){

Tut. Tut, tut, tut. Consider your wrist slapped.

Exit status and error checking were intentionally sacrificed for a
shorter example program. I agree that real programs shouldn't do this,
but by going with "void main" and throwing out the one status value
returned the example program was able to drop a few lines which had
nothing to do with the question at hand.
Unfortunately that won't wash with many of the "regulars" around here.
They don't know much about C, but they do have a religious zeal for
getting the return type of main "correct".

Many of them will try to argue that having void main there might have
everything to do with the question at hand, since according to clc dogma
it invokes UB, and they expect the compiler then to do everything in its
power to make your program go wrong.

The fact that this is complete nonsense in the real world means not a
whit to them.

Aug 1 '08 #8
On Aug 2, 1:29 am, David Mathog <mat...@caltech.eduwrote:
Eric Sosman wrote:
David Mathog wrote:
For this small test program:
#include <stdio.h>
void main(void){
Tut. Tut, tut, tut. Consider your wrist slapped.

Exit status and error checking were intentionally sacrificed for a
shorter example program.
Then why the superfluous cast in the fwrite call?
Aug 2 '08 #9
On Fri, 01 Aug 2008 12:48:21 -0700, David Mathog <ma****@caltech.edu>
wrote:
>For this small test program:

#include <stdio.h>
void main(void){
char buffer[]="ABCDEFGHIJKLMNOPQRSTUVWXYZ\n";
int size, count;
size = 27; /* always a small number which will fit in an int */
count = 1; /* ditto */
(void) fwrite(buffer, size, count, stdout);
}

The int variables size and count are both used for fwrite() arguments
which are prototyped to be size_t. If size_t is bigger than int (as on
some 64 bit systems where size_t is 8 bytes and int is 4 bytes), does
the C standard require the compiler to promote these two int values to
size_t before passing them to the function, and if so, what exactly does
it say?
As long as others have picked the nits, this is not a promotion in the
way the standard uses the term. It is a conversion as if by
assignment. If you change size and count to long and have a system
where size_t is unsigned int, the compiler is still required to
convert the arguments to the type expected by the called function
(even though it is a demotion).

--
Remove del for email
Aug 2 '08 #10
vi******@gmail.com wrote:
On Aug 2, 2:21 pm, santosh <santosh....@gmail.comwrote:
>vipps...@gmail.com wrote:
On Aug 1, 10:48 pm, David Mathog <mat...@caltech.eduwrote:
For this small test program:
>#include <stdio.h>
void main(void){
char buffer[]="ABCDEFGHIJKLMNOPQRSTUVWXYZ\n";
int size, count;
size = 27; /* always a small number which will fit in an int
*/
count = 1; /* ditto
*/ (void) fwrite(buffer, size, count, stdout);
>}

[ ... ]
>I know that in _practice_ the code above works, but I am curious
if that must always be the case.
It doesn't, it's not.

Does it _really_ fail if 'size' and 'count' are switched in this
case? [ ... ]
They are both correct. However I was refering to 'void main()'.
(assuming hosted implementation)
Ah, OK. I failed to notice that error.

Aug 2 '08 #11
In article <sl*******************@nospam.invalid>, Antoninus Twink
<no****@nospam.invalidwrote:
On 1 Aug 2008 at 22:29, David Mathog wrote:
Eric Sosman wrote:
David Mathog wrote:
void main(void){

Tut. Tut, tut, tut. Consider your wrist slapped.
Exit status and error checking were intentionally sacrificed for a
shorter example program. I agree that real programs shouldn't do this,
but by going with "void main" and throwing out the one status value
returned the example program was able to drop a few lines which had
nothing to do with the question at hand.

Unfortunately that won't wash with many of the "regulars" around here.
They don't know much about C, but they do have a religious zeal for
getting the return type of main "correct".

Many of them will try to argue that having void main there might have
everything to do with the question at hand, since according to clc dogma
it invokes UB, and they expect the compiler then to do everything in its
power to make your program go wrong.
Sometimes UB like this is relevant to the person's question/problem, so
ignoring it might be ignoring the problem. Besides, it's an easy fix and
why not use the context as an opportunity to educate?
The fact that this is complete nonsense in the real world means not a
whit to them.
Either one is posting a compilable, runnable example, or one is not. If
not, why bother with #include <stdio.h>, or a main function at all?
Aug 3 '08 #12
blargg wrote:
Antoninus Twink <no****@nospam.invalidwrote:
.... snip ...
>
Sometimes UB like this is relevant to the person's question/problem
, so ignoring it might be ignoring the problem. Besides, it's an
easy fix and why not use the context as an opportunity to educate?
>The fact that this is complete nonsense in the real world means
not a whit to them.

Either one is posting a compilable, runnable example, or one is
not. If not, why bother with #include <stdio.h>, or a main
function at all?
Ignoring the fact that Twink is a troll, if not posting a complete
compilable and runnable program, why bother posting at all? Think
of the electrons that could be saved. You will save time and be
able to contribute to PETE.

--
[mail]: Chuck F (cbfalconer at maineline dot net)
[page]: <http://cbfalconer.home.att.net>
Try the download section.
Aug 3 '08 #13
On Aug 3, 3:23 am, blargg....@gishpuppy.com (blargg) wrote:
In article <slrng97476.438.nos...@nospam.invalid>, Antoninus Twink

<nos...@nospam.invalidwrote:
On 1 Aug 2008 at 22:29, David Mathog wrote:
Eric Sosman wrote:
>David Mathog wrote:
>>void main(void){
> Tut. Tut, tut, tut. Consider your wrist slapped.
Exit status and error checking were intentionally sacrificed for a
shorter example program. I agree that real programs shouldn't do this,
but by going with "void main" and throwing out the one status value
returned the example program was able to drop a few lines which had
nothing to do with the question at hand.
Unfortunately that won't wash with many of the "regulars" around here.
They don't know much about C, but they do have a religious zeal for
getting the return type of main "correct".
Many of them will try to argue that having void main there might have
everything to do with the question at hand, since according to clc dogma
it invokes UB, and they expect the compiler then to do everything in its
power to make your program go wrong.

Sometimes UB like this is relevant to the person's question/problem, so
ignoring it might be ignoring the problem. Besides, it's an easy fix and
why not use the context as an opportunity to educate?
The fact that this is complete nonsense in the real world means not a
whit to them.

Either one is posting a compilable, runnable example, or one is not. If
not, why bother with #include <stdio.h>, or a main function at all?
It *is* compilable and runnable, but perhaps not with all compilers.
AFAIK, the standard states that an implementation may accept an
implementation-defined prototype for main(). I'd expect 'void
main(void)' to be a common choice for such prototype, seems it looks
fairly natural and is the one used in other languages.

Sebastian

Aug 4 '08 #14
s0****@gmail.com wrote:

<snip>
AFAIK, the standard states that an implementation may accept an
implementation-defined prototype for main(). I'd expect 'void
main(void)' to be a common choice for such prototype, seems it looks
fairly natural and is the one used in other languages.
I would always return a sensible value back to the system. Returning
garbage values (which is what happens when you use void main) breaks
scripts and wrapper programs. Just return 0 or EXIT_FAILURE. Why is
this so hard?

Aug 4 '08 #15
s0****@gmail.com wrote:
On Aug 3, 3:23 am, blargg....@gishpuppy.com (blargg) wrote:
Either one is posting a compilable, runnable example, or one is not. If
not, why bother with #include <stdio.h>, or a main function at all?

It *is* compilable and runnable, but perhaps not with all compilers.
So is

int WINAPI WinMain(HINSTANCE instance, HINSTANCE previnst__,
PSTR cmdline, int showmode)

but you wouldn't recommend that as a sensible form of the main program
to be posted to this newsgroup, would you?

Richard
Aug 4 '08 #16
vi******@gmail.com wrote:
On Aug 2, 1:29 am, David Mathog <mat...@caltech.eduwrote:
>Eric Sosman wrote:
>>David Mathog wrote:
For this small test program:
#include <stdio.h>
void main(void){
Tut. Tut, tut, tut. Consider your wrist slapped.
Exit status and error checking were intentionally sacrificed for a
shorter example program.

Then why the superfluous cast in the fwrite call?
(void) fwrite(buffer, size, count, stdout);

Tells the compiler (and anybody reading the program) that the return
value is intentionally being ignored. Leave that off and in their
pickier modes many compilers will issue a warning about the unused
return value.

Regards,

David Mathog
Aug 4 '08 #17
On Aug 4, 9:48 am, r...@hoekstra-uitgeverij.nl (Richard Bos) wrote:
s0s...@gmail.com wrote:
On Aug 3, 3:23 am, blargg....@gishpuppy.com (blargg) wrote:
Either one is posting a compilable, runnable example, or one is not. If
not, why bother with #include <stdio.h>, or a main function at all?
It *is* compilable and runnable, but perhaps not with all compilers.

So is

int WINAPI WinMain(HINSTANCE instance, HINSTANCE previnst__,
PSTR cmdline, int showmode)

but you wouldn't recommend that as a sensible form of the main program
to be posted to this newsgroup, would you?
Well, that's not main(); that's WinMain(), so it wouldn't work even if
it would be prototyped 'int WinMain(void)'.

Sebastian

Aug 4 '08 #18
s0****@gmail.com wrote:
On Aug 4, 9:48 am, r...@hoekstra-uitgeverij.nl (Richard Bos) wrote:
s0s...@gmail.com wrote:
On Aug 3, 3:23 am, blargg....@gishpuppy.com (blargg) wrote:
Either one is posting a compilable, runnable example, or one is not. If
not, why bother with #include <stdio.h>, or a main function at all?
It *is* compilable and runnable, but perhaps not with all compilers.
So is

int WINAPI WinMain(HINSTANCE instance, HINSTANCE previnst__,
PSTR cmdline, int showmode)

but you wouldn't recommend that as a sensible form of the main program
to be posted to this newsgroup, would you?

Well, that's not main(); that's WinMain(), so it wouldn't work even if
it would be prototyped 'int WinMain(void)'.
Well, surprisingly enough, there's nothing in the Standard that forbids
you from writing

int WINAPI main(HINSTANCE instance, HINSTANCE previnst__,
PSTR cmdline, int showmode)

Richard

Aug 5 '08 #19
On 4 Aug, 16:14, David Mathog <mat...@caltech.eduwrote:
vipps...@gmail.com wrote:
On Aug 2, 1:29 am, David Mathog <mat...@caltech.eduwrote:
Eric Sosman wrote:
David Mathog wrote:
For this small test program:
#include <stdio.h>
void main(void){
* * Tut. *Tut, tut, tut. *Consider your wrist slapped.
Exit status and error checking were intentionally sacrificed for a
shorter example program.
Then why the superfluous cast in the fwrite call?

* *(void) fwrite(buffer, size, count, stdout);

Tells the compiler (and anybody reading the program) that the return
value is intentionally being ignored. *Leave that off and in their
pickier modes many compilers will issue a warning about the unused
return value.
I haven't come across one that did that for quite a while.
And even then I thought it was Lint rather than a compiler.
Personnally I'd stop using a compiler (or compiler mode)
that did that.

--
Nick Keighley

Aug 5 '08 #20
Nick Keighley wrote:
David Mathog <mat...@caltech.eduwrote:
>vipps...@gmail.com wrote:
.... snip ...
>>
>>Then why the superfluous cast in the fwrite call?

(void) fwrite(buffer, size, count, stdout);

Tells the compiler (and anybody reading the program) that the
return value is intentionally being ignored. Leave that off
and in their pickier modes many compilers will issue a warning
about the unused return value.

I haven't come across one that did that for quite a while.
And even then I thought it was Lint rather than a compiler.
Personnally I'd stop using a compiler (or compiler mode)
that did that.
Actually if they all did that we would save a lot of effort telling
newbies to check the response of scanf, fclose, etc. And, if
something goes wrong, the presence of that (void) encourages
getting the actual response and checking it.

--
[mail]: Chuck F (cbfalconer at maineline dot net)
[page]: <http://cbfalconer.home.att.net>
Try the download section.
Aug 5 '08 #21

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

10
by: Michael | last post by:
Guys, I'm interested in how the compiler implements function calls, can anyone correct my understanding/point me towards some good articles. When a function is called, is the stack pointer...
6
by: bluekite2000 | last post by:
I have Vector<complex<float> > V(5); V.rand(); Vector<float> V1(V); //specialized function here to return norm(V). This works fine Vector<double> V2(5); V2.rand(); Vector<float>...
28
by: Michael B. | last post by:
I tend to use rather descriptive names for parameters, so the old style of declaration appeals to me, as I can keep a declaration within 80 chars: void * newKlElem...
18
by: Razvan | last post by:
Hi! What is the purpose of such a function ? int function(void)
4
by: anonymous | last post by:
Thanks your reply. The article I read is from www.hakin9.org/en/attachments/stackoverflow_en.pdf. And you're right. I don't know it very clearly. And that's why I want to understand it; for it's...
3
by: Beta What | last post by:
Hello, I have a question about casting a function pointer. Say I want to make a generic module (say some ADT implementation) that requires a function pointer from the 'actual/other modules'...
3
by: =?ISO-8859-15?Q?Jean=2DFran=E7ois?= Lemaire | last post by:
Hello, I'm having a discussion with someone who sustains that function parameters, when they are smaller than an int (say short or char) are automatically promoted to int before being passed to...
9
by: Yannick | last post by:
Hi everyone - I am not quite sure to understand what is really going on when a function defined in one translation unit calls a function defined in a different translation unit without knowing...
8
by: vaib | last post by:
hi all , It really seems that C never ceases to amaze . All this time i've been doing C and i thought i was quite adept at it but i was wrong . So without wasting any more time , here's the...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.