获取未初始化指针的地址是未定义的行为吗?
Is it undefined behavior to take the address of an uninitialized pointer?
N1570 指出这是未定义的行为:
§J.2/1 The value of an object with automatic storage duration is used
while it is indeterminate (6.2.4, 6.7.9, 6.8).
在这种情况下,我们的指针具有不确定的值:
§6.7.9/10 If an object that has automatic storage duration is not
initialized explicitly, its value is indeterminate. If an object that
has static or thread storage duration is not initialized explicitly,
then:
— if it has pointer type, it is initialized to a null pointer;
然后我假设以下测试程序表现出未定义的行为:
#include <stdio.h>
int main(void) {
char * ptr;
printf("%p", (void*)&ptr);
}
我最关心的是 strtol
函数。先引用一下N1570中与endptr
参数相关的部分:
§7.22.1.4/5 If the subject sequence has the expected form and the
value of base is zero, the sequence of characters starting with the
first digit is interpreted as an integer constant according to the
rules of 6.4.4.1. [...] A pointer to the final string is stored in the
object pointed to by endptr
, provided that endptr
is not a null
pointer.
§7.22.1.4/7 If the subject sequence is empty or does not have the
expected form, no conversion is performed; the value of nptr
is
stored in the object pointed to by endptr
, provided that endptr
is
not a null pointer.
这意味着 endptr
需要指向一个对象,并且 endptr
在某些时候被取消引用。例如,this implementation does so:
if (endptr != 0)
*endptr = (char *)(any ? s - 1 : nptr);
然而,this highly upvoted answer as well as this man page 都显示 endptr
被传递给 strtol
未初始化。是否存在使这不是未定义行为的异常?
指针的值和它的地址不一样。
void *foo;
该指针具有未定义的值,但 foo
的地址,即 &foo
的值,必须确定(否则我们无法访问它)。
至少这是我的直觉理解,我现在没有去挖掘标准,我只是觉得你看错了。
在谈论代码时,两者有时会混淆("what's the address of that pointer?" 可以表示"what's the value of that pointer, what address is it pointing to?")但它们确实截然不同。
没有。这不是未定义的行为。只有 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。即,生成 ptr
对象的地址,但从未评估 ptr
对象。
(C11, 6.3.2.1p2) "Except when it is the operand of the sizeof operator, the unary & operator, the ++ operator, the -- operator, or the left operand of the . operator or an assignment operator, an lvalue that does not have array type is converted to the value stored in the designated object (and is no longer an lvalue); this is called lvalue conversion."
我只能访问 N1256,但如果有任何 material 变化,我会感到惊讶。
最相关的部分是“6.5.3.2 地址和间接运算符”
特别是第 3 段(我强调):
Semantics
3 The unary & operator yields the address of its operand. If the
operand has type ''type'', the result has type ''pointer to type''. If
the operand is the result of a unary * operator, neither that operator
nor the & operator is evaluated and the result is as if both were
omitted, except that the constraints on the operators still apply and
the result is not an lvalue. Similarly, if the operand is the result
of a [] operator, neither the & operator nor the unary * that is
implied by the [] is evaluated and the result is as if the & operator
were removed and the [] operator were changed to a + operator.
Otherwise, the result is a pointer to the object or function
designated by its operand.
None OP 中引用的段落适用,因为正如许多人指出的那样。东西的价值和它的地址是非常不同的。
我会争辩说,没有任何关于未初始化值取其地址的限制是允许的(因为没有禁止)。
注意:我们都知道这很好,但很少在这些标准中找到明确说明 "Yes you can do so & so."
的语句
N1570 指出这是未定义的行为:
§J.2/1 The value of an object with automatic storage duration is used while it is indeterminate (6.2.4, 6.7.9, 6.8).
在这种情况下,我们的指针具有不确定的值:
§6.7.9/10 If an object that has automatic storage duration is not initialized explicitly, its value is indeterminate. If an object that has static or thread storage duration is not initialized explicitly, then:
— if it has pointer type, it is initialized to a null pointer;
然后我假设以下测试程序表现出未定义的行为:
#include <stdio.h>
int main(void) {
char * ptr;
printf("%p", (void*)&ptr);
}
我最关心的是 strtol
函数。先引用一下N1570中与endptr
参数相关的部分:
§7.22.1.4/5 If the subject sequence has the expected form and the value of base is zero, the sequence of characters starting with the first digit is interpreted as an integer constant according to the rules of 6.4.4.1. [...] A pointer to the final string is stored in the object pointed to by
endptr
, provided thatendptr
is not a null pointer.§7.22.1.4/7 If the subject sequence is empty or does not have the expected form, no conversion is performed; the value of
nptr
is stored in the object pointed to byendptr
, provided thatendptr
is not a null pointer.
这意味着 endptr
需要指向一个对象,并且 endptr
在某些时候被取消引用。例如,this implementation does so:
if (endptr != 0)
*endptr = (char *)(any ? s - 1 : nptr);
然而,this highly upvoted answer as well as this man page 都显示 endptr
被传递给 strtol
未初始化。是否存在使这不是未定义行为的异常?
指针的值和它的地址不一样。
void *foo;
该指针具有未定义的值,但 foo
的地址,即 &foo
的值,必须确定(否则我们无法访问它)。
至少这是我的直觉理解,我现在没有去挖掘标准,我只是觉得你看错了。
在谈论代码时,两者有时会混淆("what's the address of that pointer?" 可以表示"what's the value of that pointer, what address is it pointing to?")但它们确实截然不同。
没有。这不是未定义的行为。只有 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。即,生成 ptr
对象的地址,但从未评估 ptr
对象。
(C11, 6.3.2.1p2) "Except when it is the operand of the sizeof operator, the unary & operator, the ++ operator, the -- operator, or the left operand of the . operator or an assignment operator, an lvalue that does not have array type is converted to the value stored in the designated object (and is no longer an lvalue); this is called lvalue conversion."
我只能访问 N1256,但如果有任何 material 变化,我会感到惊讶。
最相关的部分是“6.5.3.2 地址和间接运算符”
特别是第 3 段(我强调):
Semantics
3 The unary & operator yields the address of its operand. If the operand has type ''type'', the result has type ''pointer to type''. If the operand is the result of a unary * operator, neither that operator nor the & operator is evaluated and the result is as if both were omitted, except that the constraints on the operators still apply and the result is not an lvalue. Similarly, if the operand is the result of a [] operator, neither the & operator nor the unary * that is implied by the [] is evaluated and the result is as if the & operator were removed and the [] operator were changed to a + operator. Otherwise, the result is a pointer to the object or function designated by its operand.
None OP 中引用的段落适用,因为正如许多人指出的那样。东西的价值和它的地址是非常不同的。
我会争辩说,没有任何关于未初始化值取其地址的限制是允许的(因为没有禁止)。
注意:我们都知道这很好,但很少在这些标准中找到明确说明 "Yes you can do so & so."
的语句