Addition of two chars, example char a = 'A' and b = 'B' - c

Why does this program output a negative value?
#include <stdio.h>
int main() {
char a = 'a', b = 'b', c;
c = a + b;
printf("%d", c);
}
Shouldn't these values be converted into ASCII then added up?

On the most common platforms, char is a signed type which can represent values from -127 to +128. You appear to be using a platform on which char has these properties.
Note that on some platforms, char is unsigned, so that the range of representable values is 0 to 255. However, you do not appear to be using such a platform.
Adding 'a' to 'b' is the same as adding their ASCII values (97 and 98 respectively), for a result of 195. This result is not representable as a char on your platform. In many implementations, the first bit is a sign bit, so you get -61.
Using unsigned char gives the result that you expect for printable 7-bit ASCII characters.
#include <stdio.h>
int main() {
char a = 'a', b = 'b';
unsigned char c;
c = a + b;
printf("%d\n",a);
printf("%d\n",b);
printf("%d\n", c);
}
Outputs:
97
98
195

a = 97
b = 98
a+b = 195
195 is out of the signed 8-bit range (-128 ... 127)
195 = 0b11000011
This equals -61 in signed 8-bit representation.

As explained by 3Dave char is a signed type and adding up two variables of such type can lead to overflow and it produces a negative result. Even if you use unsigned char this sum can result in an overflow, but not with negative value.

Related

Char automatically converts to int (I guess)

I have following code
char temp[] = { 0xAE, 0xFF };
printf("%X\n", temp[0]);
Why output is FFFFFFAE, not just AE?
I tried
printf("%X\n", 0b10101110);
And output is correct: AE.
Suggestions?
The answer you're getting, FFFFFFAE, is a result of the char data type being signed. If you check the value, you'll notice that it's equal to -82, where -82 + 256 = 174, or 0xAE in hexadecimal.
The reason you get the correct output when you print 0b10101110 or even 174 is because you're using the literal values directly, whereas in your example you're first putting the 0xAE value in a signed char where the value is then being sort of "reinterpreted modulo 128", if you wanna think of it that way.
So in other words:
0 = 0 = 0x00
127 = 127 = 0x7F
128 = -128 = 0xFFFFFF80
129 = -127 = 0xFFFFFF81
174 = -82 = 0xFFFFFFAE
255 = -1 = 0xFFFFFFFF
256 = 0 = 0x00
To fix this "problem", you could declare the same array you initially did, just make sure to use an unsigned char type array and your values should print as you expect.
#include <stdio.h>
#include <stdlib.h>
int main()
{
unsigned char temp[] = { 0xAE, 0xFF };
printf("%X\n", temp[0]);
printf("%d\n\n", temp[0]);
printf("%X\n", temp[1]);
printf("%d\n\n", temp[1]);
return EXIT_SUCCESS;
}
Output:
AE
174
FF
255
https://linux.die.net/man/3/printf
According to the man page, %x or %X accept an unsigned integer. Thus it will read 4 bytes from the stack.
In any case, under most architectures you can't pass a parameter that is less then a word (i.e. int or long) in size, and in your case it will be converted to int.
In the first case, you're passing a char, so it will be casted to int. Both are signed, so a signed cast is performed, thus you see preceding FFs.
In your second example, you're actually passing an int all the way, so no cast is performed.
If you'd try:
printf("%X\n", (char) 0b10101110);
You'd see that FFFFFFAE will be printed.
When you pass a smaller than int data type (as char is) to a variadic function (as printf(3) is) the parameter is converted to int in case the parameter is signed and to unsigned int in the case it is unsigned. What is being done and you observe is a sign extension, as the most significative bit of the char variable is active, it is replicated to the thre bytes needed to complete an int.
To solve this and to have the data in 8 bits, you have two possibilities:
Allow your signed char to convert to an int (with sign extension) then mask the bits 8 and above.
printf("%X\n", (int) my_char & 0xff);
Declare your variable as unsigned, so it is promoted to an unsigned int.
unsigned char my_char;
...
printf("%X\n", my_char);
This code causes undefined behaviour. The argument to %X must have type unsigned int, but you supply char.
Undefined behaviour means that anything can happen; including, but not limited to, extra F's appearing in the output.

when assigning the unsigned char with the integer greater than 255 it gives the different output , why?

#include<stdio.h>
int main()
{
unsigned char c =292;
printf("%d\n",c);
return 0;
}
The following code gives the output "36".
I wanted to know why this happens?
Because 292 does not fit in a variable of type unsigned char.
I suggest you to compile this program:
#include <stdio.h>
#include <limits.h>
int main()
{
unsigned char c =292;
printf("%d %d\n", c, UCHAR_MAX);
return 0;
}
and check the output:
prog.c: In function 'main':
prog.c:5:21: warning: unsigned conversion from 'int' to 'unsigned char' changes value from '292' to '36' [-Woverflow]
unsigned char c =292;
^~~
36 255
So, UCHAR_MAX in my system is 255, and that's the largest value you are allowed to assign to c.
292 just overflows c, and because it's an unsigned type, it goes from 0 to 255, thus it wraps around, giving you 292 - (255 + 1) = 36.
The size of char data_type is 1 byte and its range is 0 to 255.
but here initialization is more than 255(i.e. c=292>255)
Hence, c stores (292-255)th value (i.e. 37th value) and the value c stores is 36(because 0 is the first value).
It means you have initialize c = 36.
And finally, printf() func. fetch value from memory and print the value 36.
When you convert 292 to binary, you will get 0001 0010 0100 (9 bits).
But unfortunately, a character variable can store only 1 byte (8 bits).
So it will take the last 8 bits. ie : 0010 0100 which is equal to 36 in decimal.
Hope this helps

