输出是:10
,它没有给出错误。
int main(){
int j=10;
int *i=&j;
printf("%d",*i);
return 0;
}
但它给了我一个错误:
int main(){
int *i;
int j=10;
*i=&j;
printf("%d",*i);
return 0;
}
我知道指针取消引用导致了错误。但这是怎么回事呢?
因为您使用的是未初始化的指针。您的*i = &j
应该i = &j
这将i
定义为int *
并将其值设置为 j
的地址:
int *i=&j;
这会将i
定义为int *
,然后尝试将i
指向的内容设置为j
的地址:
int *i;
int j=10;
*i=&j;
最后一个*i = ...
是尝试取消引用未初始化的变量。
int *i=&j;
在这里,您将i
声明为int *
,并分配j
的地址。
*i=&j;
但是,在本例中,您已经声明了i
,并且您将&j
分配给i
指向的位置,而不是i
本身。所以这是一个错误。另一个是i
还没有指向任何东西,因为你还没有初始化它。如果你想让i
指向j
,你应该删除*
:
i = &j;
i
本身被声明为"指向int
的指针"。所以你应该写i = &j;
来分配它的地址 j
.
在您的情况下,*i = &j
赋值之前取消引用它,也就是说,指针的值被分配给一个 int
,它驻留在合法或非法的内存块中,因为i
是未初始化的。
变量会导致未定义的行为,更不用说访问未初始化的指针指向的对象了。
下面是一个整数变量i
的简单声明
int i = 10;
通常很容易拆分声明和初始化:
int i;
/* ... */
i = 10;
没关系。 但是 C 中指针声明的语法是不寻常的,并且在处理声明和初始化时会导致一点不对称。 你可以写
int *i = &j; /* correct */
但是,如果将其拆分,则*
不会标记,因为它是声明的一部分。
int *i;
/* ... */
i = &j; /* right */
*i = &j; /* WRONG */
int *i;
您已将i
声明为指向int
的指针,但尚未将其设置为指向任何内容;i
的值不确定为 1。 它将包含一些随机的位字符串,这些位(很可能)与有效地址2 不对应。 此时尝试取消引用i
会导致未定义的行为,这可能意味着从彻底崩溃到数据损坏再到没有任何明显问题的工作。
该行
*i = &j;
有两个问题,第一个是i
没有指向任何有意义的地方(这就是您的运行时错误无疑的来源;您正在尝试访问无效地址)。 二是*i
和&j
的类型不匹配; *i
的类型为 int
,而&j
的类型为 int *
。
- 在本地声明到没有
static
关键字的函数的变量具有自动存储持续时间,并且不会隐式初始化为任何特定值。 在没有显式初始值设定项的情况下,不要假定任何此类变量最初设置为 0 或NULL
。 在任何函数体外部声明或使用static
关键字声明的变量具有静态存储持续时间,在没有显式初始值设定项的情况下,这些变量将被初始化为 0 或NULL
。" - 有效"是指程序中定义的对象的地址(即,另一个变量,或通过"malloc"分配的内存块等)或平台定义的已知地址(例如固定的硬件输入地址)。
NULL
是一个定义明确的无效地址,易于测试。