效果很好。
#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)
但显然不是。我错过了什么?
答案 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
会指向有效的位置。