声明:char、string类型的数组和指针有另外的特性,请参看:
1
、指向变量的指针与指向数组的指针区别
对普通变量
|
对数组
|
int a;
int *p = &a;
|
int a[8];
int *p = a;
|
int a;
int *p;
p = &a;
|
int a[8];
int *p;
p = a;
|
2
、指针类型与指针所指类型区别
|
指针类型(
p
的类型)
|
指针所指类型(
*p
的类型)
|
|
去掉指针名剩下部分
|
去掉
*
和指针名后剩下部分
|
int *p
|
int *
|
int
|
int **p
|
int **
|
int *
|
int (*p)[8]
|
int (*)[8]
|
int ( )[8]
|
int *p[8]
|
int *[8]
|
int [8]
|
int *(*p)[8]
|
int *(*)[8]
|
int *( )[8]
|
void *p
|
void(
空类型
)
|
不指向任何类型
|
理解:
对于
p
来说,修饰它的是
int *
,可以理解为
( int * ) p
,所以它的类型是
int*
;
对于
* p
来说,修饰它的是
int
,可以理解为
( int ) (* p)
,所以它的类型是
int
型。
3
、数组与指针区别
int a[20];
int *p = a;
| |
求地址
|
求内容(值)
|
a = (a+0) = &a[0]= p = (p+0) = &p[0]
|
*a = a[0] = *(a+0) = *p = p[0] = *(p+0)
|
(a+1) = &a[1] = (p+1) = &p[1]
|
a[1] = *(a+1) = p[1] = *(p+1)
|
(a+i) = &a[i] = (p+i) = &p[i]
|
a[i] = *(a+i) = p[i] = *(p+i)
|
4
、指针运算几种形式区别
int a[10] = {1, 3, 5, 7, 9, 11 } ;
int * p = a ;
| ||||||
原型
|
第
1
步
|
第
2
步
|
p
变否
|
备注
| ||
p++
|
先取
p
所指地址
|
先
p
|
再指向数组下个元素地址
|
再
p+1
|
p
值改变
|
不能写成
a++
|
先求
&a[0]
|
求地址
|
再指向
a[1]
,结果为
&a[1]
|
结果为地址
| |||
*p++
|
先取
p
所指内容(值)
|
先
*p
|
再指向数组下个元素
|
再
p+1
|
p
值改变
|
不能写成
*a++
|
先求
a[0]
|
求值
|
再指向
a[1]
,结果为
&a[1]
|
结果为地址
| |||
(*p)++
|
先取
p
所指内容(值)
|
先
*p
|
再将该值加
1
|
再
*p+1
|
p
值不变
|
可以写成
(*a)++
|
先求
a[0]
|
求值
|
再将
a[0]
内容加上
1
,即为
1+1
=
2
|
结果为值
|
5
、指针类型匹配与转换
(
1
)指针类型必须匹配:不要把指针和整形数混淆。
例如:
int a=20;
int *p;
a int
型,整形数
&a int*
型,整形指针,
a
的地址
p int*
型,整形指针
*p int
型,整形数
p=&a; //
正确,
p
和
&a
都是
int*
型
p=a; //
错误,
p
是
int*
型,
a
是
int
型,二者不匹配
*p=a; //
正确,
*p
和
a
都是
int
型
*p=&a; //
错误,
*p
是
int
型,
&a
是
int*
型,二者不匹配
(
2
)指针类型要和实际存储匹配
例如:
float f=3.8;
float *fp;
int i=8;
int *ip;
f float
型
&f float*
型,
f
的地址
fp float*
型
*fp float
型
i int
型
&i int*
型,
i
的地址
ip int*
型
*ip int
型
ip=&i; //
正确,
ip
和
&i
都是
int*
型
ip=i; //
错误,
ip
是
int*
型,
i
是
int
型,二者不匹配
*ip=i; //
正确,
*ip
和
i
都是
int
型
*ip=&a; //
错误,
*ip
是
int
型,
&i
是
int*
型,二者不匹配
fp=&f; //
正确,
fp
和
&f
都是
int*
型
fp=f; //
错误,
fp
是
float*
型,
f
是
float
型,二者不匹配
*fp=f; //
正确,
*fp
和
f
都是
float
型
*fp=&f; //
错误,
*fp
是
int
型,
&f
是
float*
型,二者不匹配
ip=&f; //
错误,
ip
是
int*
型,
&f
是
float*
型,二者不匹配
fp=&i; //
错误,
fp
是
float*
型,
&i
是
int*
型,二者不匹配
ip=f;
//
错误,
ip
是
int*
型,
f
是
float
型,二者不匹配
fp=i;
//
错误,
fp
是
float*
型,
i
是
int
型,二者不匹配
(
3
)不匹配的指针类型,可以强制转换(不提倡使用)
例如:
int a=20;
int *p=a;
p=a; //
错误,类型不匹配
p=(int*)a; //
正确,强制将
a
由
int
转换为
int*
型
*p=&a; //
错误,类型不匹配
*p=(int)&a //
正确,强制将
&a
由
int*
型转换为
int
型
float f=3.8;
float *fp=&f;
int *ip=&f; //
初始化指针出错,
*ip
和
&f
类型不匹配
int *ip=(int*)&f; //
初始化正确,强制将
&f
由
float*
型转换为
int*
型
6
、字符数组与字符指针
char* s1="hello";
char s2[]="world";
两个表达式的含义是一样的
.
如果讲不同之处的话
,VC6
中编译时
,
对这两种定义进行了不同的处理
;
char *s1 = "hello";
中的
"hello",
编译时指针指向的区域位于
PE
文件的
.rdata
节中
,
是只读的
.
不信的话
,
你可以试试
:
main()
{
char *s1="hello";
char s2[]="world";
*(s2+2)='x'; // 正确
*(s1+2)='x'; // 执行时出错 .
}
{
char *s1="hello";
char s2[]="world";
*(s2+2)='x'; // 正确
*(s1+2)='x'; // 执行时出错 .
}
1
)严格的说两个表达的意思是不完全一样的,因为前者是个字符串指针,这个指针
S1
所存的地址就是存储字符串前
8
个字节即
hello
的那个地址。
2
)
而后者是字符数组。每个字符都有一个独立的地址。