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

C99中strtol(str, &str, 10)是否违反restrict别名规则?

strtol调用的restrict约束合规性问题

先看这段代码:

char *str = "1234";
long n = strtol(str, &str, 10);

C99中strtol()的原型为:

long strtol(const char *restrict nptr, char **restrict endptr, int base);

我的问题是:该调用是否违反restrict约定并产生未定义行为?我曾见过类似问题,但现有回答缺乏足够解释,无法消除我的疑惑。


我的分析如下

  • const char *restrict nptr向编译器承诺:nptr是访问字符串"1234"所在内存区域的唯一途径。
  • char **restrict endptr向编译器承诺:endptr是访问变量str的唯一途径。

调用时的假设场景:

  • 字符串"1234"位于地址0x100
  • 变量str位于地址0x500

此时:

  • nptr = 0x100(指向字符串)
  • endptr = 0x500(指向变量str)

这两个指针本身指向不同的内存位置,因此从表面看nptr和endptr直接遵守了restrict约束。

但需要注意,nptr和*endptr指向同一地址。当strtol写入*endptr = ...时,它仅修改变量str,并未直接访问字符串"1234"。只有当strtol()通过**endptr进行双重解引用时,才会通过endptr访问该字符串。

如果strtol()的某个实现出于任何原因通过**endptr访问字符串"1234",那么调用strtol(str, &str, 10)时,nptr的restrict承诺将被违反——因为该字符串将通过nptr以外的指针被访问。


具体问题

根据C99的§6.7.3.1,这是否构成restrict违规?具体而言:

  1. endptr上的restrict仅约束endptr本身,还是也约束*endptr与nptr的关系?
  2. 即使endptr和nptr本身不同,若*endptr与nptr指向同一内存,是否足以产生未定义行为?
  3. 若某个假设的strtol()实现通过**endptr访问字符串"1234",是否会被视为不符合C99标准?

问题解答

1. endptr的restrict约束范围

char **restrict endptr中的restrict仅约束指针endptr本身的访问:它承诺在strtol的执行期间,endptr指向的内存(即变量str的地址)只能通过endptr来访问,不能通过其他指针别名修改或读取这个内存位置。

这个restrict修饰符不会直接约束*endptr(也就是str变量的值,即指向字符串的指针)与nptr的关系——restrict的约束是针对它所修饰的指针的指向对象,而非指针指向对象的指向对象。

2. *endptr与nptr指向同一内存是否触发未定义行为?

不会直接触发。根据C99 §6.7.3.1的规则,restrict的核心约束是:如果两个restrict指针指向的内存区域存在重叠,那么在函数执行期间,不能通过其中一个指针修改内存,同时通过另一个指针访问该内存。

在这个调用场景中:

  • nptr指向的是字符串常量"1234"的内存(只读),strtol不会修改这个区域;
  • endptr指向的是变量str的内存,strtol会修改*endptr(即str的值),但这个修改操作和nptr指向的字符串内存无关——因为修改的是str变量本身,而非字符串内容。

只有当strtol通过**endptr去访问nptr指向的字符串时,才会违反nptr的restrict承诺:因为此时字符串内存被同时通过nptr和*endptr(即修改前的str)访问了。但只要strtol的实现不做这种操作,就不存在违规。

3. 通过**endptr访问字符串的strtol实现是否符合标准?

不符合。C99标准对strtol的行为有明确要求:它应当通过nptr来扫描输入字符串,而endptr的作用仅用于存储第一个无法转换的字符的地址。标准中没有任何允许strtol通过**endptr访问输入字符串的条款,这种实现属于超出标准规范的行为,是不符合C99标准的。

实际上,所有符合标准的strtol实现都会仅通过nptr来访问输入字符串,不会去解引用endptr指向的指针(即*endptr)来访问字符串,因此你的调用方式在符合标准的实现中是安全的,不会触发未定义行为。


内容的提问来源于stack exchange,提问作者Parminder Singh

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.01 17:03:15