NOTE. See my changes below.
ORIGINAL QUESTION:
There was some curious behavior that I can’t put up with:
#if -5 < 0
#warning Good, -5 is less than 0.
#else
#error BAD, -5 is NOT less than 0.
#endif
#if -(5u) < 0
#warning Good, -(5u) is less than 0.
#else
#error BAD, -(5u) is less than 0.
#endif
#if -5 < 0u
#warning Good, -5 is less than 0u.
#else
#error BAD, -5 is less than 0u.
#endif
When compiling:
$ gcc -Wall -o pp_test.elf pp_test.c
pp_test.c:2:6: warning: #warning Good, -5 is less than 0.
pp_test.c:10:6: error: #error BAD, -(5u) is less than 0.
pp_test.c:13:9: **warning: the left operand of "<" changes sign when promoted**
pp_test.c:16:6: error: #error BAD, -5 is less than 0u.
This suggests that the preprocessor adheres to type promotion rules when evaluating constant integer expressions. Namely, when the operator has mixed-sign operands, the signed operand is replaced with the unsigned operand. The opposite (in general) is true in C.
I cannot find anything in the literature to support this, but is it possible (probably?) That I am not thorough enough. Did I miss something? Is this behavior right?
, , #if #elif, , , .. C.
EDIT:. Sourav Ghosh, , , L LL. , , . :
#if -5LL < 0L
#warning Good, -5LL is less than 0L.
#else
#error BAD, -5LL is NOT less than 0L.
#endif
#if -(5uLL) < 0L
#warning Good, -(5uLL) is less than 0L.
#else
#error BAD, -(5uLL) is less than 0L.
#endif
#if -5LL < 0uL
#warning Good, -5LL is less than 0uL.
#else
#error BAD, -5LL is less than 0uL.
#endif
:
$ gcc -Wall -o pp_test.elf pp_test.c
pp_test.c:2:6: warning: #warning Good, -5LL is less than 0L.
pp_test.c:10:6: error: #error BAD, -(5uLL) is less than 0L.
pp_test.c:13:9: warning: the left operand of "<" changes sign when promoted
pp_test.c:16:6: error: #error BAD, -5LL is less than 0uL.
, -, 6.3.1.8, , Sourav Ghosh ( ):
, , .
, , -5LL , , 0uL, , (signed long long) (unsigned long). , .
https://gcc.gnu.org/onlinedocs/gcc-3.0.2/cpp_4.html ( ):
. , ; , GCC, 64 . , . , `#if ', ; .
, " , ", , , " " . , -5 -5L , -5LL, 0u 0uL , 0uLL. , Sourav Ghosh, .
, , , , . , ?
№ 2: , - , ( Optiboot).
#ifndef BAUD_RATE
#if F_CPU >= 8000000L
#define BAUD_RATE 115200L
#elif F_CPU >= 1000000L
#define BAUD_RATE 9600L
#elif F_CPU >= 128000L
#define BAUD_RATE 4800L
#else
#define BAUD_RATE 1200L
#endif
#endif
#ifndef UART
#define UART 0
#endif
#define BAUD_SETTING (( (F_CPU + BAUD_RATE * 4L) / ((BAUD_RATE * 8L))) - 1 )
#define BAUD_ACTUAL (F_CPU/(8 * ((BAUD_SETTING)+1)))
#define BAUD_ERROR (( 100*(BAUD_ACTUAL - BAUD_RATE) ) / BAUD_RATE)
#if BAUD_ERROR >= 5
#error BAUD_RATE error greater than 5%
#elif (BAUD_ERROR + 5) <= 0
#error BAUD_RATE error greater than -5%
#elif BAUD_ERROR >= 2
#warning BAUD_RATE error greater than 2%
#elif (BAUD_ERROR + 2) <= 0
#warning BAUD_RATE error greater than -2%
#endif
volatile long long int baud_setting = BAUD_SETTING;
volatile long long int baud_actual = BAUD_ACTUAL;
volatile long long int baud_error = BAUD_ERROR;
void foo(void) {
baud_setting = BAUD_SETTING;
baud_actual = BAUD_ACTUAL;
baud_error = BAUD_ERROR;
}
AVR:
$ avr-gcc -Wall -c -g -save-temps -o optiboot_pp_test.elf -DF_CPU=8000000L optiboot_pp_test.c
, F_CPU .
optiboot_pp_test.c:28:6: warning: #warning BAUD_RATE error greater than -2% [-Wcpp]
#warning BAUD_RATE error greater than -2%
, . :
baud_setting = BAUD_SETTING;
8: 88 e0 ldi r24, 0x08 ; 8
a: 90 e0 ldi r25, 0x00 ; 0
c: a0 e0 ldi r26, 0x00 ; 0
e: b0 e0 ldi r27, 0x00 ; 0
10: 80 93 00 00 sts 0x0000, r24
14: 90 93 00 00 sts 0x0000, r25
18: a0 93 00 00 sts 0x0000, r26
1c: b0 93 00 00 sts 0x0000, r27
baud_actual = BAUD_ACTUAL;
20: 87 e0 ldi r24, 0x07 ; 7
22: 92 eb ldi r25, 0xB2 ; 178
24: a1 e0 ldi r26, 0x01 ; 1
26: b0 e0 ldi r27, 0x00 ; 0
28: 80 93 00 00 sts 0x0000, r24
2c: 90 93 00 00 sts 0x0000, r25
30: a0 93 00 00 sts 0x0000, r26
34: b0 93 00 00 sts 0x0000, r27
baud_error = BAUD_ERROR;
38: 8d ef ldi r24, 0xFD ; 253
3a: 9f ef ldi r25, 0xFF ; 255
3c: af ef ldi r26, 0xFF ; 255
3e: bf ef ldi r27, 0xFF ; 255
40: 80 93 00 00 sts 0x0000, r24
44: 90 93 00 00 sts 0x0000, r25
48: a0 93 00 00 sts 0x0000, r26
4c: b0 93 00 00 sts 0x0000, r27
... , . , baud_setting 8, baud_actual 111111, baud_error -3.
F_CPU, ( ):
$ avr-gcc -Wall -c -g -save-temps -o optiboot_pp_test.elf -DF_CPU=8000000UL optiboot_pp_test.c
optiboot_pp_test.c:22:6: error: #error BAUD_RATE error greater than 5%
#error BAUD_RATE error greater than 5%
.
, , F_CPU.
, , , .
, , GCC ( ).
, C , , . - , , , L LL, LL , , 6.3.1.8, GCC. GCC, , " , ".
( ) , , , , . , , , , . , . , , , , ( ) , .
- - , GCC, .
№ 3: . , .
- - , , GCC, .
6.10.1:
- , , intmax_t uintmax_t, < stdint.h > .
, , .