By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
435,089 Members | 2,069 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 435,089 IT Pros & Developers. It's quick & easy.

function calls, mandatory compiler promotion of int arguments tosize_t?

P: n/a
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
Share this Question
Share on Google+
20 Replies


P: n/a
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

P: n/a
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

P: n/a
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

P: n/a
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

P: n/a
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

P: n/a
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

P: n/a
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

P: n/a
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

P: n/a
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

P: n/a
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

P: n/a
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

P: n/a
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

P: n/a
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

P: n/a
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

P: n/a
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

P: n/a
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

P: n/a
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

P: n/a
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

P: n/a
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

P: n/a
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 discussion thread is closed

Replies have been disabled for this discussion.