INF: Mixed Expressions Can Cause Unsigned Division

ID Number: Q34920

5.10 6.00 6.00a 6.00ax 7.00 | 5.10 6.00 6.00a

MS-DOS | OS/2

Summary:

The ANSI C standard specifies that when a signed and unsigned integer

are involved in an arithmetic expression, the signed integer is to be

converted to the type of the unsigned before expression evaluation. If

the signed integer is negative, the sign will be lost and the value

will change, even though the bit pattern will remain the same.

This situation is especially a problem with functions that return a

value of type size_t, which is an alias for unsigned int in our

implementation. Note that this is not a problem or a code generation

error, this is the expected behavior.

More Information:

For example, if the following statement

i = (4 - strlen( "1234567890" )) / 2;

is executed, the value of i will be 32765 rather than -3 as one might

expect, because the expression [4 - strlen("1234567890")] is an

unsigned integer expression with the value of 65530 rather than a

signed expression with the value of -6. If you look at the code

generated, you'll notice that an instruction that performs unsigned

division is generated rather than a one that performs signed division.

To avoid this behavior, use a typecast on the return value of strlen()

so that it is treated as an int. For example, the statement above will

become the following:

i = (4 - (int) strlen( "1234567890" )) / 2;

Note that even this code will fail if the length of the string is

greater than 32767; however, the incorrect code above fails if the

length of the string is greater than four.

Run-time functions that return values of type size_t, unsigned, or

unsigned long include the following:

_bios_disk _dos_freemem _fmsize fwrite

_bios_equiplist _dos_getdate _getlinestyle stackavail

_bios_keybrd _dos_getdiskfree _lrotl strcspn

_bios_memsize _dos_getfileattr _lrotr strlen

_bios_printer _dos_getftime _memavl strspn

_bios_serialcom _dos_gettime _memmax strtoul

_bios_timeofday _dos_open _msize

_clear87 _dos_read _nmsize

_control87 _dos_setblock _rotl

_dos_allocmem _dos_setdate _rotr

_dos_close _dos_setfileattr _status87

_dos_creat _dos_setftime FP_OFF

_dos_creatnew _dos_settime FP_SEG

_dos_findfirst _dos_write fread

_dos_findnext

Additional reference words: 5.00 5.10 6.00 6.00a 6.00ax 7.00