basic char int conversion

Just to exercise i wrote a function to see if a line input (string checkInt) represents an integer and I'm glad it worked.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
bool checkIntInput(string & checkInt)
{
  bool rtrn = true; // return value
  if(checkInt.size() != 0)
  {
    char charInt;
    int intChar;
    for(size_t i = 0; i < checkInt.size(); ++i)
    {
      charInt = checkInt[i];
      intChar = int(charInt) - 48;
      if( !( ((intChar + 1) > 0) &&  (intChar < 10) ) ) rtrn = false;
    }
  }
  else rtrn = false;

 return rtrn;
}


But there is something that worries me. As i convert a character value to a (signed) integer, one would expect the result would be between values -128 and +127. And the last condition should be written as:

 
 if( !( ((intChar + 1) > -128) &&  (intChar < -118) ) ) rtrn = false;


Where does this (false) logic go wrong? (Does an unsigned int a=1 converted to an unsigned int result in a=1?)
Last edited on
Yes the value of int(charInt) is in the range -128 to +127 (assuming char is signed).

You then subtract 48 which is the ascii value of '0'. That means intChar will be in the range -176 to +79. More important, if charInt is a digit the value of intChar is in the range 0 to 9 and that's what the if statement is checking.

Written another way this is what the if statement is doing.
 
if(intChar < 0 || intChar > 9) rtrn = false;
Last edited on
I am sorry Peter87, but how does this add up? Or do you mean to say that char is like a signed (not unsigned) 8-bit integer and therefor the value of, let's say character '0' (ascii 48) is not 48, but -128+48=-80 ? Could i simply claim next condition:
 
       if(int(charInt) < -80 || int(charInt) > -71) rtrn = false;

Puzzling...
Last edited on
When dealing with values in the range 0 to +127, it doesn't matter whether the value is a signed char or an unsigned char, the internal bit representation will be the same. By default a char is a signed value. But 48 decimal is binary 00110000, regardless of whether it is a signed or unsigned value.
Alright Chervil, this is very clear. What will happen if we do this:
1
2
3
4
char a;
int b = (int)a;
return 0;
}

Where character char a has a "ascii" value higher than 127 ?
Figured it out, it goes around the clock: integer 130 gives a character with (int)char value=-126 ; the char itself being unrepresentable/definable:
1
2
3
4
5
6
7
8
9
10
11
#include <iostream>
int main(){
  char a;
  unsigned int b = 130;
  a = char(b);
  std::cout << a << '\n' << (int)a << '\n';
  int c = 48;
  a = char(c);
  std::cout << a << '\n' << (int)a << '\n';
return 0;
}

./charint1

-126
0
48
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <iostream>

using namespace std;

int main()
{
    char a = (char) 128;

    int          x = a;
    unsigned int y = a;
    int          z = (unsigned char) a;
    
    cout << "x = " << x << '\n';
    cout << "y = " << y << '\n'; 
    cout << "z = " << z << '\n';
}
x = -128
y = 4294967168
z = 128
Well Chervil,

This was a very harsh trick. And a bit sick ;-) But it should be in every tutorial on programming. I did compile it and it didn't lie... Okay, let's go about, and tell me if i am wrong:

The first line you tell to have a char "a" where -128<=char<128 and its original int value was 128 and than converted to char (again you told me: -128<=char<128). And the given value 128 is 1 over the top of 127 and gets "around the clock" to -128. (No compile error what so ever, hmm?) So char "a" becomes -128 (probably it can go thousand times around).

For x is an int that equals an unsigned int (at least -2,147,483,648 to 2,147,483,647) it will take over this value (-128) whilst it is in the range.
Now we know (char) "a" and "x" have the value -128.

For "z" is an int it can have any value at least within 2 bytes it can have bigger numbers than 127; what can i learn? It is wrong to say (unsigned char)a-(char)a=128? (unsigned char)a == (char)a, while (int)a<a ?

for "y". Well the result is because the unsigned int (4 bytes) is within the range of 0 to 4,294,967,295. So subtracting 127 should leave the outcome: 4294967168. Around the clock in a different direction: learned again!

GREAT STUFF
But running around the clock is nothing else but modulus, isn't it:
1
2
3
4
5
6
7
8
9
#include <iostream>

int main()
{
    char a = (char) 1072;
    int x = a;
    std::cout << "a = " << a << '\n' << "x = " << x << '\n';
return 0;
}

./cherv
a = 0
x = 48
Some of your descriptions are ok, though I tend to look at things from a different angle.

 
    char a = (char) 128;
There's no compiler error or warning because the use of the cast tells the compiler that we think we know what we are doing. In this case what happens is the least significant 8 bits of the integer value 128 are simply stored in the char. That is, the integer 128 is hexadecimal 0x00000080 and the last part 0x80 is stored in the char a, but now it means -128 because the leftmost bit is a 1, showing it is negative.

 
    int          x = a;
This is perhaps interesting to consider in terms of the internal representation of the value. When the 8-bit value 0x80 is assigned to a 32-bit signed integer, the negative value is represented by a series of binary ones, in hex it is 0xFFFFFF80 In decimal that still means the same as before, -128.

 
    unsigned int y = a;
Here, the same bit pattern as before, hex 0xFFFFFF80 is stored in the variable y. But because y is unsigned, all those one-bits are considered as part of the number which is decimal 4294967168.

 
    int          z = (unsigned char) a;
First the right-hand side is evaluated. As an unsigned char, the value 0x80 means decimal 128. That is the value which is stored in z (0x00000080).

It can be interesting to try out different values using the online converter here:
https://www.mathsisfun.com/binary-decimal-hexadecimal-converter.html

A few comments. Mixing signed and unsigned values in the same statement can be sometimes problematic. Also when using any sort of cast from one type to another there should be some thought given to what may be a risky operation. Stroustrup himself describes c++ casts as ugly, maybe deliberately so in order to remind us that casts are generally best avoided:
http://www.stroustrup.com/bs_faq2.html#static-cast
Last edited on
Topic archived. No new replies allowed.