473,399 Members | 3,038 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,399 software developers and data experts.

Printf question.

Hi,

I was wondering something today. The following code :

unsigned char a = 200;
char b = 200;
printf( "%d %d", a, b );

gives :

200, -56

How comes? I didn't tell printf that the first argument was unsigned
and it detected it on its own. It doesn't seem possible with varargs.
How is it possible?

Thanks,

Dec 30 '05 #1
15 1605
praeiji <sp*******@gmail.com> wrote:

unsigned char a = 200;
char b = 200;
printf( "%d %d", a, b );

gives :

200, -56

How comes? I didn't tell printf that the first argument was unsigned
and it detected it on its own. It doesn't seem possible with varargs.
How is it possible?


Both arguments get promoted to int before they are passed to printf()

_Ico

--
:wq
^X^Cy^K^X^C^C^C^C
Dec 30 '05 #2
Thanks,

But why are they typecasted to int? Does it come from gcc when it sees
"%d" and the printf function?

Dec 30 '05 #3

praeiji wrote:
Hi,

I was wondering something today. The following code :

unsigned char a = 200;
char b = 200;
printf( "%d %d", a, b );

gives :

200, -56

How comes? I didn't tell printf that the first argument was unsigned
and it detected it on its own. It doesn't seem possible with varargs.
How is it possible?

Thanks,


Conversion Argument Converted Default Pre-
Specifier Type Value Base cision
%d int x (int)x 10 1

That means %d formats int. If you give it char and unsigned char it
will convert them to int.

Dec 30 '05 #4
On 30 Dec 2005 11:21:25 -0800, "praeiji" <sp*******@gmail.com> wrote
in comp.lang.c:
Hi,

I was wondering something today. The following code :

unsigned char a = 200;
char b = 200;
printf( "%d %d", a, b );

gives :

200, -56

How comes? I didn't tell printf that the first argument was unsigned
and it detected it on its own. It doesn't seem possible with varargs.
How is it possible?

Thanks,


This has nothing to do with printf(), per se. It does not know the
difference between the original objects providing the values.

What you are seeing is the result of what the C standard calls the
"default argument promotions". These occur when calling a function
without a prototype in scope, or for the "..." arguments in a variadic
function.

In the case of integer types of lesser rank than int, the "integer
promotions" occur. Since a signed int can hold the value 200, the
value in the unsigned char 'a' is converted to the int value 200.

On your particular system, chars have 8 bits and 'plain' char is
signed. The binary representation of 200 in an 8-bit byte happens to
be the same as the 8-bit 2's complement representation of -56, and
that is the implementation-defined result of assigning the
out-of-range value to a signed 'plain' char.

The integer promotions take the 'plain' char value of -56 and convert
it to an int value of -56.

So the values of 200 and -56 are generated during argument evaluation,
before printf() is called.

On some platforms, char has more than 8 bits, and 200 would remain 200
in a 'plain' char or signed char. On some platforms, 'plain' char is
unsigned, not signed. On platforms with either of these
characteristics, the output would be "200, 200".

And on some platforms, the output would not appear at all because you
did not add a final '\n'.

--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://c-faq.com/
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.learn.c-c++
http://www.contrib.andrew.cmu.edu/~a...FAQ-acllc.html
Dec 30 '05 #5
thank you :)

Silly me, I'd never heard of the "integer promotions" before.

Dec 30 '05 #6
praeiji <sp*******@gmail.com> wrote:
But why are they typecasted to int? Does it come from gcc when it sees
"%d" and the printf function?


