首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >c: strtod:双指针与单指针引用

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

Stack Overflow用户
提问于 2018-02-03 06:22:18
回答 2查看 216关注 0票数 3

效果很好。

代码语言:javascript
复制
#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()中的第二个参数已更改类型。

代码语言:javascript
复制
#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,但没有编译错误。

代码语言:javascript
复制
strol_test.c:7:5: warning: ‘strtod_epptr’ is used uninitialized in this function [-Wuninitialized]

在if()语句中,程序崩溃(seg错误)。

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

代码语言:javascript
复制
gcc -Wall -pedantic -o "strol_test" "strol_test.c"

这一切为什么要发生?为什么gcc抱怨未初始化的**strtod_epptr,而对(类似的未初始化的?) *strtod_eptr完全没问题?在取消引用**strtod_epptr时会出现什么问题?AFAIK:

代码语言:javascript
复制
char *ptr;
...strtod(...,&ptr)

应该与

代码语言:javascript
复制
char **ptr;
...strtod(...,ptr)

但显然不是这样的。我遗漏了什么?

EN

回答 2

Stack Overflow用户

发布于 2018-02-03 06:54:44

想想记忆吧。

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

现在换一种方式。

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

现在,您将str传递给了strtod()。该函数现在执行*str = something()。但是那个地方在记忆中是不存在的。该存储桶不是创建和分配的。

以后,总是传递已经存在的变量的地址。如果不是,则函数没有可以更新的变量...

票数 4
EN

Stack Overflow用户

发布于 2018-02-03 06:58:19

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

手册组

#include double strtod(const char *nptr,char **endptr);

..。

返回值

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

如果endptr不是NULL,则将指向在转换中使用的最后一个字符之后的字符的指针存储在 is引用的位置中

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

代码语言:javascript
复制
char number[]= "a123.45", *strtod_eptr;
num=strtod(number, &strtod_eptr);

因为&strtod_eptr返回strtod_eptr变量的地址,所以它工作得很好,它返回指向指针的指针。然后,strtod可以使用指向指针的指针来更改原始指针(strtod_eptr)的指向位置。

在内部,strtod会这样做:

代码语言:javascript
复制
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指向一个有效的位置时,取消对它的引用不会成为问题。

然而,

代码语言:javascript
复制
char number[]= "a123.45", **strtod_eptr;
num=strtod(number, strtod_eptr);

不起作用,因为strtod_eptr是一个uninitialzed指针,它不会特别指向任何地方。当strtod执行*endptr = &(nptr[i])时,它正试图在未定义的内存位置写入一个值,这是未定义的行为,segfault就是这种行为的一种表现。

然而,这将会起作用:

代码语言:javascript
复制
char number[]= "a123.45", *end, **strtod_eptr;

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

因为在这种情况下,strtod_eptr将指向一个有效的位置。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/48591705

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档