Hi All, I don't believe this is actually a bug, but can anybody explain why this code works correctly
void func(int v1, int v2){ unsigned char code tbl[] = {'a', 'b', 'c', 'd', 0, '1', '2', '3', '4'}; signed char xdata diff = v1 - v2; if (diff >= -4 && diff <= 4) printf("%c\n", tbl[diff + 4]); }
void func(int v1, int v2){ unsigned char code tbl[] = {'a', 'b', 'c', 'd', 0, '1', '2', '3', '4'}; int xdata diff = v1 - v2; if (diff >= -4 && diff <= 4) printf("%c\n", tbl[diff + 4]); }
You're right, it's not a bug. printf("%c") expects a char, not an int. Keil does not promote variadic function arguments. I am not sure whether this is ANSI compliant or not on a freestanding implementation.
printf("%c") expects a char, not an int.
Sorry, I didn't look closely enough at your example. Can you post a minimal compilable program that shows the problem? You definitely should be able to index the array with either an int or a char.
I cannot properly address elements of the array if I use an int as the index variabe. .... It doesn't happen in other compilers I believe you are relying on a default that legally according to K&R can be whatever. You are comparing signed char with int (signed or unsigned vill vary from compiler to compiler). Thus a compiler that default to signed will work with the above, whereas a compiler that default to unsigned will not. Erik
Can you post a minimal compilable program that shows the problem?
#include <reg51.H> #include <stdio.h> void func(int v1, int v2){ unsigned char code tbl[] = {'a', 'b', 'c', 'd', 0, '1', '2', '3', '4'}; char xdata diff = v1 - v2; if (diff >= -4 && diff <= 4) printf("%c\n", tbl[diff + 4]); } void main(){ SCON = 0x50; /* Setup serial port control register */ /* Mode 1: 8-bit uart var. baud rate */ /* REN: enable receiver */ PCON &= 0x7F; /* Clear SMOD bit in power ctrl reg */ /* This bit doubles the baud rate */ TMOD &= 0xCF; /* Setup timer/counter mode register */ /* Clear M1 and M0 for timer 1 */ TMOD |= 0x20; /* Set M1 for 8-bit autoreload timer */ TH1 = 0xFD; /* Set autoreload value for timer 1 */ /* 9600 baud with 11.0592 MHz xtal */ TR1 = 1; /* Start timer 1 */ TI = 1; /* Set TI to indicate ready to xmit */ func(1, 2); }
"You are comparing signed char with int (signed or unsigned vill vary from compiler to compiler). Thus a compiler that default to signed will work with the above, whereas a compiler that default to unsigned will not." I'm afraid you're way off the mark here. 'int' is always signed, this is a requirement of the language. 'char' may be signed or unsigned according to the implementation. I haven't got time to look into the OP's problem in detail just now, but I'm tending towards a compiler bug.
"This program works (prints 'd'). If you replace char with int, it doesn't." But I notice that if you assign 'diff + 4' to a temporary int and use that as the array index it works correctly. Need to have a look at the listing file to see what's going wrong. Maybe not on a Friday afternoon though..
But I notice that if you assign 'diff + 4' to a temporary int and use that as the array index it works correctly. You're right. If you use a temporary variable for diff + 4, it doesn't matter whether it's an int or a char. Need to have a look at the listing file to see what's going wrong. Maybe not on a Friday afternoon though.. No problem. I can have a look at the listing file myself. Here's what I got:
4: void func(int v1, int v2){ 5: unsigned char code tbl[] = {'a', 'b', 'c', 'd', 0, '1', '2', 6: int xdata diff = v1 - v2; 7: ... C:0x0409 900000 MOV DPTR,#0x0000 ;DPTR = &diff ;diff = -1 = 0xFFFF ... C:0x0419 A3 INC DPTR ;DPTR points to low byte of diff (0xFF) C:0x041A E0 MOVX A,@DPTR ;A = 0xFF C:0x041B 900472 MOV DPTR,#0x0472 ;DPTR = tbl + 4 C:0x041E 93 MOVC A,@A+DPTR ;A = *(tbl + 4 + 0xFF) That's it! C:0x041F F50B MOV 0x0B,A C:0x0421 120065 LCALL PRINTF(C:0065) 10: } 11: C:0x0424 22 RET
stefan, You are right. I have used U8, S8 and thus not had a char or int that was not prefaced by (un)signed for ages. Memory corrected, thanks. Trevelig veckohaelg Erik
"Should I consider this a compiler bug?" Well, I have no other explanation. Could you let us know what version of the compiler you are using?
Well, I have no other explanation. Could you let us know what version of the compiler you are using? Version 7.01. Is that the latest one?
"Version 7.01. Is that the latest one?" 7.20 is the latest. Maybe someone who uses a more recent version than 7.01 could check whether this has been fixed?
I know what a "character" is, but I've always wondered what a negative signed char would be. -A? Is -A less than -Q in lex order, or greater than? And then there's the combinations. Is "-w-o-r-d" the same as "word", while "-t-h-e" is the same as "-the"? Do signed chars cancel out when adjacent in strings, making "bokeper" out of "bo-ok-ke-eper"? 8-bit integers are much easier to understand.
"I know what a "character" is, but I've always wondered what a negative signed char would be." A depressed one? I wonder whether someone from Keil would like to comment on the original thread topic?