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"