Confusion about the output of this program - c

I am new to C programming and I am currently learning Data types revised chapter. In the below
program, my o/p is 36 but compiler is showing the o/p 35.
main( )
{
char ch = 291 ;
printf ( "\n%d %c", ch, ch ) ;
}
Can anyone explain me why the o/p is coming 35? I am currently using GCC 32-bit compiler.

Your system apparently has an 8-bit char type. That means 291 is too big to fit - the compiler reduces it modulo 256 (28) and you end up with 35.
In this case, Clang provides a great warning:
example.c:3:11: warning: implicit conversion from 'int' to 'char' changes value
from 291 to 35 [-Wconstant-conversion]
char ch = 291 ;
~~ ^~~
You should probably avoid relying on this behaviour, since it may vary from implementation to implementation. The C99 and C11 specs (Section 6.3.1.3) say about signed integer conversions:
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.
Since you're using GCC, you might be interested to read this excerpt from the documentation:
The result of, or the signal raised by, converting an integer to a signed integer type when the value cannot be represented in an object of that type (C90 6.2.1.2, C99 6.3.1.3).
For conversion to a type of width N, the value is reduced modulo 2N to be within range of the type; no signal is raised.
And there you have your full explanation of the reduction modulo 256.

You're actually making an overflow. A signed character can only go from values -128 to 127 (256 values = 28) in 8-bit character systems (which are pretty much everywhere).
So we go with an actual character which value equals 291 % 256 = 35.
Don't forget that the first character is 0, not 1.
Here is actually how a char is represented with the 2's complement system:
unsigned
0 ------- 127 128 ------- 255
signed
0 ------- 127 -128 ------- -1
So actually a signed char c1 = -128 equals an unsigned char c2 = 128
But here this problem is just irrelevant. We're talking about modulo because only the last eight bits are taken into account (where would the other be stored when there are only eight bits available for it in the memory ?).
291 = % 1 0010 0011
(% means binary representation)
It keeps only the % 0010 0011 which equals 35 and which will be considered exactly the same either you take it signed or not.

Because a char can only contain 8 bits of information, and 291 require more than that to be stored. It will then discard the higher bits and keep only what fitted in the variable.
You can simulate that by both bitwise and module operation:
291 % 256 = 35
291 & 0xFF = 35
A 8-bit char can contain values of -128 to 127 or 0 to 255, depending if its signed or unsigned.

Related

What's happen when i assigne high value to short int in C [duplicate]

Why the following code prints the value of a as -25536 instead of -25535. My guess is that to normalise the short value in the short range it should do 40000-32767 = 7233 and then start from the first range i.e. -32768+7233 = -25535 then where does extra one come from? Why it's -25536?
#include <stdio.h>
int main()
{
short int a = 40000;
printf("%d", a);
return 0;
}
In the C 2018 standard, 6.3.1.3 3 says conversion to a signed integer type of a value that cannot be represented in the type is implementation-defined. GCC defines the conversion to wrap modulo 2N, where N is the width of the type (the number of bits in the type, including the sign bit).
In the C implementation you are using, short int has 16 bits, so conversion wraps modulo 216 = 65,536. So 40,000 is converted to short int by subtracting 65,536 as many times as needed to produce a value into range (−32,768 to +32,767), which is just once: 40,000−65,536 = −25,536.
Note that the bits for 40,000 in pure binary are 1001 1100 0100 0000 (215 + 212 + 211 + 210 + 26 = 32,768 + 4,096, + 2,048 + 1,024 + 64 = 40,000). When interpreted as two’s complement, the leading bit means −32,768 instead of +32,768, so the interpretation of the same bits in two’s complement is −32,768 + 4,096, + 2,048 + 1,024 + 64 = −25,536. This and the arithmetic properties of two’s complement and binary are related to the reason for GCC’s choice to wrap modulo 2N.
First of all, the correct code is
printf("%hd", a);
Your compiler would have warned you about the problem if you had enabled its warnings. gcc even gives the solution.
Getting -25,536 is by no means guaranteed. But here's what's happening.
On a little-endian 2's-complement machine with 32-bit int vars, 40000 is stored as the bytes 40 9C 00 00.
On a little-endian 2's-complement machine with 16-bit short vars, the bytes 40 9C represent -25536.
No operation is performed.
The key two your question is two's complement. You should find this earlier Q&A most relevant.

ASCII value is greater than 127

