C doubt

S

sangeeta chowdhary

#include<stdio.h>
#include<string.h>

int main()
{
unsigned char i=0x80;
printf("%d %d\n",i<<1,sizeof(unsigned char));
return 0;
}

output of this code is 256 1

binary conversion of i is 10000000
now if shift it to left by 1,then ishould get zero,as there is only 8
bits available for i.
why i am getting 256.
range of unsigned char is from 0 to +255
Reply
 
T

Tom St Denis

#include<stdio.h>
#include<string.h>

int main()
{
 unsigned char i=0x80;
 printf("%d %d\n",i<<1,sizeof(unsigned char));
 return 0;

}

output of this code is   256 1

binary conversion of i is 10000000
now if shift it to left by 1,then ishould get zero,as there is only 8
bits available for i.
why i am getting 256.
range of unsigned char is from 0 to +255

Two things, first, use more descriptive subject lines (are you
actually retarded?), and second you really really really need to read
a good C language textbook.

The parameter "i<<1" is promoted as it's passed as a parameter to the
function so the compiler computes it as (int)i << 1. If you really
wanted a byte operation you should have passed (i << 1) & 0xFF.

Tom
 
D

Denis McMahon

why i am getting 256.

This has been explained to you before.

What data type does %d expect? What does this do to your char?

While you're at it, what data type does sizeof() return?

If you do not match your printf format specifiers to your data types,
stop being surprised that you get unexpected results.

Rgds

Denis McMahon
 
S

sangeeta chowdhary

Two things, first, use more descriptive subject lines (are you
actually retarded?), and second you really really really need to read
a good C language textbook.

The parameter "i<<1" is promoted as it's passed as a parameter to the
function so the compiler computes it as (int)i << 1.  If you really
wanted a byte operation you should have passed (i << 1) & 0xFF.

Tom

Retarted???
Really?
You should read my problem carefully and if you can't then please
leave it.
 
S

sangeeta chowdhary

This has been explained to you before.

What data type does %d expect? What does this do to your char?

While you're at it, what data type does sizeof() return?

If you do not match your printf format specifiers to your data types,
stop being surprised that you get unexpected results.

Rgds

Denis McMahon

Thanks a lot. Sorry for discussing a stupid problem.
 
E

Eric Sosman

#include<stdio.h>
#include<string.h>

int main()
{
unsigned char i=0x80;
printf("%d %d\n",i<<1,sizeof(unsigned char));
return 0;
}

output of this code is 256 1

binary conversion of i is 10000000
now if shift it to left by 1,then ishould get zero,as there is only 8
bits available for i.
why i am getting 256.
range of unsigned char is from 0 to +255
Reply

Again? Wasn't this exact same question asked and answered
just a few days ago? In fact, wasn't it asked *by you* just a
few days ago?

