1

I came across the following unexpected behaviour while working on pset2 does any body have any idea why this is happening in the following code, at the 9th line.

#include <cs50.h>
#include <stdio.h>
#include <ctype.h>

int main(int argc, string argv[])
{
    char added1 = 'r'  + (tolower('Z') - 'a') ;
    //shouldn't what added1 holds be the same as the one printf function
    //calculates be the same but as it can be seen by runing the program
    //they aren't why? 
    printf("added1:%i, added2:%i\n" ,added1,'r'  + (tolower('Z') - 'a'));

}

here is the output i get when i run my program:

added1:-117, added2:139

also doing this will give the same effect as the printf addition gives

int plainTextInt = 'r' ;
int keyInt = (tolower('z') - 'a') ;
int added3 = plainTextInt + keyInt;

printf("added3:%i\n" ,added3);

the out put for this one is

added3:139//the same as the added2 value (the one from the printf function)
1

In the first case, you use a char variable, which in our case is an signed char by default, supporting values from -128 to 127. The result of your computation does not fit in, so it wraps around, keeping the least significant byte of the result. You can see the numbers differing by 256, or 2 to the power of 8.

The second computation is probably returning an int instead, which happily supports much larger numbers (32 bit on modern PC).

0

This happens because of the variable types being used. Look at this:

char added1 = 'r'  + (tolower('Z') - 'a') ;

The char type is a signed single byte type. Interestingly, while a char only uses values from 0 to 127, it is technically a signed char by default. It behaves just like a single byte signed int. The statement above is equivalent to 114 + 122 - 97 and evaluates to 139. The result is a regular int, but the raw value is then stored in char as ffffff8b.

But why does it print out as -117? Its about the interaction between the formatting code in the printf statement and the unsigned variable. Look at the printf statement:

printf("added1:%i, added2:%i\n" ,added1,'r'  + (tolower('Z') - 'a'));

The first formatting symbol, %i will recast added1 from a (signed) char to a signed int. That changes the way it will be printed. Instead of printing a non-printable char (there's no ASCII char above 127 or below 0) it casts (or treats) the char as a signed int. Thus, it prints -117, which is what you get when converting the stored raw value using two's complement.

To understand how the recast works, you have to understand how twos complement representation works. It would take too long to explain here, but you can google it to learn.

The result is that the raw value stored as a char is printed as a signed int.

Interestingly, there's also a var type called unsigned char. For more info, check out this page: http://www.differencebetween.info/difference-between-signed-char-and-unsigned-char

If this (or another answer) answers your question, please click on the check mark to accept. Let's keep up on forum maintenance.

6
  • char here is signed. Overflow is not defined for unsigned data types (might work, or not), but here it's happening. – Blauelf Mar 1 '19 at 17:57
  • Oh crap, it is. Let me fix that. – Cliff B Mar 1 '19 at 18:01
  • if that is the case shouldn't """printf("added1:%u, added2:%i" ,added1,'r' + (tolower('Z') - 'a'));""" print similar stuff, or shouldn't this print true """if (added1 == 'r' + (tolower('Z') - 'a')) { printf("true"); }""" – EHM Mar 1 '19 at 18:02
  • Numbers are expanded before comparison. Character -117 with byte 8b will be expanded to ffffff8b, while the integer 139 is 0000008b, so they won't be equal. – Blauelf Mar 1 '19 at 18:20
  • 1
    char can be signed or unsigned by default, depends on platform. And the char only saves the 8b, but when we compare to an integer, both are brought to same length (adding fs for negative numbers), subtracted, result checked for zero. – Blauelf Mar 1 '19 at 18:37

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .