c:strtod:双指针与单指针的引用

时间:2018-02-02 22:22:18

标签: c pointers

效果很好。

#include <stdio.h>
#include <stdlib.h>
int main(void){
  char number[]= "a123.45", *strtod_eptr;
  double num;

  num=strtod(number, &strtod_eptr);
  if (strtod_eptr == number){
    printf("Error: no number found.\n");
  }
  else{ printf("%f\n", num+7);
  }

  return 0;
 }

不起作用。 strtod()中的第二个参数改变了类型。

#include <stdio.h>
#include <stdlib.h>
int main(void){
    char number[]= "a123.45", **strtod_epptr;
    double num;

    num=strtod(number, strtod_epptr);
    if (*strtod_epptr == number){
        printf("Error: no number found.\n");
    }
    else{
        printf("%f\n", num+7);
    }

return 0;
}

编译器警告未初始化的strtod_epptr但没有编译错误。

strol_test.c:7:5: warning: ‘strtod_epptr’ is used uninitialized in this function [-Wuninitialized]

程序在if()语句中崩溃(seg fault)。

编译器命令(在两种情况下):

gcc -Wall -pedantic -o "strol_test" "strol_test.c"

为什么会这样?为什么gcc抱怨未初始化的** strtod_epptr虽然完全没问题(类似未初始化?)* strtod_eptr? 解除引用** strtod_epptr时出了什么问题? AFAIK:

char *ptr;
...strtod(...,&ptr)

应与

相同
char **ptr;
...strtod(...,ptr)

但显然不是。我错过了什么?

2 个答案:

答案 0 :(得分:4)

想想记忆。

当您编写char *str时,您要求编译器为char指针分配内存。现在,当您将str的地址发送给函数时,&str可以更改str中的值。

现在反过来了。

当您编写char **str时,您要求编译器为指向char指针的指针分配内存。这意味着char指针没有内存分配。如果你现在取消引用该指针,它将指向没有任何意义。

现在,您已将str传递给strtod()。该功能现在*str = something()。但那个地方不存在于记忆中。该存储桶未创建和分配。

将来,始终传递已存在变量的ADDRESS。如果没有,则该函数无法更新...

答案 1 :(得分:3)

strtod需要一个双指针(指针指针),因为它想要告诉 用户停止阅读的位置。所以它必须改变一个地方 指针指向,因此它不能采取(单个)指针,它必须采取 指向指针的指针。

  

man strtod

#include <stdlib.h>
double strtod(const char *nptr, char **endptr);
     

[...]

     

返回值

     

这些函数返回转换后的值(如果有)。

     

如果endptr不是NULL指向转化中使用的最后一个字符后的字符的指针存储在引用的位置   endptr

这意味着您通过endptr的指针必须指向有效 char - 指针,这就是为什么

char number[]= "a123.45", *strtod_eptr;
num=strtod(number, &strtod_eptr);

效果很好,因为&strtod_eptr会返回strtod_eptr的地址 变量,它返回一个指针指针。然后strtod可以使用指针 到指针改变原始指针(strtod_eptr)的位置 点。

内部strtod将执行以下操作:

double strtod(const char *nptr, char **endptr)
{
    size_t i;
    double converted_value;
    ...
    if(endptr != NULL)
    {
        // i is the index the character after the last
        // character used in the conversion
        *endptr = &(nptr[i]);
    }

    return converted_value;
}

endptr指向有效位置时,取消引用它不会有问题。

然而

char number[]= "a123.45", **strtod_eptr;
num=strtod(number, strtod_eptr);

不起作用,因为strtod_eptr未初始化的指针,指向 无处可去。当strtod执行*endptr = &(nptr[i])时,它就是 试图在未定义的内存位置写一个值,这是未定义的行为和 段错是这种情况的表现。

然而,这会奏效:

char number[]= "a123.45", *end, **strtod_eptr;

strtod_eptr = &end;
num=strtod(number, strtod_eptr);

因为在这种情况下strtod_eptr会指向有效的位置。