根据http://www.cplusplus.com/reference/cstdlib/strtol/,此函数的签名为long int strtol (const char* str, char** endptr, int base)
。
但我想知道:如果它在字符串的开头传递了一个const char *
,它如何在不作弊的情况下将其转换为指向第一个未处理字符的非const指针?不执行const_cast的strtol实现会是什么样子?
根据http://www.cplusplus.com/reference/cstdlib/strtol/,此函数的签名为long int strtol (const char* str, char** endptr, int base)
。
但我想知道:如果它在字符串的开头传递了一个const char *
,它如何在不作弊的情况下将其转换为指向第一个未处理字符的非const指针?不执行const_cast的strtol实现会是什么样子?
4条答案
按热度按时间0yg35tkg1#
在const-correctness下如何实现
strtol
?你没有,因为
strtol
的定义本质上不是const
-正确的。这是C标准库中的一个缺陷。
有几个标准函数接受一个
const char*
参数(预期指向字符数组的开头),并给予一个非const
char*
指针,可用于修改该数组。strchr
就是一个例子:字符串
举例来说:
型
这个程序有未定义的行为。在我的系统上,它由于分段错误而死亡。
strchr
本身并没有出现这个问题,它承诺不会修改你传递给它的字符串,它确实没有修改,但是它返回了一个指针,调用者可以用这个指针来修改它。早在20世纪80年代后期,ANSI C委员会就将每个这样的函数分成两个版本,一个作用于
const
字符数组,另一个作用于非const
数组:型
但这会破坏在
const
出现之前编写的ANSI之前的代码,这和C没有将字符串字面量设为const
的原因是一样的。C继承了C的大部分标准库,通过提供一些函数的重载版本来处理这个问题。
底线是,作为一名C程序员,你有责任不修改你定义为
const
的对象。在大多数情况下,语言会帮助你强制执行这一点,但并不总是如此。至于这些函数如何设法返回一个指向
const
数据的非const
指针,它们可能只是在内部使用了一个强制转换(而不是const_cast
,它只存在于C中)。最新消息:即将到来的C23标准,改变了几个字符串函数(
memchr
,strchr
,strpbrk
,strrchr
,strstr
)到通用函数来解决这个问题,但截至N3054草案,这种变化还没有应用于strtol
等。我会联系标准的编辑,但要改变这一点可能为时已晚bqucvtff2#
很有可能它只是使用铸造。
在标准库中有许多函数都有相同的属性,牺牲类型安全而不是简单性可能是原因,因为你不能像C++那样重载函数。
他们希望程序员承担责任,如果
str
是一个字符串文字,就不编辑endptr
。由于其有限的类型系统,C是实用的人的实用语言。
fwzugrvs3#
strtol
确实执行了const_cast
(或等效的)。将const
强制转换不是问题,使用结果指针来修改原始的-const
指针可能会有问题。但是
strtol
只是将这个指针返回给你而没有篡改它,所以一切都很好。k5ifujac4#
如何在const-correctness下实现strtol?
使用C11
_Generic
将允许代码调用字符串
下面的实现是相同的,因为只需要保留函数签名。因为这与
strtol()
不同,它应该被称为其他东西,如strtol_s()
。型
丢失的内容:
strtol_s()
不是一个真正的函数,因此无法创建指向它的指针。它是如何在不作弊的情况下将其转换为指向第一个未处理字符的非常量指针的?
strtol()
,尽管它接受char **endptr
作为第二个参数,但不会修改*endptr
。