I am trying to print char as positive value:
char ch = 212;
printf("%u", ch);
but I get:
4294967252
How I can get 212 in the output?
Declare your ch as
unsigned char ch = 212 ;
And your printf will work.
This is because in this case the char type is signed on your system*. When this happens, the data gets sign-extended during the default conversions while passing the data to the function with variable number of arguments. Since 212 is greater than 0x80, it's treated as negative, %u interprets the number as a large positive number:
212 = 0xD4
When it is sign-extended, FFs are pre-pended to your number, so it becomes
0xFFFFFFD4 = 4294967252
which is the number that gets printed.
Note that this behavior is specific to your implementation. According to C99 specification, all char types are promoted to (signed) int, because an int can represent all values of a char, signed or unsigned:
6.1.1.2: If an int can represent all values of the original type, the value is converted to an int; otherwise, it is converted to an unsigned int.
This results in passing an int to a format specifier %u, which expects an unsigned int.
To avoid undefined behavior in your program, add explicit type casts as follows:
unsigned char ch = (unsigned char)212;
printf("%u", (unsigned int)ch);
* In general, the standard leaves the signedness of char up to the implementation. See this question for more details.
There are two bugs in this code. First, in most C implementations with signed char, there is a problem in char ch = 212 because 212 does not fit in an 8-bit signed char, and the C standard does not fully define the behavior (it requires the implementation to define the behavior). It should instead be:
unsigned char ch = 212;
Second, in printf("%u",ch), ch will be promoted to an int in normal C implementations. However, the %u specifier expects an unsigned int, and the C standard does not define behavior when the wrong type is passed. It should instead be:
printf("%hhu", ch);
(For %hhu, printf expects an unsigned char that has, in normal C implementations, been promoted to int.)
In case you cannot change the declaration for whatever reason, you can do:
char ch = 212;
printf("%d", (unsigned char) ch);
The range of char is 127 to -128. If you assign 212, ch stores -44 (212-128-128) not 212.So if you try to print a negative number as unsigned you get (MAX value of unsigned int)-abs(number) which in this case is 4294967252
So if you want to store 212 as it is in ch the only thing you can do is declare ch as
unsigned char ch;
now the range of ch is 0 to 255.
Because char is by default signed declared that means the range of the variable is
-127 to +127>
your value is overflowed. To get the desired value you have to declared the unsigned modifier. the modifier's (unsigned) range is:
0 to 255
to get the the range of any data type follow the process 2^bit example charis 8 bit length to get its range just 2 ^(power) 8.
Related
Why are two char like signed char and unsigned char with the same value not equal?
char a = 0xfb;
unsigned char b = 0xfb;
bool f;
f = (a == b);
cout << f;
In the above code, the value of f is 0.
Why it's so when both a and b have the same value?
There are no arithmetic operators that accept integers smaller than int. Hence, both char values get promoted to int first, see integral promotion
for full details.
char is signed on your platform, so 0xfb gets promoted to int(-5), whereas unsigned char gets promoted to int(0x000000fb). These two integers do not compare equal.
On the other hand, the standard in [basic.fundamental] requires that all char types occupy the same amount of storage and have the same alignment requirements; that is, they have the same object representation and all bits of the object representation participate in the value representation. Hence, memcmp(&a, &b, 1) == 0 is true.
The value of f and, in fact, the behaviour of the program, is implementation-defined.
In C++14 onwards1, for a signed char, and assuming that CHAR_MAX is 127, a will probably be -5. Formally speaking, if char is signed and the number does not fit into a char, then the conversion is implementation-defined or an implementation-defined signal is raised.
b is 251.
For the comparison a == b (and retaining the assumption that char is a narrower type than an int) both arguments are converted to int, with -5 and 251 therefore retained.
And that's false as the numbers are not equal.
Finally, note that on a platform where char, short, and int are all the same size, the result of your code would be true (and the == would be in unsigned types)! The moral of the story: don't mix your types.
1 C++14 dropped 1's complement and signed magnitude signed char.
Value range for (signed) char is [-128, 127]. (C++14 drops -127 as the lower range).
Value range for unsigned char is [0, 255]
What you're trying to assign to both of the variables is 251 in decimal. Since char cannot hold that value you will suffer a value overflow, as the following warning tells you.
warning: overflow in conversion from 'int' to 'char' changes value from '251' to ''\37777777773'' [-Woverflow]
As a result a will probably hold value -5 while b will be 251 and they are indeed not equal.
I have this unsigned char sumBinaryFigure function that calculates the sum of the digits of the binary representation of an unsigned long long number. When I call this function from the main function, for an unsigned long long it should return a integer(or another numeric data type) although the data type of the function is unsigned char. Is it possible? I tried a function overloading and it didn't work. If it sounds absurd, it's not my fault.
unsigned char sumBinaryFigure(unsigned long long number)
{
unsigned int S = 0;
while (number)
{
S += number % 2;
number /= 2;
}
return S;
}
When I call this function from the main function, for an unsigned long long it should return a integer although the data type of the function is unsigned char. Is it possible?
Yes. The question is not absurd, C types are just confusing. unsigned char and int both represent integers.
Your code is correct.
unsigned char is a 1-byte datatype. It can be used to represent a letter, or it can be used to represent a number.
The following statements are equivalent.
unsigned char ch = 'A';
unsigned char ch = 65;
Whether you use unsigned char as a character or integer, the machine does not care.
char does not necessarily contain a character. It also represents small numbers
The posted implementation of sumBinaryFigure returns a number in the range of 0-255, nothing wrong with that. Because a long long is almost certainly less than 256 bits, you don't need to worry about unsigned char not being large enough.
If I can suggest one change to your program in order to make it less confusing, change this line
unsigned int S = 0;
to this...
unsigned char S = 0;
Addendum
Just to be clear, consider the following code.
int main (void) {
char ch_num = 65; // ch_num is the byte 0100 0001
char ch_char = 'A'; // ch_char is the byte 0100 0001
printf ("%d\n", ch_num); // Prints 65
printf ("%d\n", ch_char); // Prints 65
printf ("%c\n", ch_num); // Prints A
printf ("%c\n", ch_char); // Prints A
}
A char is a byte. It's a sequence of bits with no meaning except what we impose on it.
That byte can be interpreted as either a number or character, but that decision is up to the programmer. The %c format specifier says "interpret this as a character. The %d format specifier says "interpret this as a number".
Whether it's an integer or character is decided by the output function, not the data type.
unsigned char can be converted to int without narrowing on all platforms that I can think of. You don't need to overload anything, just assign the result of the function to an int variable:
int popcnt = sumBinaryFigure(1023);
In fact, taking the function semantics into account, there's no way the result value will not fit into an int, which is guaranteed to be at least 16-bit, which means the minimal numeric_limits<int>::max() value is 32767. You'd have to have a datatype capable of storing over 32767 binary digits for this to be even remotely possible (int on most platforms is 32-bit)
I have an 80 element char array and I am trying to specific elements to an integer and am getting some number errors.
Array element 40 in hex is 0xC0. When I try assigning it to an integer I get in hex 0xFFFFC0, and I dont know why.
char tempArray[80]; //Read in from file, with element 40 as 0xC0
int tempInt = (int)tempArray[40]; //Output as 0xFFFFC0 instead of 0x0000C0
Depending on your implementation, a char type in C++ is either a signed type or an unsigned type. (The C++ standard mandates that an implementation chooses either scheme).
To be on the safe side, use unsigned char in your case.
This is so because char is treated as signed number, and the promotion to int preserves the sign. Change the array from char to unsigned char to avoid it.
Because 0XC0 is negative in char, and the cast is preserving the sign as an int. You should use unsigned char if you want to maintain the directly binary translation or as a purely positive value
for more convenience, I always use unsigned and signed always before declaration and casting. you can write the following:
unsigned char tempArray[80]; //Read in from file, with element 40 as 0xC0
unsigned int tempInt = (unsigned int)tempArray[40]; //Output as 0xFFFFC0 instead of 0x0000C0
char may be signed, so converting from a negative char value will result in a negative int value, which is usualyl represented in two's complement, resulting in a very high binary representation.
Instead, either use int tempInt = 0xFF & tempArray[40], define tempArray as unsigned char, or cast to unsigned char : int tempInt = (unsigned char)tempArray[40] (unsure if this is defined behaviour).
From what i know it should be implementation-dependent but it returns -1.Why?
char ch = 255;
int i = ch;
cout<<i;
return 0;
char by default may be signed or unsigned. (implementation dependent)
Minimum range of signed char is -127 to 127 (typically -128 to 127).
If by default char is signed, ch would not be able to accommodate 255(0xFF) and would silently convert it to -1(0xFF). Then you are typecasting it to int and printing so the output is -1.
To avoid this use unsigned char explicitly. (Range is atleast 0 to 255)
4.7 Integral conversions [conv.integral]
[3] If the destination type is signed, the value is unchanged if it can
be represented in the destination type (and bit-field width);
otherwise, the value is implementation-defined.
char might be (and in your case apparently is) a signed type wit a range from -128 to +127.
So char ch = 255 triggers an overflow which yields an implementation defined result for signed types.
Example:
printf("%d %d\n", ip[0],ip[1]); will print -64, -88. If you add 256 and you get 192 168
unsigned char a = -64; printf("%d", a); will print 192. Any idea what's happening?
ip[] is a char array for what it's worth.
Plain char has implementation-defined signedness, in your case signed.
Because printfis a variadic function, default promotions apply, meaning your char is promoted to an int, conserving the value.
Unless you tell printf you passed an unsigned char, it will think it is an int or unsigned int and cannot reverse those promotions, meaning: 192 as char is -64 as int is -64 interpreted as unsigned is 4294967195.
The right format specifier would be "%hhu" for unsigned char.
BTW: The specific numbers assume CHAR_BIT==8, sizeof(int)==4, 2s-complement representation.