未设置的C指针不为空

我正在搞乱C指针。 当我编译并运行以下代码时。

例1:

#include  int main() { int k; int *ptr; k = 555; if (ptr == NULL) { printf("ptr is NULL\n"); } else { printf("ptr is not NULL\n"); printf("ptr value is %d\n", *ptr); } printf("ptr address is %p\n", ptr); } 

我得到输出:

 ptr is not NULL ptr value is 1 ptr address is 0x7fff801ace30 

如果我没有为k赋值:

例2:

 #include  int main() { int k; int *ptr; if (ptr == NULL) { printf("ptr is NULL\n"); } else { printf("ptr is not NULL\n"); printf("ptr value is %d\n", *ptr); } printf("ptr address is %p\n", ptr); } 

然后输出就像我期望的那样:

 ptr is NULL ptr address is (nil) 

同样,如果我在函数外定义变量:

例3:

 #include  int k; int *ptr; int main() { k = 555; if (ptr == NULL) { printf("ptr is NULL\n"); } else { printf("ptr is not NULL\n"); printf("ptr value is %d\n", *ptr); } printf("ptr address is %p\n", ptr); } 

输出:

 ptr is NULL ptr address is (nil) 

在第一个示例中,ptr具有地址和值,这是预期的行为吗? 如果是这样的话:

  • 为什么ptr有地址和价值?
  • 它们来自哪里,是什么设置它们?
  • 如何在本地范围内正确定义空指针并将其保持为空,直到我准备好使用它为止?

我在x64上使用Uccntu 12.04.04上的gcc进行编译:

 root@dev:~# gcc -v Using built-in specs. COLLECT_GCC=gcc COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/4.6/lto-wrapper Target: x86_64-linux-gnu Configured with: ../src/configure -v --with-pkgversion='Ubuntu/Linaro 4.6.3-1ubuntu5' --with-bugurl=file:///usr/share/doc/gcc-4.6/README.Bugs --enable-languages=c,c++,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-4.6 --enable-shared --enable-linker-build-id --with-system-zlib --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.6 --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --enable-gnu-unique-object --enable-plugin --enable-objc-gc --disable-werror --with-arch-32=i686 --with-tune=generic --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu Thread model: posix gcc version 4.6.3 (Ubuntu/Linaro 4.6.3-1ubuntu5) 

编辑

为了清楚起见,我已将上面的例子编号。

基于Dietrich的回答,我做了一些搜索并发现了这个问题: 为什么全局变量总是初始化为’0’,而不是局部变量? 。

C中的局部变量不会自动初始化,只会自动初始化全局变量。

 int x; // 0 by default static int y; // 0 by default void function() { static int z; // 0 by default int w; // Not initialized! Could be anything! } 

未初始化变量的值未指定 。 在实践中,这可能意味着不同的事情。

  • 如果您的编译器或运行时在使用之前将内存清零,则它可能为零。

  • 它可以填充像0xdeadbeef0xeeeeeeee这样的0xeeeeeeee

  • 它可能包含来自该特定内存位置中最后一个的垃圾。 (这种方法最常见。)

您正在使用GCC,它使用第三种方法,因此您看到最后一个函数使用该内存位置的垃圾。 您可以使用Valgrind运行该程序( 强烈推荐 ),它可能会使用未初始化的内存吐出错误消息,但不能保证捕获所有错误。

正确的做事方式

一种选择是如果要使用它们,则显式初始化局部变量。

 void function() { int *ptr = NULL; ... } 

如果没有使用该值,我更喜欢保留未初始化的变量,因为编译器和Valgrind可以给我诊断消息,让我知道我对代码的理解是不正确的,如果事实certificate使用了未初始化的内存。

永远不要将间接运算符应用于未初始化的指针变量。 如果未初始化,则尝试使用它会调用未定义的行为
以上两个代码正在调用未定义的行为。 在这种情况下,结果可能是预期的或意外的。

最后一个代码工作正常,因为全局变量被隐式初始化为0 。 因此,指针ptr初始化为NULL ,您将获得正确的输出。