Overflow char to int conversion

#include <stdio.h>
void func(int a);
int main() {
char ch = 256;
func(ch);
return 0;
}
void func(int a) {
printf("%d\n", a);
}
The output of the above program is 0.
Can anyone explain how
256 is too large for the char type on your machine.
So it wraps around to the minimum value 0, as per the C standard (from N1570, emphasis mine):
6.3.1.3 Signed and unsigned integers
1 When a value with integer type is converted to another integer type other than _Bool, if the value
can be represented by the new type, it is unchanged.
2 Otherwise, if
the new type is unsigned, the value is converted by repeatedly adding
or subtracting one more than the maximum value that can be represented
in the new type until the value is in the range of the new type.60)
3
Otherwise, the new type is signed and the value cannot be represented
in it; either the result is implementation-defined or an
implementation-defined signal is raised.
The 256 literal is an int, and char is an integer type that is either signed or unsigned, so one of the above emphasized behaviors will occur.
Because Character set is limited to 255 characters only so your output is 0
http://www.asciitable.com/ have complete list of characterset details and char is limited to 256 only
unsigned char 1 byte -> 0 to 255
signed char 1 byte -> -128 to 127
Trying to store 256 in 8 bits...it gets all the 1[00000000]. So basically it overflows and the 0 bits are only left.
#include <stdio.h>
void func(int a);
int main() {
char ch = 256;
printf("%c\n",ch); //nothing prints. That's what happens when
// when we print 'NUL'
func(ch);
return 0;
}
void func(int a) {
printf("%d\n", a);
}
The maximum range of char is 127. The value 256 is 129 more than 127 and when we add 1 to 127 (which is maximum value of char) it goes to minimum value -128. So if we add 129 to 127 it results in 0.
for char
127 + 1 = -128.
127 + 129 = 0
So for the below program the output is 1.
#include <stdio.h>
void func(int a);
int main() {
char ch = 257;
func(ch);
return 0;
}
void func(int a) {
printf("%d\n", a);
}
If you compile this with gcc it actually tells you why:
testo.c: In function ‘main’:
testo.c:6:15: warning: overflow in implicit constant conversion [-Woverflow]
char ch = 256;
^

c and bit shifting in a char

I am new to C and having a hard time understanding why the code below prints out ffffffff when binary 1111111 should equal hex ff.
int i;
char num[8] = "11111111";
unsigned char result = 0;
for ( i = 0; i < 8; ++i )
result |= (num[i] == '1') << (7 - i);
}
printf("%X", bytedata);
You print bytedata which may be uninitialized.
Replace
printf("%X", bytedata);
with
printf("%X", result);
Your code then run's fine. code
Although it is legal in C, for good practice you should make
char num[8] = "11111111";
to
char num[9] = "11111111";
because in C the null character ('\0') always appended to the string literal. And also it would not compile as a C++ file with g++.
EDIT
To answer your question
If I use char the result is FFFFFFFF but if I use unsigned char the result is FF.
Answer:
Case 1:
In C size of char is 1byte(Most implementation). If it is unsigned we can
use 8bit and hold maximum 11111111 in binary and FF in hex(decimal 255). When you print it with printf("%X", result);, this value implicitly converted to unsigned int which becomes FF in hex.
Case 2: But when you use char(signed), then MSB bit use as sign bit, so you can use at most 7 bit for your number whose range -128 to 127 in decimal. When you assign it with FF(255 in decimal) then Integer Overflow occur which leads to Undefined behavior.

OR operator in C not working

I don't understand why the final printf in the code below is not printing 255.
char c;
c = c & 0;
printf("The value of c is %d", (int)c);
int j = 255;
c = (c | j);
printf("The value of c is %d", (int)c);
In most implementations the char type is signed, so it ranges from -128 to 127.
This means, 11111111 (which is 255 written in binary) is equal to -1. (As it's represented as a value stored in two's complement)
To get what you expect, you need to declare c as a unsigned char, like so:
unsigned char c = 0;
int j = 255;
c = (c | j);
printf("The value of c is %d", (int)c);
It is probably printing -1. That is because
c = (c | j);
will evaluate as
c = (0 | 255) = (0 | 0xFF) = 0xFF
but, since c is signed, 0xFF will be -1 and not 255 as you expected. If you change c to unsigned char it will print 255, as you imagined.
Try to replace char c with unsigned char c. Basically char type supports values from -128 to 127. Your result is bigger than the supported range and overflows.
By default char
is signed char
in C. If you want 255 to be printed then use unsigned char
however i explain the output in context of signed char
so that the concept becomes clear.
If you write j=127 then it will print 127 as the bit representation is 01111111.
But if you write j=128
then it will print -128
because the bit representation 01111111 has increased by 1 to become 10000000.
now if you write j=255
then the bit representation is 11111111. so it will print -1
If you write j=256
then it will print 0
because when bit representation 11111111 is increased by 1 it becomes 100000000. But only 1 byte is allocated for a characher variable so the left most bit is not stored and bit representation becomes 00000000.
Further if you write j=257
then its also a case of overflow and the bit representation become 00000001 and 1 will be printed.

Resources