No, they are not typecasted, but `promoted', which is not the same thing.
Promotion is what happens when you call a function that has no prototype, or
when a function with a variable number (variadic) of arguments like printf()
is called. With promotion, all arguments are converted to a generic 'bigger'
type: char and short to int, float to double.

Ico

--
:wq
^X^Cy^K^X^C^C^C^C
Dec 30 '05 #7
Jack Klein <ja*******@spamcop.net> writes:
On 30 Dec 2005 11:21:25 -0800, "praeiji" <sp*******@gmail.com> wrote
in comp.lang.c: [...]
unsigned char a = 200;
char b = 200;
printf( "%d %d", a, b );

gives :

200, -56

How comes? I didn't tell printf that the first argument was unsigned
and it detected it on its own. It doesn't seem possible with varargs.
How is it possible?

[snip]
In the case of integer types of lesser rank than int, the "integer
promotions" occur. Since a signed int can hold the value 200, the
value in the unsigned char 'a' is converted to the int value 200.


Correction: since a signed int can hold any value of type unsigned
char, the value in the unsigned char 'a' is promoted to type int. The
promoted type doesn't depend on the value that happens to be in the
variable; it depends on which type can hold *any* possible value of
the type.

--
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.
Dec 30 '05 #8
Keith Thompson wrote:
Jack Klein <ja*******@spamcop.net> writes:
On 30 Dec 2005 11:21:25 -0800, "praeiji" <sp*******@gmail.com> wrote
in comp.lang.c: [...]
unsigned char a = 200;
char b = 200;
printf( "%d %d", a, b );

gives :

200, -56

How comes? I didn't tell printf that the first argument was unsigned
and it detected it on its own. It doesn't seem possible with varargs.
How is it possible?

[snip]
In the case of integer types of lesser rank than int, the "integer
promotions" occur. Since a signed int can hold the value 200, the
value in the unsigned char 'a' is converted to the int value 200.


Correction: since a signed int can hold any value of type unsigned
char, the value in the unsigned char 'a' is promoted to type int.


<annoying pedant>
What, even on a system with CHAR_BIT==16 and sizeof(int)==1 ?
</annoying pedant>

Of course, you are only likely to find such systems in the embedded
world where you may well not have printf.
The
promoted type doesn't depend on the value that happens to be in the
variable; it depends on which type can hold *any* possible value of
the type.


You are, of course, correct that is is purely a matter of type, not the
value the variable happens to contain.
--
Flash Gordon
Living in interesting times.
Although my email address says spam, it is real and I read it.
Dec 30 '05 #9
us****@zevv.nl wrote:

praeiji <sp*******@gmail.com> wrote:
But why are they typecasted to int? Does it come from gcc when it sees
"%d" and the printf function?


No, they are not typecasted, but `promoted', which is not the same thing.
Promotion is what happens when you call a function that has no prototype, or
when a function with a variable number (variadic) of arguments like printf()
is called. With promotion, all arguments are converted to a generic 'bigger'
type: char and short to int, float to double.

Type promotion can also happen when you do mixed mode arithmetic.

--
+----------------------------------------------------------------+
| Charles and Francis Richmond richmond at plano dot net |
+----------------------------------------------------------------+
Dec 31 '05 #10
On Fri, 30 Dec 2005 20:56:02 GMT, Keith Thompson <ks***@mib.org> wrote
in comp.lang.c:
Jack Klein <ja*******@spamcop.net> writes:
On 30 Dec 2005 11:21:25 -0800, "praeiji" <sp*******@gmail.com> wrote
in comp.lang.c:

[...]
unsigned char a = 200;
char b = 200;
printf( "%d %d", a, b );

gives :

200, -56

How comes? I didn't tell printf that the first argument was unsigned
and it detected it on its own. It doesn't seem possible with varargs.
How is it possible?

[snip]
In the case of integer types of lesser rank than int, the "integer
promotions" occur. Since a signed int can hold the value 200, the
value in the unsigned char 'a' is converted to the int value 200.


Correction: since a signed int can hold any value of type unsigned
char, the value in the unsigned char 'a' is promoted to type int. The
promoted type doesn't depend on the value that happens to be in the
variable; it depends on which type can hold *any* possible value of
the type.


Yes, thanks.

--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://c-faq.com/
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.learn.c-c++
http://www.contrib.andrew.cmu.edu/~a...FAQ-acllc.html
Dec 31 '05 #11
"Flash Gordon" <sp**@flash-gordon.me.uk> wrote
Correction: since a signed int can hold any value of type unsigned
char, the value in the unsigned char 'a' is promoted to type int.


<annoying pedant>
What, even on a system with CHAR_BIT==16 and sizeof(int)==1 ?
</annoying pedant>

Of course, you are only likely to find such systems in the embedded world
where you may well not have printf.

But often you have vsprintf(), or you need to implement it.

The whole language does begin to break down when we push the limits of
ANSI's definition. For instance, should field-length parameters really be
size_t s?

Dec 31 '05 #12
Charles Richmond wrote:
us****@zevv.nl wrote:
praeiji <sp*******@gmail.com> wrote:

But why are they typecasted to int? Does it come from gcc when it sees
"%d" and the printf function?


