这是程序:
#include <stdio.h>
main() {
int * i;
int * j;
printf("%d\n", i);
printf("%d\n", j);
}
我编译并运行它,输出是:
888086464
0
但是,如果我注释掉第二个printf
#include <stdio.h>
main() {
int * i;
int * j;
printf("%d\n", i);
//printf("%d\n", j);
}
out out beomes:
0
我想知道为什么第二个printf改变了指针i 并且,C如何初始化指针?据我所知,如果指针未初始化,它的值Null将等于0,对吗?为什么在第一个输出中,i被初始化了?
编辑:根据你们的建议,我做了一些改变:
#include <stdio.h>
main() {
int * i;
int * j;
printf("%p\n", i);
printf("%p\n", j);
}
给出了
0x7fff67a361b0
(nil)
但是当我注释掉第二个printf
时#include <stdio.h>
main() {
int * i;
int * j;
printf("%p\n", i);
//printf("%p\n", j);
}
输出为零。 我很好奇为什么在第一个版本中有两个printf,只有j是nil而我不是。
答案 0 :(得分:4)
您没有初始化任何一个指针。你在看什么是未定义的行为。您看到的值只是堆栈中的垃圾值,每次运行时都会更改。
答案 1 :(得分:3)
如果你没有初始化指针,它可以有任何值。
您必须初始化它们。否则,您将获得undefined behavior
。
指针打印的正确方法是:
printf("%p", pointer);
答案 2 :(得分:2)
您可以通过查看两个版本的生成机器代码来回答您的问题(对于gcc,应该是-S选项)。
我怀疑在第二个版本中,根本没有创建j
(因为它没有在任何地方使用),因此正在创建i
在用于j
的插槽中。无论出于何种原因,您的堆栈已设置为前64位为0x0000000000000000
,后跟0x00007fff67a361b0
IOW,在第一个版本中,您的堆栈看起来像
Item Address 00 01 02 03 04 05 06 07
---- ------- -- -- -- -- -- -- -- --
j 0x8000 00 00 00 00 00 00 00 00
i 0x8008 00 00 7f ff 67 a3 61 b0
而在第二个版本中,它看起来像
Item Address 00 01 02 03 04 05 06 07
---- ------- -- -- -- -- -- -- -- --
i 0x8000 00 00 00 00 00 00 00 00
0x8008 ?? ?? ?? ?? ?? ?? ?? ??
(地址值仅用于说明,并不代表任何真实的架构。)
对于咯咯笑声,请将print语句修改为
printf("%p: %p\n", &i, i);
printf("%p: %p\n", &j, j);
第一个版本中的和
printf("%p: %p\n", &i, i);
在第二个。我敢打赌,第二版中为&i
打印的值(变量i
的地址)将与为&j
打印的值相同(变量的地址) j
)在第一个版本中。
注意 - 这与C 语言无关,而且与您的特定实现(编译器,链接器等)有关。我不相信你正在调用未定义的行为(你没有通过这些无效的指针访问任何内存),但你看到的是没有显式初始化指针值的危险。
在没有static
关键字的块范围内声明的变量未初始化;在实例化变量时内存中的任何内容都是初始值,并且该位模式可能不代表该类型的有效值(这称为陷阱表示)。在文件范围(在任何函数之外)或使用static
关键字声明的变量初始化为0或NULL,具体取决于它是标量还是指针类型。对于聚合类型(数组,结构和联合),规则稍微复杂一些,但基本原理是相同的。
答案 3 :(得分:0)
“未初始化”与“初始化为0”(或NULL)非常不同。
变量i
和j
未初始化。它们留下了记忆中的内容。
当你注释掉第二个printf
时,变量j
不再使用了。它可能由编译器优化(意思是根本没有定义)。在这种情况下,i
可能位于不同的位置,具有不同的未初始化的值。
这实际上是未定义的行为。我的上一节是纯粹的推测,你永远无法确定。
答案 4 :(得分:0)
指针可以容纳任何东西。除非你告诉它,否则C不会初始化本地(自动)变量。如果将它们定义为静态,则使用NULL初始化它们。
此外,您应该使用%p
来打印指针,而不是%d
。
答案 5 :(得分:0)
如果不初始化指针地址
,您将获得未定义的行为这里你将指针地址打印为int,这是不正确的,你应该使用"%p"
而不是"%d"
答案 6 :(得分:0)
And, how does C initialize pointers?
C没有,你这样做。
As far as I know, if a pointer is not initialized, it would have value Null which is equal to 0, correct?
错误。如果未初始化,则没有定义的值。这将是垃圾。打印未初始化的变量将导致垃圾,这就是您无法预测输出的原因。
Why in the first output, the i was initialized?
事实并非如此,它恰好指向了0。
附注:当您打印指针时,应使用%p
进行打印。
答案 7 :(得分:0)
C仅自动初始化static
和全局变量(全局变量在函数外声明)为零。 自动变量(即你的两个指针被调用的内容)不会自动初始化,因此您正在打印&#34;堆栈噪音&#34; (即,当你的函数初始化时,堆栈上的任何值都会发生。打印的值甚至可能会在程序的运行之间发生变化。如果你想将它们初始化为NULL
,你需要告诉编译器:
int *i = NULL;
int *j = NULL;