为何使用strtol函数时未触发ERANGE错误?
问题:为何未触发strtol的ERANGE错误?
#include <stdlib.h> #include <stdio.h> #include <stdbool.h> #include <errno.h> #include <ctype.h> static bool ReadDimensionInt(char **srcptr, int *result, const char *origStr) { char *p = *srcptr; // printf("p=%s\n", p); /* don't accept leading whitespace */ if (!isdigit((unsigned char) *p) && *p != '-' && *p != '+') { *result = 0; return true; /* leave 'src' unmodified */ } errno = 0; *result = strtol(p, srcptr, 10); if (errno == ERANGE) { printf("array bound is out of range\n"); return false; } return true; } int main(void) { char *s = "2147483648111"; char *result; int testresult; bool readok; readok = ReadDimensionInt(&s, &testresult, s); if (readok) printf("test_result=%d\n", testresult); else printf("read dimension failed"); return 0; }
给定上述代码,期望输入字符串"2147483648111"时触发printf("array bound is out of range\n");语句,当前系统中printf("%zu\n", sizeof(long));返回值为8,但实际并未触发ERANGE错误,请问原因是什么?
原因解析
- strtol的处理范围是long类型:你的系统里
long是8字节(64位),能容纳的最大值是9223372036854775807,而输入的2147483648111远小于这个值,所以strtol解析时不会触发范围错误,自然不会设置errno为ERANGE。 - 混淆了long和int的溢出检测:代码里把
strtol返回的long值直接赋值给int变量,但strtol只负责检测自身解析long时的溢出,后续的类型转换溢出属于C语言未定义行为,不会被strtol的ERANGE标记捕获。
修复方案
如果要检测解析值是否超出int的范围,需要在strtol解析后额外判断:
#include <stdlib.h> #include <stdio.h> #include <stdbool.h> #include <errno.h> #include <ctype.h> #include <limits.h> // 引入头文件获取int的范围宏 static bool ReadDimensionInt(char **srcptr, int *result, const char *origStr) { char *p = *srcptr; if (!isdigit((unsigned char) *p) && *p != '-' && *p != '+') { *result = 0; return true; } errno = 0; long temp = strtol(p, srcptr, 10); // 先存到long变量里 if (errno == ERANGE) { printf("array bound is out of range\n"); return false; } // 额外判断是否超出int的范围 if (temp < INT_MIN || temp > INT_MAX) { printf("value exceeds int range\n"); return false; } *result = (int)temp; return true; } int main(void) { char *s = "2147483648111"; char *result; int testresult; bool readok; readok = ReadDimensionInt(&s, &testresult, s); if (readok) printf("test_result=%d\n", testresult); else printf("read dimension failed"); return 0; }
内容的提问来源于stack exchange,提问作者jian
相关产品推荐
相关产品推荐

