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

Usefulness of %hd in printf

P: n/a
Is there any possible situation for printf where %hd causes a different
result to %d, and the corresponding argument was of type 'short int' ?

Jan 23 '07 #1
Share this Question
Share on Google+
34 Replies


P: n/a
Old Wolf wrote:
Is there any possible situation for printf where %hd causes a different
result to %d, and the corresponding argument was of type 'short int' ?
Think about the scanf() family of functions.

Sure, the short will promote just like floats promote to double for the
same reason. But addresses do not promote. Hence, the need for a
width specifier for 'smaller than default promotion' types.

Jan 23 '07 #2

P: n/a
user923005 wrote:
Old Wolf wrote:
Is there any possible situation for printf where %hd causes a different
result to %d, and the corresponding argument was of type 'short int' ?

Think about the scanf() family of functions.
I'm asking about the printf() family.

Are you saying that there is no difference in printf, but they added
support for %hd just to try and keep the printf family similar to the
scanf family?

Jan 23 '07 #3

P: n/a
Old Wolf wrote:
user923005 wrote:
Old Wolf wrote:
Is there any possible situation for printf where %hd causes a different
result to %d, and the corresponding argument was of type 'short int' ?
Think about the scanf() family of functions.

I'm asking about the printf() family.

Are you saying that there is no difference in printf, but they added
support for %hd just to try and keep the printf family similar to the
scanf family?
No. I am saying scanf() has to have it, while printf() could care
less.

We could just as easily complain about:

12.9: Someone told me it was wrong to use %lf with printf(). How can
printf() use %f for type double, if scanf() requires %lf?

