数组与指针
来源:互联网 发布:云南省软件行业协会 编辑:程序博客网 时间:2024/05/21 23:34
数组和指针之区别列表
以下面代码为例:
char *p;
char array[100];
说明如下:
1 因为任何类型的指针变量(针对我们用的32位CPU而言)的长度为4,故sizeof(p)为4;但sizeof(array)为100.这一点是由编译器在编译阶段确定的,即编译器对于sizeof(p)是直接以常数4替换的,对sizeof(array)是直接以100替换的。由此也可知道,用sizeof不但可读性、可扩展性好,而且丝毫不降低代码效率(包括时间和空间上的)。
2 sizeof(*p)和sizeof(array[0])则相同,都为1
3 设n为一整数,p[n]等价于*(p + n),array[n]等价于*(array+ n),即不管是指针还是数组,都有这两个等效的表示方法
4 数组形式的形参本质上是指针。后面详述。
5 array在许多情况下代表第一个元素的地址,即&array[0]。例如
p = array; /* 等价于 p = &array[0]; */
fun(array); /* 等价于 p = fun(&array[0]); */
这个现象让许多人得出“数组即指针”的错误结论。
6 但数组毕竟是数组,当array取sizeof或地址时,array代表整个数组,这时它不能替换为 &array[0]。例如:
sizeof(array)为100,而sizeof(&array[0])等于sizeof(char*);
&array表示整个数组的地址,它可以赋值给一个指向同类型数组(即100个char变量组成的数组)的指针。而 &(&array[0])表示什么?什么也不是,根本不合语法(编译不过)。
使用数组名时,前面加不加&符号有何区别?
void main()
{
char a[4];
void *b;
void *c;
b=a;
c=&a;
}
上面的代码中,b=a; c=&a;二者都获得的是数组a的首地址,所以b与c的值相同。
但从本质上说,a和&a的类型是不同的:在b=a中,a等价于&a[0],所以此处是当作char*(即指向char变量的指针)类型使用的;而&a表示数组a的地址,所以其类型是“指向含4个char元素的数组的指针”。
看下面的例子(VC下编译的结果),就说明问题
voidmain()
{
char a[20];
char *b,(*c)[20]; /* c的类型为“指向含20个char元素的数组的指针” */
b=&a; /* 编译不过,因类型不匹配 */
b=a; /* OK */
c=&a; /* OK */
c=a; /* 编译不过,因类型不匹配 */
}
由于c指向的是含20个char元素的数组,故c+1其实是对c的值加了20,可作如下测试:
printf(“%u\n”, (unsignedint)(c + 1) - (unsigned int)c);
观察打印为20.
但下面的代码编译则无任何问题,因为b c为void*,可接收任何类型的指针的赋值
voidmain()
{
char a[20];
void *b, *c;
b=&a;
b=a;
c=&a;
c=a;
}
指向数组的指针的应用
指向数组的指针应用不多,但偶尔也会碰到,下举一例(部门人员碰到的):
char a[10][20], b[10][20];
…
if (..)
{
a[i][j]…
}
else
{
b[i][j]… /* 此分支与上一分支的唯一区别是:前者是对a,后者是对b操作 */
}
两分支代码除a b之分外,完全相同。这种代码浪费空间,且不易维护——两处要同步更改。
借用数组指针,可以这样:
char(*p)[10][20];/*括号不能省略,否则p变成了指针构成的数组*/
if (..)
{
p = &a;
}
else
{
p = &b;
}
(*p)[i][j]… /* 仅一份代码 */
或者这样:
char(*p)[20];/*括号不能省略,否则p变成了指针构成的数组*/
if (..)
{
p = a;/* 将a看成&a[0],就知道其类型与p是匹配的 */
}
else
{
p = b;
}
p[i][j]… /* 仅一份代码 */
数组形式的形参本质上是指针
void Fun1(char v[100])
{
int n =sizeof(v);
v++;
}
完全应该这样理解:
void Fun1(char *v)
{
int n =sizeof(v);
v++;
}
1 Fun1中v++是合法的。
2 sizeof(v)的值不是100,而是等于sizeof(char*),即4
void Fun1(char v[100])与void Fun1(char *v)以及void Fun1(char v[])是完全等价的写法。我们应按void Fun1(char *v)来理解,编译器也都是按这种方式体现的意义来编译的。写代码时,从语法上说可以随便用哪种形式。但是从习惯上来说,如果设计该函数时是打算接受上层函数(即调用者)的数组名作为实参,则通常定义为数组形式(char数组除外);如果设计该函数时是打算接受上层函数(即调用者)的某一个变量的地址作为实参,则通常定义为指针形式。
- 指针:指针与数组
- 指针与指针数组
- 指针数组与数组指针
- 指针数组与数组指针
- 指针数组与数组指针
- 指针数组与数组指针
- 指针数组与数组指针
- 指针数组与数组指针
- 指针数组与数组指针
- 数组指针与指针数组
- 指针数组与数组指针
- 指针数组与数组指针
- 指针数组与数组指针
- 指针数组 与数组指针
- 指针数组与数组指针
- 数组指针与指针数组
- 指针数组与数组指针
- 指针数组与数组指针
- 关于同步异步、阻塞非阻塞的解释
- Android 数字显示带E(科学计数法)
- FreeSWITCH的端口设置
- CCF201612-1 中间数
- 01背包问题详解(转载)
- 数组与指针
- 求解有向图的强联通分量--tarjan算法(tarjian求最小环模板)
- Centos7下利用strongsman搭建vpn
- CATRT剪枝算法
- Java学习---6
- rhcsa学习杂记—重置centos7 系统ROOT密码
- webmagic爬取渲染网站
- 如何将图片包裹进div里
- python模块以及导入出现ImportError: No module named 'xxx'问题