-2

I was doing this simple program and my mind got stuck

    #include<stdio.h>

    int main()
    {
        signed int a;
        signed char c;
        unsigned char b;
        b = 0xf4;
        a = (signed)b;       //    1)this assignment should be same 
        c = (signed)b;
        printf("%d\n",a);
        a = c;              //     2)as this one
        printf("%d \n",a);
        return 0; 
    }

a = 244, a = -12

I tried to make sure that assignment is as smooth as it can be but I am getting two different answers and I expected both as -12. What small thing I am missing?


The relevant question was

{
    b = 0xf4;
    c = 0xf4;
    a = (signed int)b;           //trying to save sign but get 244 
    printf("%d\n", a);
    a = c;                       //sign saved here and got -3 
    printf("%d", a);
}

244, -3

so i am trying to save the sign from an unsigned char. Is this possible in this manner?

mrigendra
  • 1,472
  • 3
  • 19
  • 33
  • 2
    Your compiler is seriously broken if you get -3 - it should be -12: http://ideone.com/kgBTUS – Paul R Jun 11 '14 at 07:22
  • I guess it's because of the type conversion char-int. – user3085931 Jun 11 '14 at 07:24
  • 2
    I'm not a C rockstar. I think casting in `(signed)` both `int` and `char` is wrong. It should be `(signed int)` and `(signed char)` – Glenn Jun 11 '14 at 07:24
  • 2
    @Glenn I would have said the same thing. `signed` is as far as I know the same type as `int`. So he is casting it to int and saving it in a char. – Tim Seguine Jun 11 '14 at 07:25
  • 1
    @mrigendra: Editing the question to be more correct after someone told you an error, and staying silent about it, is not ok ... what´s the point in the answer/comment then? – deviantfan Jun 11 '14 at 07:25
  • 4
    This is relying on integer overflow, and is thus technically undefined behaviour. – Oliver Charlesworth Jun 11 '14 at 07:26
  • 2
    @OliCharlesworth no undefined behavior here, implementation defined integer conversion to a narrower signed type as ruled by 6.3.1.3p3 in c99. – ouah Jun 11 '14 at 07:29
  • @ouah: yup, you are correct. – Oliver Charlesworth Jun 11 '14 at 07:29
  • 1
    @TimSeguine You're both correct. `signed` cast is equivalent to `signed int`. The former of the two, `a = (signed)b;` is valid and fully supported through integer promotions and value-conversion. The latter is implementation defined only. – WhozCraig Jun 11 '14 at 07:29
  • @WhozCraig it doesn't really seem to have an effect. I am guessing because one fits in the target type and the other doesn't – Tim Seguine Jun 11 '14 at 07:34

4 Answers4

4
    signed char c;
    unsigned char b;
    b = 0xf4;

    /* ... */

    c = (signed)b;

The value of b is 0xf4 (244) but c type (signed char) can only hold values between -128 and 127 (in your implementation). So when 244 is assigned to c it is first converted to signed char and C says this integer conversion is implementation defined. gcc as most implementations just wraps around modulo 256 and that's why the value of c is -12.

Here is gcc documentation:

http://gcc.gnu.org/onlinedocs/gcc/Integers-implementation.html

"For conversion to a type of width N, the value is reduced modulo 2^N to be within range of the type"

ouah
  • 142,963
  • 15
  • 272
  • 331
1

The Problem is located here:

c = (signed)b;

casting the value of b, 244, to a signed char leads to an integer overflow, resulting in the value of -12 that you see. Changing the type of c to signed int solves the issue.

techshack
  • 359
  • 2
  • 18
  • 1
    You will get same results even if you do not typecast – Vagish Jun 11 '14 at 07:34
  • @Vagish Even without a cast, the value is **converted** to the type of `c` on assignment. This answer is using the word “cast” incorrectly to refer to the conversion on assignment. – Pascal Cuoq Jun 11 '14 at 07:39
  • Thats what I am trying to say,It is not a problem it is expected behavior.I always load 0xff to signed char to interpret as '-1' – Vagish Jun 11 '14 at 07:42
1

To my understanding, the output of 244 is correct. First, b is initialized to a value of 244 expressed as as a hexadecimal literal, which is then cast to the signed int a, which can hold the value of 244. According to the specification of printf format strings, the output of 244 is what is to be expected.

Codor
  • 17,447
  • 9
  • 29
  • 56
0

Event if You do not typecast 'b' by signed you will get same results.

In first assignment

a = (signed)b;

you are loading a signed int(16bit/32bit/64bit) with 0xf4 which it can hold,and as msb is '0' the result will be 244.

If your int would have been 8 bits long then the result will be '-12'.

In second case you must get '-12' because 2's complement of '-12' is 0xf4.

Vagish
  • 2,520
  • 19
  • 32