#include <stdio.h>
int main() {
char c = 125;
c = c + 10;
printf("%d", c);
return 0;
}
The output of this code is -121.
How this output is -121? Can you please explain?
If I add 100 instead of 10 with c then output is -31.
Why?
In C language the char type is an integer type able to represent all the characters required by the language itself. The standard does not specify whether it is a signed or unsigned type. After seeing the output, I can guess that your system uses a signed char of size 8 bits (7 value bits and one sign bit) and represent negative values in 2-complement.
So (as int) 125 + 10 = 135. 135 > 128 so the actual value is 135 - 256 = -121.
(In two complement mode, number are just wrapped over 2**SIZE_IN_BITS...)
How it works is that the type char in your compiler is a signed type which is 8 bits wide, and represents integer values using a system called two's complement.
In this system, the positive values go from 0 to 127 in binary like this:
00000000 0
00000001 1
00000010 2
00000011 3
... .
01111111 - 127
Upon the next increment, the highest bit flips to 1: we get 10000000. Then the subsequent binary values are interpreted as negative under two's complement:
10000000 128 -128
10000001 129 -127
10000010 130 -126
...
11111111 255 -1
The middle column, continuing to count up from 128, shows the unsigned interpretation of the 8 bit datum; it just keeps counting toward 255. That would be the behavior of the type unsigned char.
The right column, showing negative numbers, is the two's complement interpretation of exactly the same bit patterns. This instead covers a negative range of integers from -128 to -1.
Now what happens in C when we do c + 10?
Firstly, according to the rules of the C language, the c value of type char gets promoted to the type int, which has a much larger range. Thus the int value 125 is being added to the int value 10, resulting in the int value 135.
What happens next is that c is assigned that value, exactly as if by c = 135. But 135 it not in range; char only goes up to 127. Implementation-defined behavior ensues. The 135 value is somehow forced to fit, by discarding bits.
C compilers for two's complement machines (i.e. virtually all compilers on the planet) truncate wider integer value to narrower values simply by truncation of the bottom bits of the value to fit the smaller type.
So, the binary representation of 135 is this.
10000111
More precisely, suppose int is 32 bits wide. Then the representation of the int value 135 is:
00000000000000000000000010000111
This is converted to char by chopping off the top 24 bits, leaving the bottom 8:
------------------------10000111
So we end up with
10000111
in the char type. But what is that? Referring to our original table, we can add a few more rows:
10000000 128 -128
10000001 129 -127
10000010 130 -126
10000011 131 -125
10000100 132 -124
10000101 133 -123
10000110 134 -122
10000111 135 -121 <----
...
11111111 255 -1
And there is the -121.
char type is represented in memory as a byte (most of the time 8 bits), so it can represent values from -128 to +127. If you try to store a bigger value in the memory, it causes an overflow and the result is not what expected.
Here is a nice video explaning what overflow is.
The char is one byte that is 8 bit. one bit is for sign and 7 bits are all of you can use.
"char" range is:
char ==> -128 ~ 127
static_cast<char>(c+1) = 126
static_cast<char>(c+2) = 127
static_cast<char>(c+3) = -128
if you use from "unsigned char", positive range is increase.
unsigned char ==> 0 ~ 255
static_cast<unsigned char>(c+3) = 128

Printing Integer value of character variable in C

Recently in my Institute I was given a code and was asked to find out the answer. The code looks like this.
#include <stdio.h>
int main()
{
char ch=500;
printf("%d\n",ch);
}
The output will come as -12
My question is: How can I calculate the value for this kind of code? Is there any formula or process for finding the values?
The code is syntactically correct but not doing what you think.
As Paul Hankin is suggesting your compiler should give you a warning as you are trying to set a number that does not fit into a char in a char variable.
A char is 1 byte so it can store a number up to 127 if signed or 255 if unsigned.
The value overflows and only the lower 8 bits are taken into account.
500 = 0b111110100
Take only the lower 8 bits: 0b11110100
The MSB is 1 so it's negative number.
1-complement plus 1 is 0b00001100 which is 12
That's why you get -12.
Replacing it by a short or an int should correctly print 500.
You can't know, unless you know the specifics of the given system.
char is typically only 8 bits wide and can't hold the value of 500. Furthermore, the char type is unsuitable for storing integer values, since it has implementation-defined signedness.
Meaning you can't know if it can contain values from 0 to 255 or from -128 to 127 (two's complement). It can even in theory have other constrains and other signedness formats.
Also, the conversion from a large unsigned integer to a smaller signed one is implementation-defined.
I would guess that your specific system has signed 8 bit char type and two's complement signedness. The raw value of 500 is 0x1F4. Upon initialization, your particular compiler will truncate this to fit an 8 bit variable, meaning you end up with only the least significant byte, 0xF4. Since you have an 8 bits signed variable in two's complement format, 0xF4 equals -12.
(The implicit type promotion done by printf preserves the sign.)
None of this behavior is guaranteed across different systems.
Needless to say, the code is completely non-portable. You should not write code like this, which heavily relies on numerous forms of poorly defined behavior.
here in this code ch is signed character type and seems its 8-bit ascii code...
so its range is from -128 to +127 (total 256)...
now lets cycle over this ascii range starting from 0 to 127 then -128 to 0 and so...
total value of integer number is 500
from 0 to 127 and -128 to 0 (whole circle),
left integer value is 500-256 = 244.
from 0 to 127,
left integer value is 244-128=116.
from -128 to -12,
left integer value is 116-116=0.
so after counting all 500 we are at -12 of ascii range....
"sorry for long and non-mathematical explanation....effort is to make you understand"
When using char data types to encode integers, the char values go from -128 to 127. The value is overflowing.
500 - 127 = 373
373 - 128 = 245
245 - 127 = 118
118 - 128 = -10
Since we are passing over 0 twice and that counts, it give us -12. If you try to print the character you will see that it is invalid there is no -12 literal. You can also check man ascii