A: It's true that printf's %f specifier works with both float and
double arguments. Due to the "default argument promotions"
(which apply in variable-length argument lists such as
printf's, whether or not prototypes are in scope), values of
type float are promoted to double, and printf() therefore sees
only doubles. (printf() does accept %Lf, for long double.)
See also questions 12.13 and 15.2.

References: K&R1 Sec. 7.3 pp. 145-47, Sec. 7.4 pp. 147-50; K&R2
Sec. 7.2 pp. 153-44, Sec. 7.4 pp. 157-59; ISO Sec. 7.9.6.1,
Sec. 7.9.6.2; H&S Sec. 15.8 pp. 357-64, Sec. 15.11 pp. 366-78;
CT&P Sec. A.1 pp. 121-33.

Jan 23 '07 #4

P: n/a
>From the C99 standard, here is the bit on default promotions for things
lacking prototypes and for variadic functions...
>From ©ISO/IEC ISO/IEC 9899:1999 (E), 6.5.2.2 Function calls:
"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. These are called the default argument promotions. If the number
of arguments does not equal the number of parameters, the behavior is
undefined. If the function is defined with a type that includes a
prototype, and either the prototype ends with an ellipsis (, ...) or
the types of the arguments after promotion are not compatible with the
types of the parameters, the behavior is undefined. If the function is
defined with a type that does not include a prototype, and the types of
the arguments after promotion are not compatible with those of the
parameters after promotion, the behavior is undefined, except for the
following cases:
* one promoted type is a signed integer type, the other promoted type
is the corresponding unsigned integer type, and the value is
representable in both types;
* both types are pointers to qualified or unqualified versions of a
character type or void."

Jan 23 '07 #5

P: n/a
user923005 wrote:
Old Wolf wrote:
user923005 wrote:
Old Wolf wrote:
Is there any possible situation for printf where %hd causes a different
result to %d, and the corresponding argument was of type 'short int' ?
>
Think about the scanf() family of functions.
I'm asking about the printf() family.

Are you saying that there is no difference in printf, but they added
support for %hd just to try and keep the printf family similar to the
scanf family?

No. I am saying scanf() has to have it, while printf() could care
less.
So you are saying it does make a difference to printf?
What difference?

Or do you mean "couldn't care less" ?
We could just as easily complain about:

12.9: Someone told me it was wrong to use %lf with printf(). How can
printf() use %f for type double, if scanf() requires %lf?
Huh? I'm not complaining. I'm asking about printf (NOT scanf). You
brought scanf into this.
A: It's true that printf's %f specifier works with both float and
double arguments. Due to the "default argument promotions"
(which apply in variable-length argument lists such as
printf's, whether or not prototypes are in scope), values of
type float are promoted to double, and printf() therefore sees
only doubles. (printf() does accept %Lf, for long double.)
See also questions 12.13 and 15.2.
This is irrelevant to my question. (If you don't know the answer then
just say so, or don't reply)

Jan 23 '07 #6

P: n/a
"Old Wolf" <ol*****@inspire.net.nzwrote in message
news:11**********************@d71g2000cwa.googlegr oups.com...
user923005 wrote:
>Old Wolf wrote:
user923005 wrote:
Old Wolf wrote:
Is there any possible situation for printf where %hd causes a
different
result to %d, and the corresponding argument was of type 'short
int' ?

Think about the scanf() family of functions.

I'm asking about the printf() family.

Are you saying that there is no difference in printf, but they added
support for %hd just to try and keep the printf family similar to the
scanf family?

No. I am saying scanf() has to have it, while printf() could care
less.

So you are saying it does make a difference to printf?
What difference?

Or do you mean "couldn't care less" ?
>We could just as easily complain about:

12.9: Someone told me it was wrong to use %lf with printf(). How can
printf() use %f for type double, if scanf() requires %lf?

Huh? I'm not complaining. I'm asking about printf (NOT scanf). You
brought scanf into this.
>A: It's true that printf's %f specifier works with both float and
double arguments. Due to the "default argument promotions"
(which apply in variable-length argument lists such as
printf's, whether or not prototypes are in scope), values of
type float are promoted to double, and printf() therefore sees
only doubles. (printf() does accept %Lf, for long double.)
See also questions 12.13 and 15.2.

This is irrelevant to my question. (If you don't know the answer then
just say so, or don't reply)
%hd prints out the int argument cast to short. So it scrapes off any bits
that can't be represented in a short.

P.J. Plauger
Dinkumware, Ltd.
http://www.dinkumware.com
Jan 23 '07 #7

P: n/a
P.J. Plauger wrote:
"Old Wolf" <ol*****@inspire.net.nzwrote in message
news:11**********************@d71g2000cwa.googlegr oups.com...
>user923005 wrote:
>>Old Wolf wrote:
user923005 wrote:
Old Wolf wrote:
>Is there any possible situation for printf where %hd causes a
>different
>result to %d, and the corresponding argument was of type 'short
>int' ?
Think about the scanf() family of functions.
I'm asking about the printf() family.

Are you saying that there is no difference in printf, but they added
support for %hd just to try and keep the printf family similar to the
scanf family?
No. I am saying scanf() has to have it, while printf() could care
less.
So you are saying it does make a difference to printf?
What difference?

Or do you mean "couldn't care less" ?
>>We could just as easily complain about:

12.9: Someone told me it was wrong to use %lf with printf(). How can
printf() use %f for type double, if scanf() requires %lf?
Huh? I'm not complaining. I'm asking about printf (NOT scanf). You
brought scanf into this.
>>A: It's true that printf's %f specifier works with both float and
double arguments. Due to the "default argument promotions"
(which apply in variable-length argument lists such as
printf's, whether or not prototypes are in scope), values of
type float are promoted to double, and printf() therefore sees
only doubles. (printf() does accept %Lf, for long double.)
See also questions 12.13 and 15.2.
This is irrelevant to my question. (If you don't know the answer then
just say so, or don't reply)

%hd prints out the int argument cast to short. So it scrapes off any bits
that can't be represented in a short.
So the following is a bug?

----------------------------
#include <stdio.h>

int main (void)
{
int a = 1<<30;
short b = a;
printf ("%d %hd %hd\n", a, a, b);
return 0;
}
----------------------------

It prints

1073741824 1073741824 0

i.e. it doesn't truncate 'a' (which of type int) when prints
it with %hd.

Thanks,
Yevgen
Jan 23 '07 #8

P: n/a
Yevgen Muntyan wrote:
So the following is a bug?

----------------------------
#include <stdio.h>

int main (void)
{
int a = 1<<30;
short b = a;
printf ("%d %hd %hd\n", a, a, b);
return 0;
}
----------------------------

It prints

1073741824 1073741824 0

i.e. it doesn't truncate 'a' (which of type int) when prints
it with %hd.
You caused undefined behaviour by not passing an argument of
type 'short int' to %hd

Jan 23 '07 #9

P: n/a
P.J. Plauger wrote:
Old Wolf wrote:
Is there any possible situation for printf where %hd causes a
different result to %d, and the corresponding argument was
of type 'short int' ?

%hd prints out the int argument cast to short. So it scrapes off any bits
that can't be represented in a short.
Well, when the short int is passed as argument, it is promoted to int
(according to the default argument promotions). So how can the int
have any bits that can't be represented in a short?

#include <stdio.h>
int main()
{
short x;
/* your code here */
printf("%hd\n%d\n", x, x);
return 0;
}

Is there any possible code you can insert where marked, that will
cause two different values to be printed (and the program to not
have undefined behaviour) ?

Jan 23 '07 #10

P: n/a
"Yevgen Muntyan" <mu****************@tamu.eduwrote in message
news:YNoth.4407$QE6.3362@trnddc02...
P.J. Plauger wrote:
>.....
%hd prints out the int argument cast to short. So it scrapes off any bits
that can't be represented in a short.

So the following is a bug?

----------------------------
#include <stdio.h>

int main (void)
{
int a = 1<<30;
short b = a;
printf ("%d %hd %hd\n", a, a, b);
return 0;
}
----------------------------

It prints

1073741824 1073741824 0

i.e. it doesn't truncate 'a' (which of type int) when prints
it with %hd.
Yes, it's a bug. From the C Standard, for 'h' in printf:

: h -- Specifies that a following d, i, o, u, x, or X conversion
: specifier applies to a short int or unsigned short int argument
: (the argument will have been promoted according to the integer
: promotions, but its value shall be converted to short int or
: unsigned short int before printing); or that a following n
: conversion specifier applies to a pointer to a short int
: argument.

Our library prints:

1073741824 0 0

which I believe is correct.

P.J. Plauger
Dinkumware, Ltd.
http://www.dinkumware.com
Jan 23 '07 #11

P: n/a
Old Wolf wrote:
Yevgen Muntyan wrote:
>So the following is a bug?

----------------------------
#include <stdio.h>

int main (void)
{
int a = 1<<30;
short b = a;
printf ("%d %hd %hd\n", a, a, b);
return 0;
}
----------------------------

It prints

1073741824 1073741824 0

i.e. it doesn't truncate 'a' (which of type int) when prints
it with %hd.

You caused undefined behaviour by not passing an argument of
type 'short int' to %hd
Hm, good point. So P.J.Plaguer was talking about UB or about
casting short to short?
I would love to ask now about what happens in practice when
you pass ints to printf, but I won't, since I would flamed
real hard if I did (like, int a = 8; printf("%hd", a); -
real code can be like that, maybe not with short but with
size_t or something).

Yevgen
Jan 23 '07 #12

P: n/a
"P.J. Plauger" <pj*@dinkumware.comwrites:
"Yevgen Muntyan" <mu****************@tamu.eduwrote in message
news:YNoth.4407$QE6.3362@trnddc02...
>So the following is a bug?

----------------------------
#include <stdio.h>

int main (void)
{
int a = 1<<30;
short b = a;
printf ("%d %hd %hd\n", a, a, b);
return 0;
}
----------------------------

It prints

1073741824 1073741824 0

i.e. it doesn't truncate 'a' (which of type int) when prints
it with %hd.

Yes, it's a bug. From the C Standard, for 'h' in printf:

: h -- Specifies that a following d, i, o, u, x, or X conversion
: specifier applies to a short int or unsigned short int argument
: (the argument will have been promoted according to the integer
: promotions, but its value shall be converted to short int or
: unsigned short int before printing); or that a following n
: conversion specifier applies to a pointer to a short int
: argument.
I disagree. It's a bug in the test program, because the first
%hd argument is not a short int or unsigned short int argument,
which the description above require it to be. It's an int
argument.

If that is not correct, for some reason, then its behavior is
implementation-defined or perhaps undefined, because converting
an out-of-range value to a signed integer type either causes
implementation-defined behavior or raises an
implementation-defined signal.

--
int main(void){char p[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuv wxyz.\
\n",*q="kl BIcNBFr.NKEzjwCIxNJC";int i=sizeof p/2;char *strchr();int putchar(\
);while(*q){i+=strchr(p,*q++)-p;if(i>=(int)sizeof p)i-=sizeof p-1;putchar(p[i]\
);}return 0;}
Jan 23 '07 #13

P: n/a
"Yevgen Muntyan" <mu****************@tamu.eduwrote in message
news:Qfpth.4661$QE6.2165@trnddc02...
Old Wolf wrote:
>Yevgen Muntyan wrote:
>>So the following is a bug?

----------------------------
#include <stdio.h>

int main (void)
{
int a = 1<<30;
short b = a;
printf ("%d %hd %hd\n", a, a, b);
return 0;
}
----------------------------

It prints

1073741824 1073741824 0

i.e. it doesn't truncate 'a' (which of type int) when prints
it with %hd.

You caused undefined behaviour by not passing an argument of
type 'short int' to %hd

Hm, good point. So P.J.Plaguer was talking about UB or about
casting short to short?
The C Standard does suggest that the argument to %hd began
as a short and got promoted to int, but all printf cares
about is that it gets an int argument for %hd. The need for
a cast would be vacuous if only short were permitted, so that
suggests that any int value can be passed. Since the effect
of passing any int is defined, it's hard to make a case that
passing certain int values is undefined.
I would love to ask now about what happens in practice when
you pass ints to printf, but I won't, since I would flamed
real hard if I did (like, int a = 8; printf("%hd", a); -
real code can be like that, maybe not with short but with
size_t or something).
Don't see the need for a flame here -- this sort of thing
happens all the time. Some of the wording in the C Standard
reflects the looser heritage of pre-standard days, particularly
in the passing of int/unsigned int where short/unsigned short
is expected. In fact, an anticipated need for %hx was to
ensure that passing -1 prints as ffff (on an 8/16/32 bit
implementation), not ffffffff.

P.J. Plauger
Dinkumware, Ltd.
http://www.dinkumware.com
Jan 23 '07 #14

P: n/a
"Ben Pfaff" <bl*@cs.stanford.eduwrote in message
news:87************@blp.benpfaff.org...
"P.J. Plauger" <pj*@dinkumware.comwrites:
>"Yevgen Muntyan" <mu****************@tamu.eduwrote in message
news:YNoth.4407$QE6.3362@trnddc02...
>>So the following is a bug?

----------------------------
#include <stdio.h>

int main (void)
{
int a = 1<<30;
short b = a;
printf ("%d %hd %hd\n", a, a, b);
return 0;
}
----------------------------

It prints

1073741824 1073741824 0

i.e. it doesn't truncate 'a' (which of type int) when prints
it with %hd.

Yes, it's a bug. From the C Standard, for 'h' in printf:

: h -- Specifies that a following d, i, o, u, x, or X conversion
: specifier applies to a short int or unsigned short int argument
: (the argument will have been promoted according to the integer
: promotions, but its value shall be converted to short int or
: unsigned short int before printing); or that a following n
: conversion specifier applies to a pointer to a short int
: argument.

I disagree. It's a bug in the test program, because the first
%hd argument is not a short int or unsigned short int argument,
which the description above require it to be. It's an int
argument.
I think you can read the C Standard as requiring an int argument,
as I said in my previous post.
If that is not correct, for some reason, then its behavior is
implementation-defined or perhaps undefined, because converting
an out-of-range value to a signed integer type either causes
implementation-defined behavior or raises an
implementation-defined signal.
Now that's a different issue. I agree that the cast overflows,
so that part is undefined. But my remarks about %hx stand,
since conversion to unsigned short is well defined.

P.J. Plauger
Dinkumware, Ltd.
http://www.dinkumware.com
Jan 23 '07 #15

P: n/a
P.J. Plauger wrote, On 23/01/07 14:45:
"Yevgen Muntyan" <mu****************@tamu.eduwrote in message
news:YNoth.4407$QE6.3362@trnddc02...
>P.J. Plauger wrote:
>>.....
%hd prints out the int argument cast to short. So it scrapes off any bits
that can't be represented in a short.
So the following is a bug?

----------------------------
#include <stdio.h>

int main (void)
{
int a = 1<<30;
short b = a;
printf ("%d %hd %hd\n", a, a, b);
return 0;
}
----------------------------

It prints

1073741824 1073741824 0

i.e. it doesn't truncate 'a' (which of type int) when prints
it with %hd.

Yes, it's a bug. From the C Standard, for 'h' in printf:

: h -- Specifies that a following d, i, o, u, x, or X conversion
: specifier applies to a short int or unsigned short int argument
: (the argument will have been promoted according to the integer
: promotions, but its value shall be converted to short int or
: unsigned short int before printing); or that a following n
: conversion specifier applies to a pointer to a short int
: argument.

Our library prints:

1073741824 0 0

which I believe is correct.
I thought the conversion from int to short int was only defined when the
value of the int was in the range that can be represented as a short
int? This, of course, would leave your library as still conforming.

I fully expect to be proved wrong as I know you know the standard better
than I do ;-)
--
Flash Gordon
Jan 23 '07 #16

P: n/a
"Flash Gordon" <sp**@flash-gordon.me.ukwrote in message
news:la************@news.flash-gordon.me.uk...
P.J. Plauger wrote, On 23/01/07 14:45:
>"Yevgen Muntyan" <mu****************@tamu.eduwrote in message
news:YNoth.4407$QE6.3362@trnddc02...
>>P.J. Plauger wrote:
.....
%hd prints out the int argument cast to short. So it scrapes off any
bits
that can't be represented in a short.
So the following is a bug?

----------------------------
#include <stdio.h>

int main (void)
{
int a = 1<<30;
short b = a;
printf ("%d %hd %hd\n", a, a, b);
return 0;
}
----------------------------

It prints

1073741824 1073741824 0

i.e. it doesn't truncate 'a' (which of type int) when prints
it with %hd.

Yes, it's a bug. From the C Standard, for 'h' in printf:

: h -- Specifies that a following d, i, o, u, x, or X conversion
: specifier applies to a short int or unsigned short int argument
: (the argument will have been promoted according to the integer
: promotions, but its value shall be converted to short int or
: unsigned short int before printing); or that a following n
: conversion specifier applies to a pointer to a short int
: argument.

Our library prints:

1073741824 0 0

which I believe is correct.

I thought the conversion from int to short int was only defined when the
value of the int was in the range that can be represented as a short int?
This, of course, would leave your library as still conforming.

I fully expect to be proved wrong as I know you know the standard better
than I do ;-)
Sorry, but you're right, as I pointed out in an earlier post.

P.J. Plauger
Dinkumware, Ltd.
http://www.dinkumware.com
Jan 23 '07 #17

P: n/a
"Old Wolf" <ol*****@inspire.net.nzwrites:
Yevgen Muntyan wrote:
So the following is a bug?

----------------------------
#include <stdio.h>

int main (void)
{
int a = 1<<30;
short b = a;
printf ("%d %hd %hd\n", a, a, b);
return 0;
}
----------------------------

It prints

1073741824 1073741824 0

i.e. it doesn't truncate 'a' (which of type int) when prints
it with %hd.

You caused undefined behaviour by not passing an argument of
type 'short int' to %hd
Interesting.

In the description of fprintf(), C99 7.19.6.1p7 says that the 'h'
modifier

Specifies that a following d, i, o, u, x, or X conversion
specifier applies to a short int or unsigned short int argument
(the argument will have been promoted according to the integer
promotions, but its value shall be converted to short int or
unsigned short int before printing);
[...]

and p9 says:

[...] If any argument is not the correct type for the
corresponding conversion specification, the behavior is undefined.

But is the "correct type" for "%hd" short, or is it int?

If the correct type is short, then the following two calls:

printf("%hd\n", (short)42);
printf("%hd\n", 42);

can behave differently, and the latter invokes undefined behavior.
For any user-written variadic function that uses <stdarg.h>, the two
calls are identical; the "(short)42)" argument is promoted to int
before the call.

The standard doesn't say that printf() uses <stdarg.h>. Conceivably
the compiler could treat printf() specially, but it would be difficult
(but not impossible) to do this for calls through a pointer, where the
compiler doesn't know whether it's calling printf() or an equivalent
user-defined variadic function.

Things would be more consistent if the "correct type" for "%hd" were
int rather than short.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Jan 23 '07 #18

P: n/a
Yevgen Muntyan wrote:
>
.... snip ...
>
So the following is a bug?

----------------------------
#include <stdio.h>

int main (void)
{
int a = 1<<30;
short b = a;
This probably overflows, and all other behaviour is undefined. In
fact the 1<<30 may have overflowed already. So you have no hope of
detecting anything in any further code.

--
<http://www.cs.auckland.ac.nz/~pgut001/pubs/vista_cost.txt>

"A man who is right every time is not likely to do very much."
-- Francis Crick, co-discover of DNA
"There is nothing more amazing than stupidity in action."
-- Thomas Matthews
Jan 23 '07 #19

P: n/a
CBFalconer <cb********@yahoo.comwrites:
Yevgen Muntyan wrote:
... snip ...

So the following is a bug?

----------------------------
#include <stdio.h>

int main (void)
{
int a = 1<<30;
short b = a;

This probably overflows, and all other behaviour is undefined. In
fact the 1<<30 may have overflowed already. So you have no hope of
detecting anything in any further code.
Assuming the value 1<<30 can be represented as an int but not as a
short, there is no undefined behavior. Overflow on an arithmetic
operator invokes UB, but overflow on a conversion, as in "short b = a;",
merely yields an implementation-defined result or (in C99) raises an
implementation-defined signal.

But yes, it's also possible that 1<<30 exceeds INT_MAX; in that case,
the "<<" operator invokes undefined behavior even before the result is
assigned to "a".

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Jan 23 '07 #20

P: n/a
Keith Thompson wrote, On 23/01/07 17:56:
"Old Wolf" <ol*****@inspire.net.nzwrites:
>Yevgen Muntyan wrote:
>>So the following is a bug?

----------------------------
#include <stdio.h>

int main (void)
{
int a = 1<<30;
short b = a;
printf ("%d %hd %hd\n", a, a, b);
return 0;
}
----------------------------

It prints

1073741824 1073741824 0

i.e. it doesn't truncate 'a' (which of type int) when prints
it with %hd.
You caused undefined behaviour by not passing an argument of
type 'short int' to %hd

Interesting.

In the description of fprintf(), C99 7.19.6.1p7 says that the 'h'
modifier

Specifies that a following d, i, o, u, x, or X conversion
specifier applies to a short int or unsigned short int argument
(the argument will have been promoted according to the integer
promotions, but its value shall be converted to short int or
unsigned short int before printing);
[...]

and p9 says:

[...] If any argument is not the correct type for the
corresponding conversion specification, the behavior is undefined.

But is the "correct type" for "%hd" short, or is it int?

If the correct type is short, then the following two calls:

printf("%hd\n", (short)42);
printf("%hd\n", 42);

can behave differently, and the latter invokes undefined behavior.
For any user-written variadic function that uses <stdarg.h>, the two
calls are identical; the "(short)42)" argument is promoted to int
before the call.

The standard doesn't say that printf() uses <stdarg.h>. Conceivably
the compiler could treat printf() specially, but it would be difficult
(but not impossible) to do this for calls through a pointer, where the
compiler doesn't know whether it's calling printf() or an equivalent
user-defined variadic function.

Things would be more consistent if the "correct type" for "%hd" were
int rather than short.
Possibly they did it because it was simpler than making it undefined for
integers outside the range of short (the library might take advantage of
the limited range to do something that won't work with a larger range)
and undefined to pass int instead of long or long instead of int etc.
After all, why would you use %hd when you are actually going to be
passing an int that could be out of range for a short?
--
Flash Gordon
Jan 23 '07 #21

P: n/a
0
"Keith Thompson" <ks***@mib.orgwrote in message
news:ln************@nuthaus.mib.org...
Specifies that a following d, i, o, u, x, or X conversion
specifier applies to a short int or unsigned short int argument
(the argument will have been promoted according to the integer
promotions, but its value shall be converted to short int or
unsigned short int before printing);
Things would be more consistent if the "correct type" for "%hd" were
int rather than short.
You're making it more complex than things are IMO.
You can just think of it that the variable is cast to short inside printf
discarding the bits that dont fit into a short anymore. So passing a short
is always safe, passing an int is safe as long as its value fits into a
short too.

Dont think I'll ever run into trouble on whatever platform with that in
mind.
Jan 23 '07 #22

P: n/a
"Serve Laurijssen" <se*@n.tkwrites:
"Keith Thompson" <ks***@mib.orgwrote in message
news:ln************@nuthaus.mib.org...
Specifies that a following d, i, o, u, x, or X conversion
specifier applies to a short int or unsigned short int argument
(the argument will have been promoted according to the integer
promotions, but its value shall be converted to short int or
unsigned short int before printing);
Things would be more consistent if the "correct type" for "%hd" were
int rather than short.

You're making it more complex than things are IMO.
I'm not; the standard is.
You can just think of it that the variable is cast to short inside printf
discarding the bits that dont fit into a short anymore. So passing a short
is always safe, passing an int is safe as long as its value fits into a
short too.
Casting from int to short doesn't necessarily just discard bits, but
converting an int value that's representable as a short is guaranteed
to yield the same value.
Dont think I'll ever run into trouble on whatever platform with that in
mind.
That's probably true. Assuming that short is the "correct type" for
"%hd" (as the standard implies), passing an int value to printf() with
a "%hd" format invokes undefined behavior, according to the standard.
But it's difficult to imagine a conforming implementation in which

printf("%hd\n", 42);

does anything other than printing "42".

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Jan 23 '07 #23

P: n/a
Keith Thompson wrote:
>
.... snip ...
>
Things would be more consistent if the "correct type" for "%hd"
were int rather than short.
It can't be, because the default promotions ensure that it will
always become an int.

--
<http://www.cs.auckland.ac.nz/~pgut001/pubs/vista_cost.txt>

"A man who is right every time is not likely to do very much."
-- Francis Crick, co-discover of DNA
"There is nothing more amazing than stupidity in action."
-- Thomas Matthews
Jan 23 '07 #24

P: n/a
CBFalconer <cb********@yahoo.comwrites:
Keith Thompson wrote:
... snip ...

Things would be more consistent if the "correct type" for "%hd"
were int rather than short.

It can't be, because the default promotions ensure that it will
always become an int.
Are you saying it can't be short, or it can't be int?

See also my article in comp.std.c, subject 'printf("%hd\n", 42);'.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Jan 23 '07 #25

P: n/a
On Jan 23, 12:56 pm, Keith Thompson <k...@mib.orgwrote:
"Old Wolf" <oldw...@inspire.net.nzwrites:
Yevgen Muntyan wrote:
So the following is a bug?
----------------------------
#include <stdio.h>
int main (void)
{
int a = 1<<30;
short b = a;
printf ("%d %hd %hd\n", a, a, b);
return 0;
}
----------------------------
It prints
1073741824 1073741824 0
i.e. it doesn't truncate 'a' (which of type int) when prints
it with %hd.
You caused undefined behaviour by not passing an argument of
type 'short int' to %hd
Interesting.

In the description of fprintf(), C99 7.19.6.1p7 says that the 'h'
modifier

Specifies that a following d, i, o, u, x, or X conversion
specifier applies to a short int or unsigned short int argument
(the argument will have been promoted according to the integer
promotions, but its value shall be converted to short int or
unsigned short int before printing);
[...]

and p9 says:

[...] If any argument is not the correct type for the
corresponding conversion specification, the behavior is undefined.

But is the "correct type" for "%hd" short, or is it int?
int.
If the correct type is short, then the following two calls:

printf("%hd\n", (short)42);
printf("%hd\n", 42);

can behave differently, and the latter invokes undefined behavior.
For any user-written variadic function that uses <stdarg.h>, the two
calls are identical; the "(short)42)" argument is promoted to int
before the call.

The standard doesn't say that printf() uses <stdarg.h>.
But it does specify the prototype which ends with the ellipsis
punctuator and the Standard specifies what happens to arguments passed
to such a function with a prototype in scope (specifically 6.5.2.2p7):
integer promotions are performed, regardless of whether printf is
implemented using stdarg.h or not, no two ways about it.
Conceivably
the compiler could treat printf() specially, but it would be difficult
(but not impossible) to do this for calls through a pointer, where the
compiler doesn't know whether it's calling printf() or an equivalent
user-defined variadic function.

Things would be more consistent if the "correct type" for "%hd" were
int rather than short.
I don't see how the parenthetical comment you cited from 7.19.6.1p7
leaves any room for doubt about this. Even if it could be argued that
it isn't crystal clear, it should be obvious that there is no way to
bypass the default argument promotions that occur in a call to a
variable-argument function regardless of how that function is
implemented, leaving no room for an alternate interpretation in the
first place.

Robert Gamble

Jan 24 '07 #26

P: n/a
Keith Thompson wrote:
CBFalconer <cb********@yahoo.comwrites:
>Keith Thompson wrote:

... snip ...
>>>
Things would be more consistent if the "correct type" for "%hd"
were int rather than short.

It can't be, because the default promotions ensure that it will
always become an int.

Are you saying it can't be short, or it can't be int?
Due to default promotion the actual parameter that the printf
routine receives will be an int if the parameter in the calling
routine is either an int or a short. Thus the %hd can't describe a
short, it can only describe special treatment for an int.

--
"The mere formulation of a problem is far more often essential
than its solution, which may be merely a matter of mathematical
or experimental skill. To raise new questions, new possibilities,
to regard old problems from a new angle requires creative
imagination and and marks real advances in science."
-- Albert Einstein
Jan 24 '07 #27

P: n/a
CBFalconer <cb********@yahoo.comwrites:
Keith Thompson wrote:
CBFalconer <cb********@yahoo.comwrites:
Keith Thompson wrote:

... snip ...

Things would be more consistent if the "correct type" for "%hd"
were int rather than short.

It can't be, because the default promotions ensure that it will
always become an int.
Are you saying it can't be short, or it can't be int?

Due to default promotion the actual parameter that the printf
routine receives will be an int if the parameter in the calling
routine is either an int or a short. Thus the %hd can't describe a
short, it can only describe special treatment for an int.
I like the conclusion, but I'm not convinced by the logic. The
required behavior of printf depends heavily on what the "correct type"
is for a given conversion specification. If the "correct type" for
"%hd" is supposed to be int, the standard should say so explicitly.

Given the current description, even assuming int is the "correct
type", the behavior of printf("%hd", SHRT_MAX+1) (assuming
INT_MAX SHRT_MAX) apears to be undefined by omission. That's
permitted, of course, but I'm not comfortable with it, and I don't
believe it was the intent.

See also the thread in comp.std.c.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Jan 24 '07 #28

P: n/a


On Jan 23, 2:02 am, "Old Wolf" <oldw...@inspire.net.nzwrote:
user923005 wrote:
Old Wolf wrote:
user923005 wrote:
Old Wolf wrote:
Is there any possible situation for printf where %hd causes a different
result to %d, and the corresponding argument was of type 'short int' ?
Think about the scanf() family of functions.
I'm asking about the printf() family.
Are you saying that there is no difference in printf, but they added
support for %hd just to try and keep the printf family similar to the
scanf family?
No. I am saying scanf() has to have it, while printf() could care
less.So you are saying it does make a difference to printf?
What difference?

Or do you mean "couldn't care less" ?
We could just as easily complain about:
12.9: Someone told me it was wrong to use %lf with printf(). How can
printf() use %f for type double, if scanf() requires %lf?Huh? I'm not complaining. I'm asking about printf (NOT scanf). You
brought scanf into this.
A: It's true that printf's %f specifier works with both float and
double arguments. Due to the "default argument promotions"
(which apply in variable-length argument lists such as
printf's, whether or not prototypes are in scope), values of
type float are promoted to double, and printf() therefore sees
only doubles. (printf() does accept %Lf, for long double.)
See also questions 12.13 and 15.2.This is irrelevant to my question. (If you don't know the answer then
just say so, or don't reply)- Hide quoted text -- Show quoted text -
Of course its relevant. The printf() function is varadic, which means
that it is literally impossible to pass a short (which will promote to
int) or a float (which will promote to double) before it gets to the
called function, by default argument promotions. That is why printf()
doesn't care. It literally *can't* care about it because it will never
get a short and it will always get an int.

If you specify %hd then (internally) the printf() function should do
this:
short short_value = (short) int_value;
before printing it (in my opinion).
Of course, if you actually passed a short, then it will not be
different.
On the other hand, if you did not pass a short then the behavior is
undefined.

If you pass in the int value 32000 or if you pass in the short value
32000 there is literally no way that printf() can tell which one of
those two things you did.

Jan 24 '07 #29

P: n/a
Keith Thompson <ks***@mib.orgwrote:
CBFalconer <cb********@yahoo.comwrites:
Keith Thompson wrote:
CBFalconer <cb********@yahoo.comwrites:
>Keith Thompson wrote:
>>
>>Things would be more consistent if the "correct type" for "%hd"
>>were int rather than short.
>>
>It can't be, because the default promotions ensure that it will
>always become an int.
>
Are you saying it can't be short, or it can't be int?
Due to default promotion the actual parameter that the printf
routine receives will be an int if the parameter in the calling
routine is either an int or a short. Thus the %hd can't describe a
short, it can only describe special treatment for an int.

I like the conclusion, but I'm not convinced by the logic. The
required behavior of printf depends heavily on what the "correct type"
is for a given conversion specification. If the "correct type" for
"%hd" is supposed to be int, the standard should say so explicitly.
It does:

# h Specifies that a following d, i, o, u, x,orX conversion specifier
# applies to a short int or unsigned short int argument (the argument
# will have been promoted according to the integer promotions, but
# its value shall be converted to short int or unsigned short int
# before printing);

That's 7.19.6.1#7 from n1124.pdf. Note parenthesis.

Richard
Jan 24 '07 #30

P: n/a

"Keith Thompson" <ks***@mib.orgwrote in message
news:ln************@nuthaus.mib.org...
>You're making it more complex than things are IMO.

I'm not; the standard is.
Thats what I mean, sometimes one doesnt need to read the standard to produce
code because that just complicates simple matters
Jan 24 '07 #31

P: n/a
On Jan 24, 10:52 am, r...@hoekstra-uitgeverij.nl (Richard Bos) wrote:
Keith Thompson <k...@mib.orgwrote:
CBFalconer <cbfalco...@yahoo.comwrites:
Keith Thompson wrote:
CBFalconer <cbfalco...@yahoo.comwrites:
Keith Thompson wrote:
>Things would be more consistent if the "correct type" for "%hd"
>were int rather than short.
It can't be, because the default promotions ensure that it will
always become an int.
Are you saying it can't be short, or it can't be int?
Due to default promotion the actual parameter that the printf
routine receives will be an int if the parameter in the calling
routine is either an int or a short. Thus the %hd can't describe a
short, it can only describe special treatment for an int.
I like the conclusion, but I'm not convinced by the logic. The
required behavior of printf depends heavily on what the "correct type"
is for a given conversion specification. If the "correct type" for
"%hd" is supposed to be int, the standard should say so explicitly.It does:

# h Specifies that a following d, i, o, u, x,orX conversion specifier
# applies to a short int or unsigned short int argument (the argument
# will have been promoted according to the integer promotions, but
# its value shall be converted to short int or unsigned short int
# before printing);

That's 7.19.6.1#7 from n1124.pdf. Note parenthesis.
After reading the comp.std.c thread I finally understand Keith's point.
The problem is with the wording stating that the argument must be a
short int or unsigned short int (which will obviously undergo
promotion) but it doesn't accommodate an argument that starts out as an
int. I think the intent is obvious, and at least one person from the
Committee has already confirmed this on the comp.std.c thread, but the
wording in the descriptions of this function and others (all of the
ctype.h functions have a similar issue, there are probably others)
should be changed to reflect this. For example, instead of saying
"applies to a short int or unsigned short int argument" it should say
"applies to an int or unsigned int argument after any applicable
promotions" which would also eliminate the need for the parenthetical
comment.

Robert Gamble

Jan 24 '07 #32

P: n/a
"Serve Laurijssen" <se*@n.tkwrites:
"Keith Thompson" <ks***@mib.orgwrote in message
news:ln************@nuthaus.mib.org...
You're making it more complex than things are IMO.
I'm not; the standard is.

Thats what I mean, sometimes one doesnt need to read the standard to
produce code because that just complicates simple matters
One *should* be able to read the standard to determine whether a given
piece of code is valid, and if so, what it does. I'm just pointing
out an instance where this doesn't necessarily work, due to a flaw in
the standard.

Ideally, if reading the standard "complicates simple matters", it's
likely because the matters really aren't as simple as you thought they
were.

Not all programmers *have* to read the standard, but you seem to be
arguing that they *shouldn't*. I may still be misunderstanding your
point. I strongly disagree with the point I *think* you're making.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Jan 24 '07 #33

P: n/a

"Keith Thompson" <ks***@mib.orgwrote in message
news:ln************@nuthaus.mib.org...
One *should* be able to read the standard to determine whether a given
piece of code is valid, and if so, what it does. I'm just pointing
out an instance where this doesn't necessarily work, due to a flaw in
the standard.

Ideally, if reading the standard "complicates simple matters", it's
likely because the matters really aren't as simple as you thought they
were.

Not all programmers *have* to read the standard, but you seem to be
arguing that they *shouldn't*. I may still be misunderstanding your
point. I strongly disagree with the point I *think* you're making.
Nah, it shouldnt have been in this particular case. The issue was clear 10
posts ago but then the standard was brought in and it goes on and on and on.
I know, it's some people's hobby (or work) here to know all the small
details and nitpick about them and yes, the standard's wording tries to take
care of everything so it gets naturally complex. Just leave it out when it's
not needed :)
Jan 24 '07 #34

P: n/a
"Serve Laurijssen" <se*@n.tkwrites:
"Keith Thompson" <ks***@mib.orgwrote in message
news:ln************@nuthaus.mib.org...
One *should* be able to read the standard to determine whether a given
piece of code is valid, and if so, what it does. I'm just pointing
out an instance where this doesn't necessarily work, due to a flaw in
the standard.

Ideally, if reading the standard "complicates simple matters", it's
likely because the matters really aren't as simple as you thought they
were.

Not all programmers *have* to read the standard, but you seem to be
arguing that they *shouldn't*. I may still be misunderstanding your
point. I strongly disagree with the point I *think* you're making.

Nah, it shouldnt have been in this particular case. The issue was clear 10
posts ago but then the standard was brought in and it goes on and on and on.
I know, it's some people's hobby (or work) here to know all the small
details and nitpick about them and yes, the standard's wording tries to take
care of everything so it gets naturally complex. Just leave it out when it's
not needed :)
Feel free not to participate in discussions that you find boring.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Jan 24 '07 #35

This discussion thread is closed

Replies have been disabled for this discussion.