Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/62.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 获取未初始化指针的地址是未定义的行为吗?_C_Pointers_Language Lawyer_Undefined Behavior - Fatal编程技术网

C 获取未初始化指针的地址是未定义的行为吗?

C 获取未初始化指针的地址是未定义的行为吗?,c,pointers,language-lawyer,undefined-behavior,C,Pointers,Language Lawyer,Undefined Behavior,N1570说明这是未定义的行为: #include <stdio.h> int main(void) { char * ptr; printf("%p", (void*)&ptr); } §J.2/1使用具有自动存储持续时间的对象的值 而它是不确定的(6.2.4、6.7.9、6.8) 在这种情况下,指针有一个不确定的值: §6.7.9/10如果具有自动存储持续时间的对象未 显式初始化,其值不确定。如果一个物体 没有显式初始化静态或线程存储持续时间, 然后:

N1570说明这是未定义的行为:

#include <stdio.h>

int main(void) {
    char * ptr;
    printf("%p", (void*)&ptr);
}
§J.2/1使用具有自动存储持续时间的对象的值 而它是不确定的(6.2.4、6.7.9、6.8)

在这种情况下,指针有一个不确定的值:

§6.7.9/10如果具有自动存储持续时间的对象未 显式初始化,其值不确定。如果一个物体 没有显式初始化静态或线程存储持续时间, 然后:

-如果有指针类型,则初始化为空指针

然后,我假设以下测试程序表现出未定义的行为:

#include <stdio.h>

int main(void) {
    char * ptr;
    printf("%p", (void*)&ptr);
}

然而,它们都显示
endptr
被传递到
strtol
未初始化。是否存在使这不是未定义行为的异常?

指针的值及其地址不相同

void *foo;
该指针有一个未定义的值,但必须很好地确定
foo
的地址,即
&foo
的值(否则我们无法访问它)

至少这是我的直觉理解,我现在没有挖掘标准,我只是觉得你看错了


当谈到代码时,这两种情况有时会混淆(“该指针的地址是什么?”可能意味着“该指针的值是什么,它指向的地址是什么?”),但它们确实不同。

不。这不是未定义的行为。只有
ptr
未初始化且具有不确定的值,但
&ptr
具有正确的值

strtol
上的标准引用说明:

…如果主题序列为空或不具有预期形式,则不执行转换;nptr的值存储在endptr指向的对象中,前提是endptr不是空指针

上面这句话是关于这样一个电话:

strtol(str, 0, 10);
手册页中的呼叫和链接的答案都非常好。

参见此示例

char * ptr; 
由于
ptr
没有指向任何对象,因此取消引用它会调用未定义的行为。但当您将其地址传递给strtol时,语法为

long int strtol(const char *nptr, char **endptr, int base);  
在声明中

long parsed = strtol("11110111", &ptr, 2);   
strtol
endptr
参数指向对象
ptr
,解除锁定它将不会调用任何UB。

在此表达式中:

&ptr

操作数的地址,i。e、 ,将生成
ptr
对象的地址,但从不计算
ptr
对象的地址


(C11,6.3.2.1p2)“除非它是sizeof运算符的操作数、一元&运算符、++运算符、--运算符或.运算符或赋值运算符的左操作数,否则没有数组类型的左值将转换为存储在指定对象中的值(不再是左值);这称为左值转换。”

我只能访问N1256,但如果有任何实质性变化,我会感到惊讶

最相关的部分是“6.5.3.2地址和间接运算符”

特别是第3段(我的重点):

语义学

3一元运算符&产生其操作数的地址。如果 操作数的类型为“类型”,结果的类型为“指向类型的指针”。如果 操作数是一元*运算符的结果,该运算符 也不评估&operator,结果就好像两者都是 省略,但运算符上的约束仍然适用,并且 结果不是左值。类似地,如果操作数是结果 对于[]运算符,既不是&运算符也不是一元数*,即 计算[]所隐含的值,结果就好像是&运算符 已删除,并且[]运算符已更改为+运算符。 否则,结果是指向对象或函数的指针 由其操作数指定

OP中引用的段落都不适用,因为正如许多人指出的那样。某物的价值和地址大不相同

我想说的是,不允许对未初始化的值使用它们的地址进行任何限制(因为没有禁止)


注意:我们都知道这很好,但在这些标准中,很少有语句明确地说“是的,您可以这样做&so。”

您使用的不是指针的值,而是存储指针值的变量的地址。由于
NULL
通常是
#将
d定义为0,标准明确允许使用
**endptr
调用
strtol
,为什么不能执行
strtol(str,0,10)?我的回答有点误导…这是对…的回答,前提是endptr不是空指针。当然,它允许它是
0
。我会编辑那个部分。