printf and cout

L

laikon

Hello, everyone:

this is about overflow in C and C++.


int c = 400;
printf("%c", c);


it print ? on screen, and ascii of '?' is 63.


but
cout << int(char(400));


it print -112 on screen.


so, my question is why comes 63 and -112, what relations between
them,
why printf and cout behavior so differently.


both tests are in VC2005.


thanks a lot.
 
B

Bernhard Schauer

int c = 400;
printf("%c", c);

it print ? on screen, and ascii of '?' is 63.

but
cout << int(char(400));

it print -112 on screen.

so, my question is why comes 63 and -112, what relations between them,
why printf and cout behavior so differently.

Hi!

both values are the same, except that the '?' is not meant as the
character '?' but as an unprintable character. It also "looks" different
than a normal '?'.
As Richard Heathfield posted in comp.lang.c try to dump the output to a file
and inspect it using some kind of hexdump/hexedit.

regards
 
L

laikon

Hi!

both values are the same, except that the '?' is not meant as the
character '?' but as an unprintable character. It also "looks" different
than a normal '?'.
As Richard Heathfield posted in comp.lang.c try to dump the output to a file
and inspect it using some kind of hexdump/hexedit.

regards

thanks.

I just know it:

Just as you say, '?' does not mean to be the result of the overflow,
but a symbol of unknown ascii character. when a number overflows by
char, and the left binary is negate, the printf will print '?'.
 
P

Pascal J. Bourguignon

laikon said:
Hello, everyone:

this is about overflow in C and C++.


int c = 400;
printf("%c", c);


it print ? on screen, and ascii of '?' is 63.

That would depend on the locale, on what character encoding is used by
your terminal.

Usually C char are one octet. So when you want to treat 400 as a char,
you get 400 % 256, which is 144. But 144 is not an ASCII code, and
neither the code of an ISO-8859-1 character (and therefore neither the
code of an Unicode character). It's a control code : DCS, Device
Control String. Your terminal doesn't interpret this control code, as
such, and prints its perplexity in the form of a question mark. You'd
do the same.

but
cout << int(char(400));


it print -112 on screen.

Looks like your chars are signed chars.
400 % 256 == 144 % 256 == -112 % 256

so, my question is why comes 63 and -112, what relations between
them,
why printf and cout behavior so differently.

Well they're not the same, one is a C function, the other is a C++
object. But the point is that they don't get a chance to do the same
anyways. You give the integer 400 to print, and you give the integer
-112 to cout. Try:

::printf("%d\n",int(char(400)));
cout<<int(char(400))<<endl;

and then:

::printf("%c\n",char(400));
cout<<char(400)<<endl;

and there of course, you get different results because of the way
cout handles characters, that is, as integers, but that's another
story. You could try:

char str[2];str[0]=char(400);str[1]=0;
::printf("%s\n",cstr);
cout<<cstr<<endl;
 
J

James Kanze

That would depend on the locale, on what character encoding is used by
your terminal.
Usually C char are one octet. So when you want to treat 400 as a char,
you get 400 % 256, which is 144. But 144 is not an ASCII code, and
neither the code of an ISO-8859-1 character (and therefore neither the
code of an Unicode character). It's a control code : DCS, Device
Control String. Your terminal doesn't interpret this control code, as
such, and prints its perplexity in the form of a question mark. You'd
do the same.



Looks like your chars are signed chars.
400 % 256 == 144 % 256 == -112 % 256
Well they're not the same, one is a C function, the other is a C++
object. But the point is that they don't get a chance to do the same
anyways. You give the integer 400 to print, and you give the integer
-112 to cout.

More to the point, he told printf to convert the integer to a
char, and attempt to print that. In C++, he told the system to
convert the integer to a char, and then print integral value of
that char.
Try:

and then:

and there of course, you get different results because of the
way cout handles characters,

I'm not sure of that, although there's really no guarantee about
much at this level. Typically, though, unless you've been
playing games with locales, you should get the same thing.
 
P

Paul Brettschneider

laikon said:
Hello, everyone:

this is about overflow in C and C++.


int c = 400;
printf("%c", c);


it print ? on screen, and ascii of '?' is 63.


but
cout << int(char(400));


it print -112 on screen.

These two things are not the same at all.
The printf version should read like this:

#include <cstdio>

int main()
{
int c = 400;
printf("%d", (char)400);
}

And, not surprisingly, it prints -112 too (on a 2s complement machine).
 
J

James Kanze

