#include<stdio.h>
#include<string.h>
#include<stdlib.h>
void test(char**string)
{
if(*string ==NULL)
*string = (char*)malloc(50)
strcpy(*string, "hello world")
}
int main()
{
char*str=NULL
test(&str)
printf("str=%s\n",str)
free(str)
return0
}
指针的声明与初始化1、不恰当的指针声明
考虑如下的声明:
int* ptr1, ptr2// ptr1为指针,ptr2为整数
正确的写法如下:
int* ptr1, *ptr2
用类型定义代替宏定义是一个好的习惯,类型定义允许编译器检查作用域规则,而宏定义不一定会。
使用宏定义辅助声明变量,如下所示:
#define PINT int*
PINT ptr1, ptr2
不过结果和前面所说的一致,更好的方法是使用下面的类型定义:
typedef int* PINT
PINT ptr1, ptr2
2、使用指针未初始化
在使用指针之前未初始化会导致运行时错误,如下面的代码:
int* p
...
printf("%d\n", *p)
指针p未被初始化,可能含有垃圾数据
3、处理未初始化指针
总是用NULL来初始化指针
用assert函数
用第三方工具
把指针初始化为NULL更容易检查是否使用正确,即便这样,检查空值也比较麻烦,如下所示:
int *pi = NULL
...
if(pi == NULL) {
//不应该解引pi
} else {
//可以使用pi
}
我们可以使用assert函数来测试指针是否为空值:
assert(pi != NULL)
指针的使用问题
缓冲区溢出
缓冲区溢出是指当计算机向缓冲区内填充数据位数时超过了缓冲区本身的容量,使得溢出的数据覆盖在合法数据上,理想的情况是程序检查数据长度并不允许输入超过缓冲区长度的字符,但是绝大多数程序都会假设数据长度总是与所分配的储存空间相匹配,这就为缓冲区溢出埋下隐患。操作系统所使用的缓冲区又被称为”堆栈”.。在各个操作进程之间,指令会被临时储存在”堆栈”当中,”堆栈”也会出现缓冲区溢出。
下面几种情况可能导致缓冲区的溢出:
访问数组元素时没有检查索引值
对数组指针做指针算术运算时不够小心
用gets这样的函数从标准输入读取字符串
误用strcpy和strcat这样的函数
1、测试NULL
使用malloc这样的函数的时候一定要检查返回值,否则可能会导致程序的非正常终止,下面是一般的方法:
float *vector = malloc(20 * sizeof(float))
if(vector == NULL) {
//malloc分配内存失败
} else {
//处理vector
}
2、错误使用解引操作
声明和初始化指针的常用方法如下:
int num
int *pi = &num
下面是一种看似等价但是错误的声明方法:
int num
int *pi
*pi = &num
3、迷途指针
参见《C迷途指针》
4、越过数组边界访问内存
没有什么可以阻止程序访问为数组分配的空间以外的内存,下面的例子中,我们声明并初始化了三个数组来说明这种行为:
#include<stdio.h>
int main()
{
char firstName[8] = "1234567"
char middleName[8] = "1234567"
char lastName[8] = "1234567"
middleName[-2] = 'X'
middleName[0] = 'X'
middleName[10] = 'X'
printf("%p %s\n", firstName, firstName)
printf("%p %s\n", middleName, middleName)
printf("%p %s\n", lastName, lastName)
return 0
}