Unsigned Character Indexes with /O1a Can Create Invalid Code

ID Number: Q61974

5.10 | 5.10

MS-DOS | OS/2

buglist5.10 fixlist6.00

Summary:

When an unsigned character variable is used to index the first 256

elements of an array whose size is greater than 256, erroneous results

may occur. This problem occurs when the variable is declared locally

and maximum optimization (Ox) or loop optimization is enabled with

relaxed alias checking (Ola). To work around this problem, either

declare the unsigned character variable outside of main, or do not use

the aforementioned compiler options, or both.

Sample Code

-----------

/* Compile with /Ox or /Ola to illustrate the problem. */

#include <stdio.h>

void main(void)

{

int i, data[512];

unsigned char c; /* For correct results, make this global. */

for (i=0; i<512; i++)

data[i] = i;

for (c=0; c<256; c++) /* Compare c to 256 to illustrate the */

/* problem. */

printf("data[%d] = %d\n", (int)c, data[c]);

}

More Information:

The problem lies mostly in the fact that overflow conditions are

undefined. Because the compiler can do whatever it wants in an

overflow situation, programmers should not write code that relies on a

specific behavior occuring during an overflow situation.

In this particular case, the compiler puts the address of the start of

the array in a 16-bit register (SI). After each iteration of the loop,

the register is incremented by 2 to account for the 2-byte shift for

the next element of the array. If the loop were to actually stop at

255, this behavior would work fine. However, in this case, when the

loop counter resets to 0 (zero), the register is not reset and

continues incrementing until a protection violation (OS/2) occurs or

the program crashes (DOS). This problem is caused by a failure to

execute an "AND SI, 255" instruction after each increment.

Microsoft has confirmed this to be a problem with C version 5.10. This

problem was corrected in C 6.00, which will now perform the required

"AND" instruction.