C语言中char转int是否恒为正值?断言检查是否冗余?
移除字符频率统计代码中assert语句的必要性分析
我正在编写生产级C代码,需要快速统计字符数组中各字符的出现频率。想移除转换时检查正值的assert语句,请问该断言属于冗余代码还是有保留必要?
char input[] = "Hello World"; int inputLength = sizeof(input)/ sizeof(char); int *frequencies = calloc(256, sizeof(int)); for(int i = 0; i < inputLength-1; i++) { int value = (int) input[i]; assert(value > -1);//Is this line redundant? frequencies[value] += 1; } printf("(%d)", inputLength); PrintFrequencies(frequencies); free(frequencies);
这个断言是否冗余,要结合C语言中char的类型特性和你的生产环境输入场景来判断:
当
char是无符号类型时:这是部分编译器的默认行为,此时input[i]的取值范围是0-255,转换为int后必然是非负数,assert(value > -1)完全是多余的,移除后不会有任何风险,还能减少debug模式下的不必要检查开销。当
char是有符号类型时:input[i]的取值范围是-128到127,如果输入中存在ASCII值大于127的字符(比如扩展ASCII字符),会被解释为负数,转换为int后value为负,此时访问frequencies[value]会触发数组越界,属于未定义行为。但要注意:assert仅在debug模式下生效(未定义NDEBUG宏时),生产环境中会被直接编译掉,没法起到运行时防护作用;- 如果你的生产输入明确只会包含标准ASCII字符(0-127),那这个断言依然是冗余的,因为转换后的
value必然非负; - 如果输入可能包含扩展ASCII字符,更合理的做法是把
char强制转换为unsigned char再转int:int value = (int)(unsigned char)input[i];,这样无论char是有符号还是无符号,value都会落在0-255的合法范围内,此时这个断言就完全没必要保留了。
另外要注意:生产级代码中,assert只适合作为debug阶段的逻辑校验工具,不能替代真正的运行时错误处理。如果需要对输入做合法性检查,应该用if语句配合错误日志、返回码等方式处理,而不是依赖assert。
内容的提问来源于stack exchange,提问作者murage kibicho
相关产品推荐
相关产品推荐

