这是一个新手C ++指针问题。我不知道为什么会发生这种情况......
我发现如果我写这段代码。这完全有效。
代码1
int *j; //create an pointer j
*j = 50; //assign 50 to the *j, meaning value pointed by address 50 is xxx
然而,当我想尝试使它更简单时。编译器给我这个错误信息。
代码2
int *j = 50; //i guess this should be the same with Code1...
编译错误
error: invalid conversion from ‘int*’ to ‘int’
那为什么会那样?
答案 0 :(得分:13)
那里的C语法有点含糊不清。
int *j = 50;
相当于
int *j;
j = 50;
实际上,你在第一段代码中所做的是危险的,因为在为它分配值之前你还没有为j分配任何内存。你需要像这样为它做记忆:
C中的
int *j = (int*) malloc(sizeof(int));
*j = 50;
在C ++中
int *j = new int;
*j = 50;
或者将指针指向已经有效的其他内存块:
int k;
int *j = &k;
*j = 50;
printf("%d", k); // 50
编辑:值得指出的是,歧义与'*'符号有关。在声明中,int *j;
* j表示“一个名为j的指针”。但是当您在第二行“* j = 50”中使用它时,*将成为取消引用符号,表示“地址j处的值”。
答案 1 :(得分:2)
他们完全有不同的含义。
第一个声明指针,并将int
中当前地址指向的j
设置为50
。没有其他背景,这已经很糟糕; j
中的地址未初始化,您最有可能通过将值写入内存中的随机位置来导致分段错误。
第二段代码声明了一个指针,并将存储在其中的地址定义为50.如果你把它分开,就像写一样(注意第二个语句中没有星号):
int *j; j = 50;
答案 2 :(得分:2)
声明int *j;
后,在堆栈上分配了int *
类型的空间(在本例中),该空间具有一些地址addr_stk
并且内容我们不知道,即。垃圾。
+--------+ +--------+
| ??? |----+ | xxx | trying to store 50 here
+--------+ | +--------+
| j | | | |
+--------+ | +--------+
|addr_stk| +---->| ??? | have no permission to access this location
+--------+ +--------+
当您使用*j = 50;
时,指针变量(对象)j
的内容将用作在其中存储值50
的地址。因此,您尝试将值50存储在具有垃圾地址值的某个地址位置,这意味着它可以位于任何位置。每当您尝试访问未分配给您的内存位置时,将无法存储或访问该位置,操作系统将阻止您进行操作并抛出一些错误。
您需要做的是首先用一些有效的地址初始化指针变量j
。这可以通过首先使用malloc
分配一些内存然后使用它来完成。或者使用其他变量(本地或全局)的地址初始化j
。像
int *j, i;
j = &i;
*j = 50;
或
int *j;
j = malloc (sizeof (int));
*j = 50;
在访问*j
的情况下,我们在j
内有一个有效地址,因此使用j
的内容作为地址(指针访问),有效,为{{1解析为有效的内存访问。
重要的是,当您使用*j
分配内存时,应始终释放内存。这是一个好习惯,否则在大型程序中会导致内存泄漏。
答案 3 :(得分:1)
你的两个例子都错了。
第一个:
int *j;
*j = 50;
将50
存储到地址j
。但是,您从未初始化j
,因此您只是存储到未知地址。有时这会“成功”,有时这会使你的应用程序崩溃,有时它只会破坏你的应用程序状态而不会导致错误;它永远不是你真正想要做的。
第二个:
int *j = 50;
尝试使用类型为“int”的值初始化“pointer-to-int”类型的变量,这是一个错误。
相反,你想做类似的事情:
int i = 50;
int *j = &i; // j is now a pointer to i.
或:
int i;
int *j;
j = &i; // note: no * before j. j now contains a valid address.
*j = 50; // store 50 to the address j. After this, i == 50.
答案 4 :(得分:1)
*
是变量的类型的一部分,而不是其名称。
int* j
表示“我有一个名为j
的变量,它是指向int的指针。”
int* j = 50
(代码2)的意思是“我有一个名为j
的变量,它是指向int的指针,并且应该使用值50
”进行初始化。这是不允许的;如果没有显式强制转换,指针可能无法使用0
以外的整数值进行初始化。 如果你不知道自己在做什么,明确地去解决这个问题是一个非常非常糟糕的想法,如果你问这些问题,那么你肯定不知道自己在做什么足以尝试。
您应该能够从错误消息中找出这一点。无效的转换就是:您的代码尝试从一种类型转换为另一种类型(通过赋值),这是无效的。您分配的内容不是您所分配的兼容类型。它告诉你所涉及的类型是什么。
*j = 50
(代码1中的第二行)表示“在50
指向的位置”写入值j
。这很糟糕,因为j
尚未初始化。 这被称为“未定义的行为”并且正是如此 - 它可能以任何方式失败,或者不会失败,但即使它似乎有效也总是错误。但它会编译,并且大多数编译器甚至不会试图警告你这种事情,除非你问他们真的很高的警告水平 - 如果有的话。
答案 5 :(得分:0)
int *j = 50
实际上等于
int *j;
j = 50;
因为初始化的分配无论如何都会分配变量itsel。
在这两种情况下,这都是一个非常糟糕的主意,因为指针无效。