Why stores 255 in a char variable give its value -1 in C?

I am reading a C book, and there is a text the author mentioned:
"if ch (a char variable) is a signed type, then storing 255 in the ch variable gives it the value -1".
Can anyone elaborate on that?
Assuming 8-bit chars, that is actually implementation-defined behaviour. The value 255 cannot be represented as a signed 8-bit integer.
However, most implementations simply store the bit-pattern, which for 255 is 0xFF. With a two's-complement interpretation, as a signed 8-bit integer, that is the bit-pattern of -1. On a rarer ones'-complement architecture, that would be the bit pattern of negative zero or a trap representation, with sign-and-magnitude, it would be -127.
If either of the two assumptions (signedness and 8-bit chars) doesn't hold, the value will be¹ 255, since 255 is representable as an unsigned 8-bit integer or as a signed (or unsigned) integer with more than 8 bits.
¹ The standard guarantees that CHAR_BIT is at least 8, it may be greater.
Try it in decimal. Suppose we can only have 3 digits. So our unsigned range is 0 - 999.
Let's see if 999 can actually behave as -1 (signed):
42 + 999 = 1041
Because we can only have 3 digits, we drop the highest order digit (the carry):
041 = 42 - 1
This is a general rule that applies to any number base.
That is not guaranteed behavior. To quote ANSI/ISO/IEC 9899:1999 §6.3.1.3 (converting between signed and unsigned integers) clause 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.
I'll leave the bitwise/2's complement explanations to the other answers, but standards-compliant signed chars aren't even guaranteed to be too small to hold 255; they might work just fine (giving the value 255.)
That's how two's complement works. Read all about it here.
You have classical explanation in others messages. I give you a rule:
In a signed type with size n, presence of MSB set as 1, must interpreted as -2^(n-1).
For this concrete question, assuming size of char is 8 bits length (1 bytes), 255 to binary is equal to:
1*2^(7) +
1*2^(6) +
1*2^(5) +
1*2^(4) +
1*2^(3) +
1*2^(2) +
1*2^(1) +
1*2^(0) = 255
255 equivalent to 1 1 1 1 1 1 1 1.
For unsigned char, you get 255, but if you are dealing with char (same as signed char), MSB represents a negative magnitude:
-1*2^(7) +
1*2^(6) +
1*2^(5) +
1*2^(4) +
1*2^(3) +
1*2^(2) +
1*2^(1) +
1*2^(0) = -1

Simple Character Interpretation In C

