与指针相关的常见错误

来源:互联网 发布:创力cms 编辑:程序博客网 时间:2024/05/16 00:24

(1)

int* i = 3;
char* ch = 'a';

error C2440: 'initializing' :
cannot convert from 'const char' to 'char *'

不能给char(单字符)、int、float、double指针赋常量值
(但字符串指针可以,见下面详解)

int* num; num = &3; //错,常量没有地址
char* ch; ch = &'a';
 //错,常量没有地址

 

(2)

char* a="fish";
int i=3, *b = &i;

cout<<a<<' '<<b<<endl;

输出:fish  0012FF34

字符串指针可赋常量,但指针本身仍是变量,值可变。
要输出数值,须用 cout<<*b;
要输出指针变量的值,一般都要在指针名前加 *

但字符串指针是“数组”,指针名就是这个数组名,
而数组名就代表了数组的首地址,所以不必加 *

接下来考虑这个问题:

同样是将常量赋给指针,为什么 char* a = "a";
可以通过编译,而 char* ch = 'a'; 就不可以呢?
如果系统先申请了"a"这么一段字符串空间,然后
将其首址给指针a,那char* ch='a';为什么就不可以
呢?

 关于这个问题...请好心的高手赐教...
(注:本文全部内容皆为自己总结,如有错误,敬请
指明,谢谢!)

 

(3)
 char* name;
 cout<<name<<"  "<<*name<<endl;

 int* num;
 cout<<num<<"  "<<*num<<endl;

无论是name、num还是*name、*num, 在未给它赋值之前是
不允许读取其内容的。但可以sizeof其大小,因为sizeof
只是根据其类型判断大小,并不读取其内容。但下面的语句
可以正常输出:

 int* b, i;
 b = &i;
 cout<<b<<"  "<<*b<<endl;

RESULT: 0012FF34  -858993460

 对于未赋值的指针(常称为“野指针”),指针本身
的空间已经确定,但其指向的空间(即指针的值)是不确定的,或
者是随意的(函数形参例外),虽然编译没有错,但程序运行时
,这个指针很可能指向内存中被其它的程序占用的空间,甚至其
它非法的地方。

下面通过简单调试说明:

 char *name, *a="fish";
 int* b;

 cout<<b<<"  "<<*b<<endl;

开始时,三个指针变量name、a、b的值都是指向同一个地址
0xcccccccc,其中a和name的值为"",而b的值为空;

按F5继续,看到a的值改变了!这很容易理解,系统不可能真的
就把0xcccccccc这个地址同时分配给多个变量使用,这样肯定
要出问题,而是说当你未赋初值时你们先站在这里别动,乖乖地
“临时守在这个地方,不许干任何事”。一旦有新的空间给你,
再“放走”这些指针。
 地址“0xcccccccc”就像一个孤儿所,而指针指向的空间
就像是指针的“家”,被“收养”的指针才有自己的“家”,有自己
的自由。为了避免有些初学者将“指针的地址”与“指针的值”
混为一谈,我们将指针的地址比作指针的“名字”,这样,任何一
个指针一出身就有自己的惟一的名字,但不一定有自己的“家”。
没有“家”,当然就只能暂住“孤儿所”了。

 

 int* b = NULL;
 cout<<"&b= "<< &b <<"/t b= "<< b <<endl;

将正确输出为:&b= 0012FF34    b= 00000000

但*b仍然是不能输出的。之所以这样,在于NULL的特殊性。
NULL实际上代表的是一个地址0x00000000,这个地址的特殊性
在于它不允许赋值(其实它真的没有值,这正是“空”的含义),
实际中我们经常给一个指针赋初值为NULL,这其实是为了防止
指针访问非法地址,将它们统统指向这个“禁区”。因为不能
赋值,通过*b来取得的0x00000000的值当然就会出错。

 为了揭开NULL的面纱,这里说些题外话,很多书上说
“NULL就是0,但又不完全等同于0”,特别是关于Javascript
介绍的书常常有这一表述,其实很让人费解,不妨从上面的解释
稍作引申:NULL代表地址0x00000000,地址是十六进制数值,
将0x00000000转为十进制不就是0吗?说二者“不完全”相等,
就是因为一个是地址,而另一个是常量。


(4)
用cin给指针赋值:

 char* name;
 cout<<"Enter the Name of the worker: ";
 cin>>name;
 cout<<name;

有很多人说错了,原因是“name中存储的是地址,因此
输出的是地址名,改为 cout<<*name 就对了”。

事实上,这段代码编译不会出错,但运行结果可能让你
一头雾水,不知所措。无论你输入什么,程序一旦运行
到这里,就出现“XXX.exe已停止工作”,为什么呢?

其实,要仔细研究这个问题,还要分两种情况:

 如果你输入的是单个字符,那么cout<<name;
语句就错了,但根本原因不在这里,现在是程序不能运行,
而不是运行结果不对,如果在cout<<name;之前无任何差错,
不管你cout的是name还是*name都应该能正常显示啊,聪明
一点的初学者可能马上想到问题(1),对了,这不是各问题(1)
一种情况吗?只是将赋值方法由“=”改为“cin”而已,问题
终于找到!

 那如果输入的是多个字符呢?这下没招了,怎么
调试都不能找到原因。别担心,学过动态申请的同学可能
根本不需要看这一段,不过为了说明问题,还是有必要探
讨一下。用sizeof(char*)得到char*类型的指针大小为1,
显然这里存放的是地址,但这个地址指向的空间又有多大?
无可知晓,如果要更正上面的错误,修改如下:

 char* name;
 name = new char[5];
 cout<<"Enter the Name of the worker: ";
 cin>>name;
 cout<<name;

但注意这时输入字符串长度不能大于5(可以等于5)。

 double salary;
 cout<<"Enter the Salary of the worker: ";
 cin>>salary;
 cout<<salary;

 

原创粉丝点击