No, they are not typecasted, but `promoted', which is not the same thing.
Promotion is what happens when you call a function that has no prototype, or
when a function with a variable number (variadic) of arguments like printf()
is called. With promotion, all arguments are converted to a generic 'bigger'
type: char and short to int, float to double.


Type promotion can also happen when you do mixed mode arithmetic.


Or even unmixed-mode arithmetic:

short x = 1, y = 2;
short z = x + y; /* see the "int"? */

--
Eric Sosman
es*****@acm-dot-org.invalid
Dec 31 '05 #13
On 2005-12-31, Malcolm <re*******@btinternet.com> wrote:
"Flash Gordon" <sp**@flash-gordon.me.uk> wrote
Correction: since a signed int can hold any value of type unsigned
char, the value in the unsigned char 'a' is promoted to type int.


<annoying pedant>
What, even on a system with CHAR_BIT==16 and sizeof(int)==1 ?
</annoying pedant>

Of course, you are only likely to find such systems in the embedded world
where you may well not have printf.

But often you have vsprintf(), or you need to implement it.

The whole language does begin to break down when we push the limits of
ANSI's definition. For instance, should field-length parameters really be
size_t s?


You could take the cheap way out and do stuff along the lines of

sprintf(format,"%%%d.%df",width,precision>=0?preci sion:0);

c89 doesn't appear to provide for field-length parameters anyway - at
least the draft i have doesn't.
Dec 31 '05 #14


praeiji dropped $.02 in the slot and wrote:
Hi,

I was wondering something today. The following code :

unsigned char a = 200;
char b = 200;
printf( "%d %d", a, b );

gives :

200, -56

How comes? I didn't tell printf that the first argument was unsigned
and it detected it on its own. It doesn't seem possible with varargs.
How is it possible?


That would happen if plain char on your machine is signed and char is
eight bits wide. The assignment b = 200 makes b -56.

Roger.
Jan 2 '06 #15
Bliss wrote:
praeiji dropped $.02 in the slot and wrote:
Hi,

I was wondering something today. The following code :

unsigned char a = 200;
char b = 200;
printf( "%d %d", a, b );

gives :

200, -56

How comes? I didn't tell printf that the first argument was
unsigned and it detected it on its own. It doesn't seem
possible with varargs. How is it possible?


That would happen if plain char on your machine is signed and
char is eight bits wide. The assignment b = 200 makes b -56.


Your conditions are necessary, but not strictly sufficient to make b
receive the value of -56.

As the value 200 is outside the range of an 8-bit signed
plain char, the conversion is implementation defined.[*]
Even adding the condition that signed char has twos
complement representation is not sufficient to force a
value of -56 for b since an implementation is still
entitled to assign say 0 in such cases, if it chooses.

You can say it likely yielded -56 because most implementations
are two's complement and preserve the bitwise representation
(albeit with trunction or sign extension) when performing
conversions of an integer value which is outside the range of
the target type.
[*] C99 adds the possibility of an implementation defined signal.

--
Peter

Jan 2 '06 #16

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

Similar topics

9
by: Wenjie | last post by:
Hello, Is printf("%d", var); OK for the unsigned long var = SOME_VAR? Or should some other print format be specified? Thanks and best regards, Wenjie
14
by: Mantorok Redgormor | last post by:
Would this by any chance invoke undefined behavior? extern int printf(const char *, ...); int main(void) { printf("Hello\n"); return 0; } That is, providing my own printf prototype would...
188
by: infobahn | last post by:
printf("%p\n", (void *)0); /* UB, or not? Please explain your answer. */
31
by: DeltaOne | last post by:
#include<stdio.h> typedef struct test{ int i; int j; }test; main(){ test var; var.i=10; var.j=20;
12
by: John Devereux | last post by:
Hi, I would like to know if their is a conversion specifier, or other method, that will allow me to not use particular arguments to printf. Failing that, is it permissable to simply "not use"...
11
by: rahul8143 | last post by:
Does printf output depends on compilers or operating systems? I have one program int main() { int i=5; printf("%d %d %d",i++,i++,i++); return 0; } Output of this program on DOS (TC) 7 6 5...
27
by: jacob navia | last post by:
Has anyone here any information about how arrays can be formatted with printf? I mean something besides the usual formatting of each element in a loop. I remember that Trio printf had some...
7
by: Martin Jørgensen | last post by:
Hi, Perhaps a stupid question but I wonder if this isn't possible using C: printf("\nOr push <enter> for default (which is theta=%ld)%s", theta, ": "); It would be nicer to have it on one...
5
by: Why Tea | last post by:
int printf(const char *fmt,...) The fmt is const, indicating that it can't be changed during runtime. If I want to print a series of integers that I only know the largest value beforehand,...
7
by: Rajesh S R | last post by:
printf("%hhd",89);/*Assume char has 8 bits and is signed*/ Is it valid? I know that it has been discussed in comp.std.c. ...
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:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
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
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
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
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...

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.