为什么我不能直接将int赋值给int指针,比如:int *p = 6;?

7

错误:从'int'到'int *'的转换无效
int *q = 8;

这很好。
*q = 6;

为什么我不能直接像这样将int分配给int指针:int *q = 6,而我可以在下一行安全地分配它?


初始化与赋值 - pmg
2
尽量不要编写多语言源文件。这样做非常困难,而且结果并不完全符合所选的任何一种语言。 - pmg
7
不能!指针没有初始化,你不能对它进行解引用操作。我无法在下一行安全地分配它。 - Ajay Brahmakshatriya
@FelixPalmen 是的,它也应该是被接受答案的一部分。 - Ajay Brahmakshatriya
3
考虑到这篇文章的回答更多,得分也更高,相比之下重复的那篇文章应该被关闭并指向这篇文章,而不是关闭这篇文章。 - Bernhard Barker
显示剩余2条评论
13个回答

25

因为它们完全是不同的东西。第一个是带有初始化表达式的变量定义,即指针本身的初始化

int *         q                      = 8;
~~~~~         ~                      ~~~
type is int*; name of variable is q; initialized with 8

第二个是指针所指对象的赋值:

*q                              = 6;
~~                              ~~~
dereference on q via operator*; assign the resulting lvalue pointed by q to 6

而且,int *p = 6;的意思是定义一个名为p、类型为int*并用6初始化的变量,但这会失败,因为6不能直接用于初始化指针(即错误“从'int'到'int*'的转换无效”)。


14

* 符号在你的代码片段中被重复使用了两次,第一次用作类型声明 int * ,声明一个指向整数的指针。第二次用于解引用指针 *q,调用间接运算符。

* 也可以用于调用乘法运算符 *q = *q * *q;

要给一个指向整数的指针赋值,需要先对其进行解引用。将非0整数值分配给指针本身(这就是 int *q = 8; 所做的)需要 reinterpret_cast,因此你会得到这个错误。


5
“两个不同的目的”实际上是不正确的。让我们看一下“两个”指针的定义: int *p,*q; 如果 * 属于 int,那么您将定义两个指针为 int* p,q /*错误*/; 这是 C 兼容性的不幸残留物,因为在其他上下文中,如 std::vector<int*> 中它是类型的一部分。 - MSalters

6

语句int *q定义了一个指向整数的指针变量,因此初始化必须是指针值而不是整数值。

因此,int *q = 8int *q; *q = 8不同(后者是未定义的行为,因为它对未初始化的指针进行了解引用),但类似于int *q; q = 8,这使误解更加明显。


5

This:

int *q = 8;

是一个初始化语句,它初始化了指针q,而不是*q(指针指向的内容)。如果使用赋值语句等效地替换初始化语句,将会如下所示:

int *q;
q = 8;

所以你可以看到这是没有意义的。(当然也不允许——一个 int 不是指针)

只是为了确保,如果你写:

int *q;
*q = 8;

这是语法上正确的,但是行为未定义。您的指针并没有指向一个int类型的对象,它还没有被初始化,很可能指向一些无效的位置。在那里进行写入操作会导致任何事情发生。


不,它在语法上是不正确的。你不能将整数赋值给指针,这是简单赋值的约束违规。(初始化遵循相同的规则) - Lundin
我指的是第一行,由于违反了约束条件,它将无法编译。 - Lundin
@Lundin和我认为我的文本已经足够清晰易懂了,如果你仔细阅读的话,"语法正确"是指最后一段代码片段。 - user2371524
仍然第一行无法编译。它不会像你所说的那样初始化指针,因为它无法编译。 - Lundin
@Lundin 我没有声称这样的事情。 - user2371524
2
@Lundin 谈论语法,稍后会详细说明。我并不声明这是有效的代码。 - user2371524

3
因为类型不匹配。 6 本身不是指针类型的值,而是整数类型的,因此不能直接存储在指针中。
当你执行 *q = 6 时,* 将对指针进行解引用,所以类型变为 int(或者更确切地说是一个左值 int,即可被赋值的东西)。

3

在这里,将值8分配给类型为int*的对象。它意味着q指向内存中地址8

 int *q = 8;

等价于:

int *q;
q = 8;

不等于:

int *q;
*q = 8;

这是违法的,因为它涉及限制违规

相关的stackoverflow问题:是否可能将C指针初始化为NULL?


你所说的“违反约束条件”是指原帖作者的代码,因为你的帖子格式让人感觉你在谈论最后一个代码片段(该代码片段并不涉及约束条件)。 - M.M

3

指针变量保存一个地址,或者说是某个东西的“位置”。因此,指针保存的是一个内存地址。当你说:

int *q = 6;

你正在创建一个指向int的指针变量,并告诉它指向地址6中存储的int值,这可能不是你真正想要的。指针变量应该指向一些包含实际数据的内存地址,以便访问。例如:
int x = 5;
int *q = &x;

这创建了一个变量(x),它包含值5。 下一行创建了一个指针变量,它包含x的地址。您已将指针变量“q”设置为整数变量“x”的地址。

现在,您可以通过执行以下操作来查看“x”中的内容:

int y;
y = *q;

这句话的意思是“取q所指向的内容,并将其存储在y中”。最终结果是y将被设置为5。
int x = 5;     // create variable x and set it to 5
int *q = &x;   // create int pointer variable, set it to the address of x
int y;         // create variable y
y = *q;        // take the value pointed to by q, and store it in y

如果,例如变量x在内存位置1234处,并且您查看了存储在'q'中的值,则该值将为1234,即x的地址。 当您说“y = *q”时,您实际上是说“取出地址1234中存储的值,并将该值放入y中”。由于内存位置1234是'x',而'x'被赋予了值5,因此值5将存储在地址1234处。
y = *q;

将存储在地址1234中的值赋给y,因此使y成为5,这是存储在x中的值,也就是q“指向”的值。

可以缩写为:

int x = 5;
int *q = &x;
int y = *q;

这只回答了问题的前半部分,而没有回答第二个问题:“我可以在下一行安全地分配它吗?” - Máté Juhász

2
当你写下 int *q = 8; 时,意味着你声明了一个指针 q 并将其初始化为整数8。但是,由于 q 是一个指针,它需要一个地址值,因此您会收到不兼容的错误提示。
而当你在声明后写下 *q=8 时,这意味着你正在解除 q 指向的地址并向该位置写入值。在这里,q 指向一个 int,因此你将整数值 8 写入 q 指向的位置,这是正确的。如果未将 q 初始化为指向正确位置,则也可能在运行时导致错误。

1
你不能使用整数来初始化一个指针,因为初始化遵循“简单赋值”的规则。你需要先将整数转换为指针。 - Lundin
1
谢谢。我没有明确地说问题是整数被赋值给指针。 - LearningC

1
在你的第一条语句中,你声明并初始化了一个指向类型为int的某个值的指针(在同一行上)。在第二条语句中,你正在更改指针指向的值。两件不同的事情。你所拥有的是初始化后跟赋值。不要让*困扰你。

0

因为它不是有效的C语言,就这么简单。具体来说,这是赋值运算符的约束违规,因为整数到指针或指针到整数不是“简单赋值”的有效形式(C11 6.5.16.1)。

您可以通过添加显式转换来在整数和指针之间进行转换。但结果不能保证有效:指针和整数可能具有不同的表示形式,并且可能存在对齐问题。

*q = 6;的情况下,您将一个int赋给另一个int,这当然是完全可以的(前提是指针指向某个已分配的内存位置)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接