blarson@oberon.UUCP (Bob Larson) (01/21/86)
[This is an expantion/clarifacation of a previous article I canceled a few hours after posting. Apologies if the cancel did not work correctly.] In a program I am writing, I want to sign extend the eight least significant bits of an unsigned variable to an int. Given that char is an 8-bit and signed (not a completly portable assumption, but true on the machine in question), assigning to a char and then to an int will cause the sign extention I want. Not wanting an extra temporary variable, I decided that double casting would do what I want: intvar=(int)(char)unsignedvar; Upon examining the code produced, I found the later did not work correctly. K&R (section 2.7) and two other C compilers agree with my interpritaion. Below is a program that tests this problem. A C compiler validation suite should include a program that tests this use of casts. If you would like to add a result to my table send it to me via mail, and I will repost the table if warented. Machine os compiler #bad of possible Vax 750 4.2BSD cc 0 9 Prime Primos cc 19.4 0 9 QT+ os9/68k microware 1.3 9 9 --Cut here-- /* Program to test sign extention by casting, by Robert A. Larson */ /* send results to ihnp4!sdcrdcf!oberon!blarson or blarson@usc-ecl.arpa */ /* note this program assumes 8-bit characters, and character tests are not valid otherwise */ /* note this program assumes 16-bit shorts, and short tests are not valid otherwise */ /* if sizeof(int) != sizeof(short) && sizeof(int) != sizeof(long) int to long expation testing should be added */ /* comment out as appropriate */ /* #define signedchar /* declaration "signed char" allowed */ #define unsigchar /* declaration "unsigned char" allowed */ #define unsigshort /* declaration "unsigned short" allowed */ #define unsiglong /* declaration "unsigned long" allowed */ main(){ int bad=0, possible=0; char c; #ifdef signedchar signed char sc; #endif #ifdef unsigchar unsigned char uc; #endif short s; #ifdef unsigshort unsigned short us; #endif int i; unsigned u; long l; #ifdef unsiglong unsigned long ul; #endif u=0x1ff; c=(char)u; if(c<0) printf("Characters are signed.\n"); if(((char)u) != c){ printf("((char)u) != c\n"); bad++; } possible++; if(((int)(char)u) != (int)c){ printf("((int)(char)u) != (int)c\n"); bad++; } possible++; i=(int)c; if(((int)(char)u) != i){ printf("((int)(char)u) != i\n"); bad++; } possible++; #ifdef signedchar sc=(signed char)u; if(sc>=0) printf("??? signed char are not signed.\n"); if(((signed char)u) != sc){ printf("((signed char)u) != sc\n"); bad++; } possible++; if(((int)(signed char)u) != (int)sc){ printf("((int)(signed char)u) != (int)sc\n"); bad++; } possible++; i=(int)sc; if(((int)(signed char)u) != i){ printf("((int)(signed char)u) != i\n"); bad++; } possible++; #endif if(sizeof(int)>2){ u=0x1ffff; s=(short)u; if(((short)u) != s){ printf("((short)u) != s\n"); bad++; } possible++; if(((int)(short)u) != (int)s){ printf("((int)(short)u) != (int)s\n"); bad++; } possible++; i=(int)s; if(((int)(short)u) != i){ printf("((int)(short)u) != i\n"); bad++; } possible++; #ifdef unsigshort us=(unsigned short)u; if(((unsigned short)u) != us){ printf("((unsigned short)u) != us\n"); bad++; } possible++; if(((int)(unsigned short)u) != (int)us){ printf("((int)(unsigned short)u) != (int)us\n"); bad++; } possible++; i=(int)us; if(((int)(unsigned short)u) != i){ printf("((int)(unsigned short)u) != i\n"); bad++; } possible++; #endif } printf("%d bad out of a possible %d.\n",bad,possible); } -- Bob Larson Arpa: Blarson@Usc-Ecl.Arpa Uucp: ihnp4!sdcrdcf!oberon!blarson