4.5.断言

_nassert 内在函数不会生成任何代码,因此不是典型的编译器内在函数。相反,该函数告知编译器使用 assert 函数声明的表达式为真。它可用于断言某些条件为真,而编译器又可以在其优化期间使用它。

警告

如果 _nassert 中指定的条件为假,则代码会在运行时失败。

列表 4.12 显示了使用 _nassert 的示例。在本例中,编程器保证循环至少执行一次,且 count 是 4 的倍数。这使编译器能够避免生成代码以在展开期间检查 count==0和剥离迭代。

列表 4.12 使用 nassert 避免生成不必要的检查
1 2 3 4 5 6 7 8 9 10 11 12 13 14
#include<stdint.h>int16_tsum(int16_t*input,int16_tcount){int16_tsum=0;int16_ti=0;_nassert(count>0&&count%4==0);for(i=0;i<count;i++)sum+=input[i];returnsum;}

表 4.6 显示了在不使用和使用 _nassert 的情况下生成的汇编代码。

表 4.6 汇编代码比较
使用 _nassert 时生成的 Asm(循环展开了 4 倍) 未使用 _nassert 时生成的 Asm(循环展开了 2 倍)
||sum||: MOV AH,AL MOVB AL,#0 ASR AH,2 ADDB AH,#-1 MOVZ AR6,AH ||$C$L1||: ADD AL,*XAR4++ ADD AL,*XAR4++ ADD AL,*XAR4++ ADD AL,*XAR4++ BANZ ||$C$L1||,AR6-- LRETR
||sum||: MOV AH,AL MOVB XAR7,#0 BF ||$C$L4||,LEQ CMPB AH,#2 BF ||$C$L1||,GEQ MOV PL,#0 BF ||$C$L3||,UNC ||$C$L1||: AND AH,AH,#0xfffe MOV PL,AH MOVL XAR5,XAR4 MOV AH,AL ASR AH,1 ADDB AH,#-1 MOVZ AR6,AH ||$C$L2||: MOV AH,AR7 ADD AH,*XAR5++ ADD AH,*XAR5++ MOVZ AR7,AH BANZ ||$C$L2||,AR6-- ||$C$L3||: TBIT AL,#0 BF ||$C$L4||,NTC MOVL ACC,XAR4 SETC SXM ADD ACC,PL MOVL XAR4,ACC MOV AL,AR7 ADD AL,*+XAR4[0] MOVZ AR7,AL ||$C$L4||: MOV AL,AR7 LRETR