您也许可以尝试使用此代码来了解您想要了解的内容:

 #include  #include  typedef struct _appl{ //the pointer int *ptr_int; float *ptr_float; double *ptr_double; char *ptr_char; //the basic data types int a_int; float a_float; double a_double; char a_char; struct _appl *next; } appl; //the pointers int *ptr_int_global; float *ptr_float_global; double *ptr_double_global; char *ptr_char_global; //the basic data types int a_int_global; float a_float_global; double a_double_global; char a_char_global; //pointer to structure data type appl *ptr_struct_global; //struct data type; appl a_struct_global; int main() { //the pointers int *ptr_int_local; float *ptr_float_local; double *ptr_double_local; char *ptr_char_local; //the basic data types int a_int_local; float a_float_local; double a_double_local; char a_char_local; //pointer to structure data type appl *ptr_struct_local; //struct data type; appl a_struct_local; //test the basic data types (local variables) puts("********"); puts("****first test : test the basic data types (local variables)"); puts("********"); printf("the value of a non-initialized int is : %d\n", a_int_local); printf("the value of a non-initialized float is : %f\n", a_float_local); printf("the value of a non-initialized double is : %f\n", a_double_local); printf("the value of a non-initialized char is : %d\n\n", a_char_local); //test the basic data types (global variables) puts("second test : test the basic data types (global variables)"); printf("the value of a non-initialized int is : %d\n", a_int_global); printf("the value of a non-initialized float is : %f\n", a_float_global); printf("the value of a non-initialized double is : %f\n", a_double_global); printf("the value of a non-initialized char is : %d\n\n", a_char_global); //test the pointers (local variables) puts("third test : test basic data type pointers (local variables)"); if(ptr_int_local == NULL) printf("a non-initialized int pointer is NULL\n"); else printf("a non-initialized int pointer is not NULL\n"); if(ptr_float_local == NULL) printf("a non-initialized float pointer is NULL\n"); else printf("a non-initialized float pointer is not NULL\n"); if(ptr_double_local == NULL) printf("a non-initialized double pointer is NULL\n"); else printf("a non-initialized double pointer is not NULL\n"); if(ptr_char_local == NULL) printf("a non-initialized char pointer is NULL\n\n"); else printf("a non-initialized char pointer is not NULL\n\n"); puts("attention ! sometimes a non-initialized char pointer (global variables) is NULL, while sometimes not !"); //test the pointers (global variables) puts("fourth test : test basic data type pointers (global variables)"); if(ptr_int_global == NULL) printf("a non-initialized int pointer is NULL\n"); else printf("a non-initialized int pointer is not NULL\n"); if(ptr_float_global == NULL) printf("a non-initialized float pointer is NULL\n"); else printf("a non-initialized float pointer is not NULL\n"); if(ptr_double_global == NULL) printf("a non-initialized double pointer is NULL\n"); else printf("a non-initialized double pointer is not NULL\n"); if(ptr_char_global == NULL) printf("a non-initialized char pointer is NULL\n\n"); else printf("a non-initialized char pointer is not NULL\n\n"); //test data structure (local variable) puts("fifth test : test data structure type (local variables)"); if(ptr_struct_local == NULL) printf("a non-initialized data structure pointer is NULL\n\n"); else printf("a non-initialized data structure pointer is not NULL\n\n"); //test data structure (global variable) puts("sixth test : test data structure type (global variables)"); if(ptr_struct_global == NULL) printf("a non-initialized data structure pointer is NULL\n\n"); else printf("a non-initialized data structure pointer is not NULL\n\n"); ptr_struct_local = (struct _appl*)malloc(sizeof(struct _appl*)); if(ptr_struct_local == NULL) printf("failed to allocate memory\n\n"); else printf("success of allocating memory\n\n"); appl *a = ptr_struct_local; //test the basic data types (in a local data structure variable) puts("\nseventh test : test the basic data types (in a local data structure variable)"); printf("the value of a non-initialized int is : %d\n", a->a_int); printf("the value of a non-initialized float is : %f\n", a->a_float); printf("the value of a non-initialized double is : %f\n", a->a_double); printf("the value of a non-initialized char is : %d\n\n", a->a_char); //test the pointers (in a local data structure variable) puts("eigth test : test the pointers (in a local data structure variable)"); if(a->ptr_int == NULL) printf("a non-initialized int pointer is NULL\n"); else printf("a non-initialized int pointer is not NULL\n"); if(a->ptr_float == NULL) printf("a non-initialized float pointer is NULL\n"); else printf("a non-initialized float pointer is not NULL\n"); if(a->ptr_double == NULL) printf("a non-initialized double pointer is NULL\n"); else printf("a non-initialized double pointer is not NULL\n"); if(a->ptr_char == NULL) printf("a non-initialized char pointer is NULL\n\n"); else printf("a non-initialized char pointer is not NULL\n\n"); ptr_struct_global = (struct _appl*)malloc(sizeof(struct _appl*)); if(ptr_struct_global == NULL) printf("failed to allocate memory\n\n"); else printf("success of allocating memory\n\n"); appl *b = ptr_struct_global; //test the basic data types (in a global data structure) puts("\nninth test : test the basic data types (in a global data structure)"); printf("the value of a non-initialized int is : %d\n", b->a_int); printf("the value of a non-initialized float is : %f\n", b->a_float); printf("the value of a non-initialized double is : %f\n", b->a_double); printf("the value of a non-initialized char is : %d\n\n", b->a_char); //test the pointers (in a global data structure) puts("tenth test : test the pointers (in a global data structure)"); if(b->ptr_int == NULL) printf("a non-initialized int pointer is NULL\n"); else printf("a non-initialized int pointer is not NULL\n"); if(b->ptr_float == NULL) printf("a non-initialized float pointer is NULL\n"); else printf("a non-initialized float pointer is not NULL\n"); if(b->ptr_double == NULL) printf("a non-initialized double pointer is NULL\n"); else printf("a non-initialized double pointer is not NULL\n"); if(b->ptr_char == NULL) printf("a non-initialized char pointer is NULL\n\n"); else printf("a non-initialized char pointer is not NULL\n\n"); }