Here is my code
#include<stdio.h>
void main()
{
char ch = 129;
printf("%d", ch);
}
I get the output as -127. What does it mean?
It means that char is an 8-bit variable that can only hold 2^8 = 256 values, since the declaration is char ch, ch is a signed variable, which means it can store 127 negative and positive values. when you ask to go over 127 then the value starts over from -128.
Think of it like some arcade games where you go from one side of the screen to the other:
ch = 50;
-----> 50 is stored
|___________________________________|___________| since it fits
-128 0 50 127 between -127
and 128
ch = 129;
--- 129 goes over
--> 127 by 2, so
|__|____________________________________________| it 'lands' in
-128 -127 0 127 -127
BUT!! you shouldn't rely on this since it's undefined behaviour!
In honor of Luchian Grigore here's the bit representation of what's happening:
A char is a variable that will hold 8-bits or a byte. So we have 8 0's and 1's struggling to represent whatever value you desire. If the char is a signed variable it will represent whether it's a positive or negative number. You probably read about the one bit representing the sign, that's an abstraction of the true process; in fact it is only one of the first solutions implemented in electronics. But such a trivial method had a problem, you would have 2 ways of representing 0 (+0 and -0):
0 0000000 -> +0 1 0000000 -> -0
^ ^
|_ sign bit 0: positive |_ sign bit 1: negative
Inconsistencies guaranteed!! So, some very smart folks came up with a system called Ones' Complement which would represent a negative number as the negation (NOT operation) of its positive counterpart:
01010101 -> +85
10101010 -> -85
This system... had the same problem. 0 could be represented as 00000000 (+0) and 11111111 (-0). Then came some smarter folks who created Two's Complement, which would hold the negation part of the earlier method and then add 1, therefore removing that pesky -0 and giving us a shiny new number to our range: -128!. So how does our range look now?
00000000 +0
00000001 +1
00000010 +2
...
01111110 +126
01111111 +127
10000000 -128
10000001 -127
10000010 -126
...
11111110 -2
11111111 -1
So, this should give an idea of what's happening when our little processor tries to add numbers to our variable:
0110010 50 01111111 127
+0000010 + 2 +00000010 + 2
------- -- -------- ---
0110100 52 10000001 -127
^ ^ ^
|_ 1 + 1 = 10 129 in bin _| |_ wait, what?!
Yep, if you review the range table above you can see that up to 127 (01111111) the binary was fine and dandy, nothing weird happening, but after the 8'th bit is set at -128 (10000000) the number interpreted no longer held to its binary magnitude but to the Two's Complement representation. This means, the binary representation, the bits in your variable, the 1's and 0's, the heart of our beloved char, does hold a 129... its there, look at it! But the evil processor reads that as measly -127 cause the variable HAD to be signed undermining all its positive potential for a smelly shift through the real number line in the Euclidean space of dimension one.
It means you ran into undefined behavior.
Any outcome is possible.
char ch=129; is UB because 129 is not a representable value for a char for you specific setup.
Your char is most likely an 8-bit signed integer that is stored using Two's complement. Such a variable can only represent numbers between -128 and 127. If you do "127+1" it wraps around to -128. So 129 is equivalent to -127.
This comes from the fact that a char is coded on one byte, so 8 bits of data.
In fact char has a value coded on 7 bits and have one bit for the sign, unsigned char have 8 bits of data for its value.
This means:
Taking abcdefgh as 8 bits respectively (a being the leftmost bit, and h the rightmost), the value is encoded with a for the sign and bcdefgh in binary format for the real value:
42(decimal) = 101010(binary)
stored as :
abcdefgh
00101010
When using this value from the memory :
a is 0 : the number is positive, bcdefgh = 0101010 : the value is 42
What happens when you put 129 :
129(decimal) = 10000001(binary)
stored as :
abcdefgh
10000001
When using this value from the memory :
a is 0 : the number is negative, we should substract one and invert all bits in the value, so (bcdefgh - 1) inverted = 1111111 : the value is 127
The number is -127
On your system: char 129 has the same bits as the 8 bit signed integer -127.
An unsigned integer goes from 0 to 255, and signed integer -128 to 127.
Related (C++):
You may also be interested in reading the nice top answer to What is an unsigned char?
As #jmquigley points out. This is strictly undefined behavior and you should not rely on it.
Allowing signed integer overflows in C/C++
The char type is a 8-bit signed integer. If you interpret the representation of unsigned byte 129 in the two's complement signed representation, you get -127.
The type char can be either signed or unsigned, it's up to the compiler. Most compilers have it as `signed.
In your case, the compiler silently converts the integer 129 to its signed variant, and puts it in an 8-bit field, which yields -127.
char is 8 bits, signed. It can only hold values -128 to 127. When you try and assign 129 to it you get the result you see because the bit that indicates signing is flipped. Another way to think of it is that the number "wraps" around.
Whether a plain char is signed or unsigned, is implementation-defined behavior. This is a quite stupid, obscure rule in the C language. int, long etc are guaranteed to be signed, but char could be signed or unsigned, it is up to the compiler implementation.
On your particular compiler, char is apparently signed. This means, assuming that your system uses two's complement, that it can hold values of -128 to 127.
You attempt to store the value 129 in such a variable. This leads to undefined behavior, because you get an integer overflow. Strictly speaking, anything can happen when you do this. The program could print "hello world" or start shooting innocent bystanders, and still conform to ISO C. In practice, most (all?) compilers will however implement this undefined behavior as "wrap around", as described in other answers.
To sum it up, your code relies on two different behaviors that aren't well defined by the standard. Understanding how the result of such unpredictable code ends up in a certain way has limited value. The important thing here is to recognize that the code is obscure, and learn how to write it in a way that isn't obscure.
The code could for example be rewritten as:
unsigned char ch = 129;
Or even better:
#include <stdint.h>
...
uint8_t ch = 129;
As a rule of thumb, make sure to follow these rules in MISRA-C:2004:
6.1 The plain char type shall be used only for the storage and use of character values.
6.2 signed and unsigned char type shall be used only for the storage and use of numeric values.

Resources