Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/60.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/image/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 为什么strtof和strtod的endptr参数是指向非常量字符指针的指针?_C_Libc_Const Correctness - Fatal编程技术网

C 为什么strtof和strtod的endptr参数是指向非常量字符指针的指针?

C 为什么strtof和strtod的endptr参数是指向非常量字符指针的指针?,c,libc,const-correctness,C,Libc,Const Correctness,标准C库函数strof和strod具有以下签名: float strtof(const char *str, char **endptr); double strtod(const char *str, char **endptr); 它们各自将输入字符串str分解为三个部分: 空白的初始序列,可能为空 表示浮点值的字符的“主题序列” 无法识别的字符的“尾随序列”(并且不影响转换) 如果endptr不是NULL,则*endptr设置为指向转换中最后一个字符(即尾随序列的开始)后面的字符的指针

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

float strtof(const char *str, char **endptr);
double strtod(const char *str, char **endptr); 
它们各自将输入字符串
str
分解为三个部分:

  • 空白的初始序列,可能为空
  • 表示浮点值的字符的“主题序列”
  • 无法识别的字符的“尾随序列”(并且不影响转换)
  • 如果
    endptr
    不是
    NULL
    ,则
    *endptr
    设置为指向转换中最后一个字符(即尾随序列的开始)后面的字符的指针


    我想知道:
    endptr
    为什么是指向非
    const
    char
    指针的指针?
    *endptr
    不是指向
    const
    char
    字符串(输入字符串
    str
    )的指针吗
    char*
    可以自动转换为
    const char*
    ,但是
    char**
    不能自动转换为
    const char**
    ,调用函数使用的指针的实际类型(其地址被传递)更可能是
    char*
    。这种自动转换不可能的原因是,有一种不明显的方法可以通过几个步骤来删除
    常量
    限定,其中每个步骤本身看起来都非常有效和正确。Steve Jessop在评论中提供了一个例子:

    如果您可以自动将
    char**
    转换为
    const char**
    ,那么您可以这样做

    char *p;
    char **pp = &p;
    const char** cp = pp;
    *cp = (const char*) "hello";
    *p = 'j';.
    
    为了施工安全,其中一条线路必须是非法的,由于其他线路都是完全正常的操作,因此必须是
    cp=pp

    更好的方法是将这些函数定义为使用
    void*
    代替
    char**
    char**
    const char**
    都可以自动转换为
    void*
    。(受攻击的文本实际上是一个非常糟糕的主意;它不仅阻止任何类型检查,而且C实际上禁止类型为
    char*
    const char*
    的对象访问alias。)或者,这些函数可以使用
    ptrdiff\u t*
    size\u t*
    参数来存储端点的偏移量,而不是指向它的指针。无论如何,这通常更有用


    如果您喜欢后一种方法,可以围绕标准库函数编写这样一个包装器,并调用您的包装器,以便保持代码的其余部分保持干净和无强制转换。

    可用性。
    str
    参数被标记为
    const
    ,因为不会修改输入参数。如果
    endptr
    const
    ,则这将指示调用者不应在输出时更改从
    endptr
    引用的数据,但调用者通常希望这样做。例如,在从字符串中取出浮点数后,我可能希望使用null终止该字符串:

    float StrToFAndTerminate(char *Text) {
        float Num;
    
        Num = strtof(Text, &Text);
        *Text = '\0';
        return Num;
    }
    
    在某些情况下,想要做的事情是完全合理的。如果
    endptr
    的类型为
    const char**
    ,则不起作用


    理想情况下,
    endptr
    的常量应与
    str
    的实际输入常量相匹配,但C无法通过其语法表示这一点。(当描述为什么C#中省略了
    const

    这与
    strchr
    和friends的问题基本相同,只是这里有一个out参数指针而不是返回值。@Steve:是的,但是它比
    strchr
    问题更大,因为如果没有显式强制转换,就无法将
    const
    限定指针的地址传递给这些函数。这是一个有趣的问题。基本上,这意味着您可以在
    strtoX
    函数后面隐藏从
    char const*
    char*
    的强制转换。奇怪。@Jens:这很烦人,但在C语言中这是不可避免的,因为没有函数重载。在C++中,有两个<代码> Schchr 函数,如果输入为“代码> char *<代码>,而代码为> const char *<代码>,如果输入为“代码> const char */COD>”,则返回<代码> char */COD>。在C++标准中没有这样的代码< Strut/<代码>的重载,但我不知道它的原理。在任何人提问之前,C++中没有<代码> Sttoof ,因为它不是在C89中。搜索显示,我很长一段时间都不知道这个基本原理:“无论是
    char**
    还是
    const char**
    都可以自动转换为void*”我明白你的意思,使用
    void*
    可以让用户无需强制转换就可以传入
    const char**
    。但这也会让他们在一个充满错误的世界里无需施法。考虑到C语言的局限性,我认为最好保留基本的类型安全性,甚至是失去const-safety的代价。这不仅仅是可用性,这些函数存储的结果是指针,你不能写入常量内存。“如果有人拥有它,请发布。”-如果您可以自动将
    char**
    转换为
    const char**
    ,则可以执行
    char*p;字符**pp=&p;常量字符**cp=pp*cp=(常量字符*)“你好”*p='j'。为了施工安全,其中一条线路必须是非法的,由于其他线路都是完全正常的操作,因此必须是
    cp=pp。偏移量当然可以解决常量问题,尽管现在在整个库中一致使用该约定为时已晚,而且在
    const
    发明时它可能已经太破坏性了,我不确定。如果字符串处理函数返回偏移量而不是指针是正常的,那么strcpy是否总是返回0?;-)理想情况下
    str