These two things are not the same at all.
The printf version should read like this:
#include <cstdio>
int main()
{
int c = 400;
printf("%d", (char)400);
}
And, not surprisingly, it prints -112 too (on a 2s complement machine).

On a 2's complement machine with 8 bit bytes, where plain char
is signed. Exceptions to the first two conditions are fairly
rare today. But unsigned plain char is an option with a lot of
compilers, and the default on some as well (and would make life
a lot easier if you could count on it).
 
R

Ron Natalie

laikon said:
Hello, everyone:

this is about overflow in C and C++.


int c = 400;
printf("%c", c);


it print ? on screen, and ascii of '?' is 63.

Printf %c changes the int value passed to unsigned char and then
prints that. The int to unsigned conversion wraps around 2**Number of
bits in char (256 most likely)
but
cout << int(char(400));


it print -112 on screen.
Because you convert to int rather than unsignec char.
both tests are in VC2005.
Should be the same in any conforming compiler with 8 bit chars.
 
R

Ron Natalie

Pascal said:
Looks like your chars are signed chars.
400 % 256 == 144 % 256 == -112 % 256
Doesn't matter if his chars are signed or not,
the C STANDARD specifically says the %c formatter
converts to unsigned char.
 
A

Alexander Dong Back Kim

Hello, everyone:

this is about overflow in C and C++.

int c = 400;
printf("%c", c);

it print ? on screen, and ascii of '?' is 63.

but
cout << int(char(400));

it print -112 on screen.

so, my question is why comes 63 and -112, what relations between
them,
why printf and cout behavior so differently.

both tests are in VC2005.

thanks a lot.

do sizeof(int) and sizeof(char)

How large number 1 byte data type can handle?

cheers,
 
N

Nick Keighley

do sizeof(int) and sizeof(char)

How large number 1 byte data type can handle?

is this related to the previous discussion?
I don't actually understand what you mean.
Do you mean
"how can we handle large numbers of 1 byte objects?"
"what is the largest value int (or char) we can handle?"
"how many 1 byte objects can we ahndle?"?

sizeof(char) == 1 by definition even if an odd machine
has 32 bit bytes (I understand some DSPs do this)
the sizeof(char) is *still* 1 (counter intuitive but true).

A char must be a least 8-bits.

sizeof(int) >= sizeof(char)

and an int must be at least 16-bits (the standard
doesn't quite say this straight out but it boils
down to this.

Note
in C
sizeof('a') == sizeof(int)

and in C++
sizeof('a') == sizeof(char)
 
J

James Kanze

laikon wrote:
Printf %c changes the int value passed to unsigned char and
then prints that. The int to unsigned conversion wraps around
2**Number of bits in char (256 most likely)
Because you convert to int rather than unsignec char.
Should be the same in any conforming compiler with 8 bit chars.

Not for the C++ case. In fact, compiling with the /J (plain
char is unsigned) option should change the output.
 
P

Paul Brettschneider

James said:
On a 2's complement machine with 8 bit bytes, where plain char
is signed. Exceptions to the first two conditions are fairly
rare today. But unsigned plain char is an option with a lot of
compilers, and the default on some as well (and would make life
a lot easier if you could count on it).

Some hardware might be optimised for signed chars and other hardware for
unsigned chars (I think this is the reason that Linux/PPC defaults to
unsigned whereas Linux/x86 traditionally uses signed).
 
J

James Kanze

James Kanze wrote:

[...]
Some hardware might be optimised for signed chars and other hardware for
unsigned chars (I think this is the reason that Linux/PPC defaults to
unsigned whereas Linux/x86 traditionally uses signed).

That was the original motivation. The first two machines to
support C were the PDP-11 and the Interdata 8/32. On the first,
making char unsigned would have had a significant performance
penalty, and on the second, making it signed would have slowed
things down. And at the time, only US ASCII mattered, so even
signed, all of the encodings actually being used were positive,
and it didn't seem to make a difference.

Today, of course, most machines support either equally well, and
seven bit ASCII has been almost universally superceded by eight
bit codes: ISO 8859-n or UTF-8 (or some propriatary code pages
in console windows under Windows---probably for historical
reasons). But of course, most implementations continue to make
plain char signed, because that's the way it was on a PDP-11,
code was written which counted on it (although K&R warned from
the very beginning not to), and implementors don't want to risk
breaking it.

The result is, of course, that something like:

std::transform( s.begin(), s.end(),
s.begin(),
::tolower ) ;

results in undefined behavior.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,770
Messages
2,569,584
Members
45,075
Latest member
MakersCBDBloodSupport

Latest Threads

Top