This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

bug in the compiler??

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]);

}
and this doesn't?
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]);

}
Is this behaviour ANSI-compliant?

Cheers

  • 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.
    
    That's right, and it gets one. In fact, the printf is irrelevant here - I put it there just to make my example more clear. The problem is that I cannot properly address elements of the array if I use an int as the index variabe. Is this correct behaviour? It doesn't happen in other compilers.

  • 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?
    There you go.
    #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);
    }
    
    This program works (prints 'd'). If you replace char with int, it doesn't.

  • "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
    
    Obviously this code takes a character at address tbl + 4 + 0xFF instead of tbl + 4 - 1. Should I consider this a compiler bug?

  • 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?

  • "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?