浅析C语言指针使用中的几个常见错误

2015-01-04 06:02张尔谦
人间 2015年15期
关键词:常量字符串数组

张尔谦

(武警警官学院,四川 成都 610000)

浅析C语言指针使用中的几个常见错误

张尔谦

(武警警官学院,四川 成都 610000)

指针是C语言中的一个重要概念,也可以说是C语言的灵魂。指针的引入使C语言变得高效和灵活,同时也给使用者尤其是初学者带来一定的困惑。本文对C语言指针使用中的几个常见错误进行了分析。

指针;数组; C语言

指针是C语言中的一个重要概念,也可以说是C语言的灵魂。指针的引入使C语言变得高效和灵活,同时也给使用者尤其是初学者带来一定的困惑。在教学实践中经常会发现C语言指针使用中的一些常见的具有典型性的错误,现列举分析如下。

一、间接引用未初始化的指针

对于指针变量如果仅进行了定义而未对其进行初始化,则不可对其进行间接访问。例如int *p;*p=100;,这是初学者常犯的一个错误。对于指针变量p进行定义,仅仅是为p分配了一个存储空间,而这个存储空间里所存储的值在没有对p进行初始化之前是不可预知的,而这个不可预知的值既然存储在变量p中就自然被理解为是一个地址值。在这种情况下,执行语句*p=100;就会改写以这个存储于p中的不可预知的值为地址的存储单元里的内容,而该存储单元中可能存储着一个重要的数据,这样就有可能破坏系统的运行,造成严重后果。把上述错误语句改为int *p, a;p=&a; *p=100;由于在对p进行间接引用之前已对其进行初始化,使指针p指向整型变量a,则不会出现上述错误。

二、不能正确区别指针变量与数组名的使用方法

指针变量是用来存放地址值的,而数组名代表该数组第一个元素的地址。例如:

int *p,a={1,2,3,4,5};其中a的值即为数组a中第一个元素的地址即&a[0],可以将指针p初始化为a(即p=a;等价于p=&a[0];),这样指针p就指向数组a的第一个元素a[0]。但是必须注意p是可以存放地址值的变量而a则是一个地址常量。请看下例:

#include

int main()

{ int i,a={1,2,3,4,5};

for (i=0;i<5;i++)

printf("%d ",*(a++));

return 0;

}

该程序段不能输出数组a的元素的值,编译时会给出出错提示“'++' needs l-value”(自增运算符只能应用于左值)原因在于a是一个常量,而常量不能作为左值,即不能出现在赋值符的左侧,不能进行自增运算。这是数组名与指针变量的重要区别。

将上述错误程序改写如下,则能正确输出数组a的各个元素的值:

#include

int main()

{ int *p,i,a={1,2,3,4,5};

p=a;

for (i=0;i<5;i++)

printf("%d ",*(p++));

return 0;

}

三、不能正确区别字符指针变量与字符数组的使用方法

字符指针变量用来指向一个字符而字符数组可以由若干个数组元素组成,每个数组元素都可以存储一个字符。从这一点上来看,二者并不容易混淆。但字符指针变量和字符数组都可以用字符串常量来初始化,这时就要特别注意二者的区别了。例如下面对字符指针变量和字符数组的初始化都是合法的:

char a=”abcdefg”; //初始化字符数组a

char * p=”abcdefg”;//初始化指针变量p

但前者是定义字符数组a并把字符串”abcdefg”中的字符逐个赋给数组a的各元素,而后者是将字符串的第一个元素的地址赋给p。虽然以上两个赋值语句的机制并不相同但利用数组a和指针p都能输出字符串”abcdefg”。下面的程序输出两次字符串”abcdefg”:

#include

int main()

{char a="abcdefg";//初始化字符数组a

char * p="abcdefg";//初始化指针变量p

printf("%s ",a);//利用数组输出字符串

printf("%s ",p);//利用指针输出字符串

return 0;

}

字符指针变量和字符数组都可以用字符串常量来初始化,并能利用指针变量和字符数组正确输出,但二者的机制却不相同。在C语言中,初始化字符指针时创建的字符串被定义为只读,不能利用指针修改这个字符串的值。而由字符串常量初始化的数组是可以修改的,数组中的元素可以改变。例如:

char a="abcdefg";//初始化字符数组a

char * p="abcdefg";//p指向字符串常量的第//一个字符

a[2]=’f’;//合法

p[2]=’f’;//非法,字符串常量不能改变

再看下例:

# include

void swap(char *x,char *y)

{ char t;

t=*x; *x=*y; *y=t;

}

void main( )

{ char *s1="abc",*s2="123";

swap(s1,s2); printf("%s,%s ",s1,s2);

}

程序执行后的输出结果是()。

A)123,abc B)abc,123 C)1bc,a23 D)321,cba

这是2006年4月二级C语言试题第38题,标准答案是C。笔者认为这是一道值得商榷的题目。通过实验验证该程序可通过编译但不能正常运行,更不能得出选项C所给出的结果。原因就在于初始化字符指针s1时创建的字符串"abc"和初始化字符指针s2时创建的字符串"123"被系统定义为只读,不能利用指针修改这个字符串的值。

四、结语

程序设计语言的学习是一个在纠错中不断提高的过程,了解C指针使用中常见的典型性错误并认真分析其原因有助于提高对C语言的理解水平和应用水平。

[1]Peter Van Der Linden著,许波译.C专家编程[M].北京:人民邮电出版社,2008.

[2]Kenneth A. Reek著,许波译.C和指针[M].北京:人民邮电出版社,2008.

[3]谭浩强.C程序设计(第四版)[M].北京:清华大学出版社,2010.

TP311

A

1671-864X(2015)05-0200-01

猜你喜欢
常量字符串数组
科学照亮世界
——卡文迪什测定万有引力常量
JAVA稀疏矩阵算法
基于文本挖掘的语词典研究
JAVA玩转数学之二维数组排序
一次函数的学习引导
更高效用好 Excel的数组公式
VHDL中常用的数据对象
SQL server 2008中的常见的字符串处理函数
倍增法之后缀数组解决重复子串的问题
最简单的排序算法(续)