23

标准 C 库函数strtofstrtod具有以下签名:

float strtof(const char *str, char **endptr);
double strtod(const char *str, char **endptr); 

它们每个都将输入字符串 , 分解str为三个部分:

  1. 一个初始的、可能为空的空白序列
  2. 表示浮点值的字符“主题序列”
  3. 无法识别(并且不影响转换)的字符“尾随序列”。

如果endptr不是NULL,则*endptr设置为指向紧随作为转换一部分的最后一个字符的字符的指针(换句话说,尾随序列的开始)。

我想知道:为什么 是endptr指向const char指针的指针?不是*endptr指向const char字符串(输入字符串str)的指针吗?

4

2 回答 2

11

原因只是可用性。char *可以自动转换为const char *,但char **不能自动转换为const char **,调用函数使用的指针(其地址被传递)的实际类型char *const char *. 无法进行这种自动转换的原因是,有一种不明显的方法可以const通过几个步骤来删除限定,其中每个步骤本身看起来都完全有效和正确。Steve Jessop 在评论中提供了一个例子:

如果您可以自动转换char**const char**,那么您可以

char *p;
char **pp = &p;
const char** cp = pp;
*cp = (const char*) "hello";
*p = 'j';.

对于 const-safety,其中一行必须是非法的,并且由于其他行都是完全正常的操作,因此它必须是cp = pp;

一个更好的方法是定义这些函数来void *代替char **. 两者char **const char **都可以自动转换为void *. (有问题的文本实际上是一个非常糟糕的主意;它不仅阻止了任何类型检查,而且 C 实际上禁止类型对象char *const char *别名。)或者,这些函数可以采用一个ptrdiff_t *orsize_t *参数来存储偏移量end,而不是指向它的指针。无论如何,这通常更有用。

如果您喜欢后一种方法,请随意围绕标准库函数编写这样的包装器并调用您的包装器,以保持其余代码的const清洁和无强制转换。

于 2010-10-06T15:41:35.067 回答
5

可用性。该str参数被标记为,const因为输入参数不会被修改。如果endptrconst,那么这将指示调用者他不应该更改从endptr输出中引用的数据,但调用者通常只想这样做。例如,我可能想在得到浮点数后对字符串进行空终止:

float StrToFAndTerminate(char *Text) {
    float Num;

    Num = strtof(Text, &Text);
    *Text = '\0';
    return Num;
}

在某些情况下,想要做的事情是完全合理的。endptr如果是 type则不起作用const char **

理想情况下,endptr应该是 const-ness 与 的实际输入 const-ness 相匹配str,但 C 无法通过其语法来表明这一点。( Anders Hejlsberg在描述为什么被排除在 C# 之外时谈到了这一点。)const

于 2010-10-06T15:58:19.250 回答