Okay, okay, maybe not. Most of C's arithmetic operators
carry out the "integer promotions" on their operands before they
actually operate on them. This is because most computers cannot
actually do arithmetic on narrow integers: They do something like
load the narrow value into a CPU register (widening it in the
process) and then operate on the widened value. So, when you
write `i << 1' the first thing that happens is that `i' is
promoted to an `int' (on some weird machines the promotion may
be to `unsigned int', but that's not likely here). After the
promotion, you've got an `int' with the value 128; you shift this
left one bit position and have an `int' with the value 256, and
that's the value you hand to printf().

I cannot imagine a C textbook or reference that would fail
to explain this to anyone who bothered to read it. Hint.
 
B

Ben Bacarisse

Denis McMahon said:
On 13/07/10 12:40, sangeeta chowdhary wrote:
[Restoring code that has got snipped:]

| unsigned char i=0x80;
| printf("%d %d\n",i<<1,sizeof(unsigned char));
This has been explained to you before.

I thought so too, but then I went to look and now I don't think it was.
Yes, the same post appeared on Jul 6th and it would have been better for
the OP to follow up on that thread, maybe by explaining why they still
needed more explanation, but the question was not really answered.

Of the two replies that addressed the content of the question, one asked
a set of questions intended to get the OP to think it through and the
other took a more direct route. However, both fell into the trap (that
I did not see at the time) of talking about the type of i << 1 (one
asking what it is and the other stating that it is probably int).

If you think about it from the point of view of someone not familiar
with C, this does not help. If << were to act as the OP seems to
expect, the result could still be converted to int *afterwards* (maybe
because of passing it to a variadic function, maybe just because of some
odd rules about expressions) and the result would still be the
"expected" zero. The real answers is that << promotes its operands:
i.e. 'i' is converted to int *before* the shift. Yes, the result type
is also int, but that is not enough to explain the result.

Now I doubt that this is the real problem (I suspect the OP just wants
the answer to some coursework) but it seems worth pointing out that the
question was not really answered the first time round.
What data type does %d expect? What does this do to your char?

This answer confuses *me*! Are you saying the format governs the type
that gets passed? By the time %d comes into it, there is not a char in
sight.

<snip>
 
B

Ben Bacarisse

Thanks a lot. Sorry for discussing a stupid problem.

Can you explain how the answer helped you with your question? As you'll
see from another reply, this answer confused me. I don't see how the
format comes into it at all.
 
B

Ben Bacarisse

Eric Sosman said:
Again? Wasn't this exact same question asked and answered
just a few days ago? In fact, wasn't it asked *by you* just a
few days ago?

Yes, but the question was not really answered. I failed to notice that
at the time -- I saw a reply about types and thought "answered" without
thinking it through.
Okay, okay, maybe not. Most of C's arithmetic operators
carry out the "integer promotions" on their operands before they
actually operate on them.

This key point was not mentioned the last time round.

<snip>
 
S

sangeeta chowdhary

     Again?  Wasn't this exact same question asked and answered
just a few days ago?  In fact, wasn't it asked *by you* just a
few days ago?

     Okay, okay, maybe not.  Most of C's arithmetic operators
carry out the "integer promotions" on their operands before they
actually operate on them.  This is because most computers cannot
actually do arithmetic on narrow integers: They do something like
load the narrow value into a CPU register (widening it in the
process) and then operate on the widened value.  So, when you
write `i << 1' the first thing that happens is that `i' is
promoted to an `int' (on some weird machines the promotion may
be to `unsigned int', but that's not likely here).  After the
promotion, you've got an `int' with the value 128; you shift this
left one bit position and have an `int' with the value 256, and
that's the value you hand to printf().

     I cannot imagine a C textbook or reference that would fail
to explain this to anyone who bothered to read it.  Hint.

Ya you are right , i am again asking this problem because due to some
reason, my post was not displayed.
Thanks a lot for replying me again.
 
K

Keith Thompson

Tom St Denis said:
Two things, first, use more descriptive subject lines (are you
actually retarded?), and second you really really really need to read
a good C language textbook.

Tom, please keep the childish insults to yourself.

sangeeta, in spite of that, Tom has some valid points. You really
do need to use more descriptive subject lines that give us some
idea what you're asking about, and you really would benefit from
a good C language textbook.
The parameter "i<<1" is promoted as it's passed as a parameter to the
function so the compiler computes it as (int)i << 1. If you really
wanted a byte operation you should have passed (i << 1) & 0xFF.

That's a remarkably high density of mistakes, Tom (a snarky comment
I wouldn't have made if you hadn't chosen to be insulting).

The *argument* is promoted because it's passed to a variadic
function. The promotion occurs after the evaluation of the
argument expression, so it would be equivalent to (int)(i<<1), not
(int)i<<1. Saying that (i << 1) & 0xFF gives you a byte assumes
that CHAR_BIT==8, which is very likely but not guaranteed.

But as others have pointed out, argument promotion is largely
irrelevant here. The integer promotions are applied to the operands
of the "<<" operator, so i is promoted from unsigned char to int
[*] before it's shifted, which explains the observed behavior.

Some comments on the original code:

| #include<stdio.h>
| #include<string.h>

Style point: This would be more readable as:

#include <stdio.h>
#include <string.h>

| int main()

Better: "int main(void)" (though that's unlikely to cause any real
problems).

| {
| unsigned char i=0x80;
| printf("%d %d\n",i<<1,sizeof(unsigned char));

Style point: Judicuous use of whitespace can make code more
readable:

printf("%d %d\n", i << 1, sizeof(unsigned char));

sizeof yields a result of type size_t; "%d" requires an int argument.
In C99, you can write:

printf("%d %zu\n", i<<1, sizeof(unsigned char));

In C90:

printf("%d %lu\n", i<<1, (unsigned long)sizeof(unsigned char));

Or you could just write:

printf("%d 1\n", i<<1);

since sizeof(unsigned char) is 1 by definition.

| return 0;
|
| }

[*] If UCHAR_MAX > INT_MAX, i will be promoted to unsigned int, not int.
This can happen only on exotic systems where CHAR_BIT >= 16.
 
K

Kenny McCormack

actually retarded?), and second you really really really need to read
a good C language textbook.

Tom, please keep the childish insults to yourself.[/QUOTE]

Yes, Tom. Leader Kiki has spoken. All bow down.
 
S

sangeeta chowdhary

Tom, please keep the childish insults to yourself.

sangeeta, in spite of that, Tom has some valid points.  You really
do need to use more descriptive subject lines that give us some
idea what you're asking about, and you really would benefit from
a good C language textbook.

Thank you so much sir,I am just a beginner that's why making these
mistakes.But yes
I will definitely keep you valuable comments to my mind and will try
to improve.
The parameter "i<<1" is promoted as it's passed as a parameter to the
function so the compiler computes it as (int)i << 1.  If you really
wanted a byte operation you should have passed (i << 1) & 0xFF.

That's a remarkably high density of mistakes, Tom (a snarky comment
I wouldn't have made if you hadn't chosen to be insulting).

The *argument* is promoted because it's passed to a variadic
function.  The promotion occurs after the evaluation of the
argument expression, so it would be equivalent to (int)(i<<1), not
(int)i<<1.  Saying that (i << 1) & 0xFF gives you a byte assumes
that CHAR_BIT==8, which is very likely but not guaranteed.

But as others have pointed out, argument promotion is largely
irrelevant here.  The integer promotions are applied to the operands
of the "<<" operator, so i is promoted from unsigned char to int
[*] before it's shifted, which explains the observed behavior.

Some comments on the original code:

| #include<stdio.h>
| #include<string.h>

Style point: This would be more readable as:

#include <stdio.h>
#include <string.h>

| int main()

Better: "int main(void)" (though that's unlikely to cause any real
problems).

| {
|  unsigned char i=0x80;
|  printf("%d %d\n",i<<1,sizeof(unsigned char));

Style point: Judicuous use of whitespace can make code more
readable:

printf("%d %d\n", i << 1, sizeof(unsigned char));

sizeof yields a result of type size_t; "%d" requires an int argument.
In C99, you can write:

printf("%d %zu\n", i<<1, sizeof(unsigned char));

In C90:

printf("%d %lu\n", i<<1, (unsigned long)sizeof(unsigned char));

Or you could just write:

printf("%d 1\n", i<<1);

since sizeof(unsigned char) is 1 by definition.

|  return 0;
|
| }

[*] If UCHAR_MAX > INT_MAX, i will be promoted to unsigned int, not int.
This can happen only on exotic systems where CHAR_BIT >= 16.

--
Keith Thompson (The_Other_Keith) (e-mail address removed)  <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"
 
K

Keith Thompson

sangeeta chowdhary said:
Thank you so much sir,I am just a beginner that's why making these
mistakes.But yes
I will definitely keep you valuable comments to my mind and will try
to improve.
[70 lines deleted]

Another suggestion: it's usually not necessary to quote the entire
article to which you're replying. Delete any quoted material that's
not relevant to your followup. In particular, don't quote signatures
(the text at the end following the "-- " delimiter) unless you're
actually commenting on them.

See what I've done here, for example.
 
D

Denis McMahon

This answer confuses *me*! Are you saying the format governs the type
that gets passed? By the time %d comes into it, there is not a char in
sight.

I'm not an expert on the inner workings of printf, but over the 20+
years that I've been using C I have noticed that unless my format
specifiers match the data types that I'm passing to it, and vice versa,
I can get unexpected results.

Nowadays, if I get unexpected results in a printf, one of the first
things I check is that my format specifiers and data types match.

Rgds

Denis McMahon
 
K

Keith Thompson

Denis McMahon said:
I'm not an expert on the inner workings of printf, but over the 20+
years that I've been using C I have noticed that unless my format
specifiers match the data types that I'm passing to it, and vice versa,
I can get unexpected results.

Nowadays, if I get unexpected results in a printf, one of the first
things I check is that my format specifiers and data types match.

Of course the format has to match the type of the argument that's
passed. (The meaning of "match" can be a big vague in some cases,
but not in this one.) The question in this case is, what's the
type of the argument?

In the original code, as I recall, i was an object of type unsigned
char, and the expression i<<1 was passed as an argument corresponding
to a "%d" format. The operand ``i'' is promoted from unsigned
char to int *by the "<<" operator*, before the shift operation is
executed and certainly before the "%d" format becomes relevant.
i<<1 yields a result of type int, not of type unsigned char,
regardless of the context in which it appears.

(Unless UCHAR_MAX > INT_MAX, in which case it's of type unsigned
int, but that's only possible if CHAR_BIT >= 16 and some additional
conditions apply.)

You wrote:

What data type does %d expect? What does this do to your char?

And the answers are:

"%d" expects int, which is exactly what's being passed to it.
It doesn't do anything to the char (or the unsigned char) because
printf never sees an argument of any character type.

So your response was misleading; the argument already matched the
format specifier.

Note that even without the "<<" operator, something similar would
happen, though for different reasons. Given:

unsigned char i;
printf("%d\n", i);

the argument i is promoted from unsigned char to int (or possibly
to unsigned int on a sufficiently exotic system). But this time it's
not because of the "integer promotions" implied by the "<<" operator,
but by the "default argument promotions" implied by the fact that
printf is a variadic function, and the argument corresponds to the
"..." rather than to a declared parameter.

(C tends to like promoting narrow integer expressions to int or to
unsigned int. There are several different rules that cause these
promotions to happen in different contexts.)
 
B

Ben Bacarisse

Denis McMahon said:
I'm not an expert on the inner workings of printf, but over the 20+
years that I've been using C I have noticed that unless my format
specifiers match the data types that I'm passing to it, and vice versa,
I can get unexpected results.

Nowadays, if I get unexpected results in a printf, one of the first
things I check is that my format specifiers and data types match.

Yes, they must match, but they do in this specific case.
 
D

Denis McMahon

Yes, they must match, but they do in this specific case.

No they didn't, at least not in the original code, or rather, the
original was doing an implicit char to int cast, which meant that what
the OP thought was an operation on an 8 bit char was (probably) actually
taking place on a 32 bit int.

Consider:

char i = 0x80;
printf("%d",i<<1);

The << operator takes two ints and returns an int, so before the <<
operation takes place, i is implicitly cast to an int.

Next, the integer value 0x80 is shifted left 1 bit to 0x100;

Finally, printf is taking the integer value 0x100 (or binary 0000 0000
0000 0000 0000 0001 0000 0000) and displaying it as a decimal number, 256.

Rgds

Denis McMahon
 
B

Ben Bacarisse

Denis McMahon said:
No they didn't, at least not in the original code, or rather, the
original was doing an implicit char to int cast, which meant that what
the OP thought was an operation on an 8 bit char was (probably) actually
taking place on a 32 bit int.

Consider:

char i = 0x80;
printf("%d",i<<1);

The << operator takes two ints and returns an int, so before the <<
operation takes place, i is implicitly cast to an int.

Next, the integer value 0x80 is shifted left 1 bit to 0x100;

Finally, printf is taking the integer value 0x100 (or binary 0000 0000
0000 0000 0000 0001 0000 0000) and displaying it as a decimal number,
256.

In what way does the int argument (i << 1) not match the %d format?
 
D

Denis McMahon

In what way does the int argument (i << 1) not match the %d format?

See other explanations - the issue is that the promoted i from the <<
and the %d are not the data type the OP thinks he is displaying, ie
unsigned char.

Rgds

Denis McMahon
 

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

Forum statistics

Threads
473,769
Messages
2,569,578
Members
45,052
Latest member
LucyCarper

Latest Threads

Top