You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 19:44:59