Dan*_*ien 22 c const-correctness std
标准C库函数strtof并strtod具有以下签名:
float strtof(const char *str, char **endptr);
double strtod(const char *str, char **endptr);
Run Code Online (Sandbox Code Playgroud)
它们将输入字符串分解str为三部分:
如果endptr不是NULL,则*endptr设置为指向紧跟在转换的一部分的最后一个字符之后的字符的指针(换句话说,尾随序列的开始).
我想知道:endptr那么,为什么指向非const char指针?不是*endptr指向const char字符串的指针(输入字符串str)?
R..*_*R.. 11
原因很简单.char *可以自动转换到const char *,但char **不能自动转换为const char **,并通过调用函数使用的指针(其地址被传递)的实际类型更可能是char *比const char *.这种自动转换不可能的原因是,有一种非显而易见的方法可以const通过几个步骤来删除资格,其中每个步骤看起来完全有效并且本身是正确的.Steve Jessop在评论中提供了一个例子:
如果你可以自动转换
char**为const char**,那么你可以做到Run Code Online (Sandbox Code Playgroud)char *p; char **pp = &p; const char** cp = pp; *cp = (const char*) "hello"; *p = 'j';.对于const-safety,其中一条线必须是非法的,并且由于其他线都是完全正常的操作,因此必须如此
cp = pp;
一种更好的方法是定义这些函数来(被击中后的文本实际上是一个非常糟糕的主意,它不仅能防止任何类型检查,但是C实际上禁止类型的对象void *代替char **.双方char **并const char **可以自动转换到void *.char *和const char *别名).此外,这些功能可能已经采取了ptrdiff_t *或size_t *在哪个参数存储偏移的结束,而不是指向它的指针.无论如何,这通常更有用.
如果您喜欢后一种方法,请随意在标准库函数周围编写这样的包装器并调用您的包装器,以便保留其余的代码 - const清理和无转换.
可用性.该str说法被标记为const,因为输入参数将不会被修改.如果endptr是const,则会告诉调用者他不应该更改从endptr输出引用的数据,但通常调用者想要这样做.例如,我可能希望在获取浮点数后终止字符串:
float StrToFAndTerminate(char *Text) {
float Num;
Num = strtof(Text, &Text);
*Text = '\0';
return Num;
}
Run Code Online (Sandbox Code Playgroud)
在某些情况下,想做的事情是完全合理的.如果endptr属于类型则不起作用const char **.
理想情况下,endptr应该是与实际输入常量匹配的常量str,但C无法通过其语法指示这一点.(Anders Hejlsberg在描述为什么const被排除在C#之外时会谈到这一点.)
| 归档时间: |
|
| 查看次数: |
5417 次 |
| 最近记录: |