C指针声明和初始化问题

在声明和初始化指针时可能会出现问题,更准确地说,指针初始化失败。在本节中,我们会研究出现这类问题的情况。

不恰当的指针声明

考虑如下声明:

int* ptr1, ptr2;

声明本身没错,不过,可能跟我们的本意不同,它把ptr1声明为整数指针,而把ptr2声明为整数。我们将星号有意紧挨着数据类型,而ptr1前面则加了空格。这样的位置对编译器来说没有区别,但是对于读代码的人来说,可能暗示着ptr1ptr2都是整数指针。然而,只有ptr1是指针。

在同一行中把两个变量都声明为指针的正确写法如下所示:

int *ptr1, *ptr2;

注意 每个变量声明独占一行更好。

用类型定义代替宏定义是另一个好习惯。类型定义允许编译器检查作用域规则,而宏定义不一定会。

我们可以使用宏指令辅助声明变量,如下所示。在这里,define指令包装了整数指针,并用它来声明变量:

#define PINT int*
PINT ptr1, ptr2;

不过,结果就跟前面所说的一样。更好的方法是用下面的类型定义:

typedef int* PINT;
PINT ptr1, ptr2;

两个变量均被声明为整数指针。

使用指针前未初始化

在初始化指针之前就使用指针会导致运行时错误,有时候将这种指针称为野指针。下面这个简单的例子声明了一个整数指针,但是使用之前没有为其赋值:

int *pi;
...
printf(“%d\n”,*pi);

图7-1说明了此时的内存分配情况。

enter image description here

图7-1:野指针

这里没有初始化pi变量,因此它会包含垃圾数据(在图中用省略号表示)。如果pi中的内存地址超出了应用程序的合法地址空间,这段代码很可能会在执行过程中终止。否则打印出来的就是恰好位于那个地址的数据(不管具体是什么),而且会表示为整数。如果我们用的是字符串指针,就经常会看到打印出奇怪的字符(直到遇到末尾的0才停止)。

处理未初始化指针

指针本身并不能告诉我们它是否有效,所以,不能只靠检查指针的内容来判断它是否有效。不过,有三种方法可以用来处理未初始化的指针:

  • 总是用NULL来初始化指针;
  • assert函数;
  • 用第三方工具。

把指针初始化为NULL更容易检查是否使用正确。即便这样,检查空值也比较麻烦,如下所示:

int *pi = NULL;
...
if(pi == NULL) {
    // 不应该解引pi
} else {
    // 可以使用pi
}

我们可以用assert函数来测试指针是否为空值。下例测试了pi变量是否为空值。如果表达式为真,那么什么都不会发生,如果表达式为假,程序会终止。这样,指针为空的话程序就会终止。

assert(pi != NULL);

对于应用程序的调试版本,这种方法可能可以接受。如果指针是空值,输出类似下面:

Assertion failed: pi != NULL

我们在assert.h头文件中声明assert函数。

可使用第三方工具来帮助定位这类问题,此外,有些编译器选项也比较有用,使用静态分析工具中会讲到。

赞(1)

评论 抢沙发

评论前必须登录!

 

C指针