指针和数组的区别
首先我们编写如下代码:
#include<stdio.h>
#include<stdlib.h>
int main(){
char *s1 = "hello";
char *s2 = "hello";
char a1[] = "hello";
char a2[] = "hello";
printf("%p %p %p %p \n",s1, s2, a1, a2);
return 0;
}
程序运行结果:

从结果可以看出,第一个和第二个 “hello” 的地址都为 “0000000000404000” ,原因是这个时候的数指针指向的 “hello” 为字符串常量,它存放在静态存储区(静态存储区的特点是,内存从分配之后一直到程序结束才会被回收),因此,对于两个 “hello” 这样的字符串常量它的值是一样的,所以 s1、s2 实际指向的是同一个 “hello” ,因此看到的地址是相同的;对于 a1、a2 而言,它们是局部变量,放在栈上,栈上的内容是可以随时修改的,它们是指向两个不同的 “hello” ,它的值可以改为其它内容,因此这里一共有 3 个 “hello”。
*s1 = ‘H’; // 错误,*s1 为字符串常量,不可以修改
*a1 = ‘H’; // 正确,a1[]为局部变量,可以修改
s1++; // 正确,s1 是地址变量,可以修改
a1++; // 错误,a1 是地址常量,不可以修改
char* get_string(){
char *s = "hello"; // 正确, 字符串常量在静态存储区,程序结束时才会回收内存地址
char s[] = “hello”; // 错误,局部变量在栈上,相应程序结束后该内存地址不能使用
return s;
}
0 指针数组
指针数组是数组,数组的每一个元素是指针,形式如下:
<数据类型> *<指针变量名>[<大小>];
指针数组名表示该指针数组的起始地址。
代码写法如下:
int main(){
int a=1, b=2, c=3;
int* p[3] = {&a, &b, &c};
return 0;
}
或
typedef int* ptype[3];
int main(){
int a=5, b=2, c=0;
ptype p = {&a, &b, &c};
return 0;
}
例0.0 编程实现通过指针数组来遍历二维数组
#include<stdio.h>
int main(){
int a[2][3] = {{1,3,5}, {1,9,6}};
int *p[2];
int i, j;
p[0] = a[0];
p[1] = a[1];
for(i=0; i<2; i++){
for(j=0; j<3; j++){
printf("%d ", *(p[i]+j)); //p[i][j]
}
puts("");
}
return 0;
}
运行结果

Q1:指针数组占空间大小?
A1: sizeof(数据类型)*数组长度。
Q2: 指针数组是什么样的指针?
A2: 二级指针。
Q3: 指针数组名加 1 移动多少字节?
A3:sizeof(数据类型)。
1 数组指针
数组指针式指针,指向数组的指针,也就是指向数组首地址的地址,形式如下,
<数据类型> (*<指针变量名>)[表达式];
代码写法如下:
int main(){
int a= {1, 2, 3};
int(*p)[3] = &a;
return 0;
}
或
typedef int(*ptype)[3];
int main(){
int a= {1, 2, 3};
ptype p = &a;
return 0;
}
例1.0
int a[3][3], (*p)[3];
p = a;
下面表示 a 数组元素的是哪一个选项()
A:p+1 B:*(p+1) C:*(p+1)+1 D:*(*p+1)
解析: 二维数组名代(a)表数组的起始地址,数组名加 1 (a+1),移动 1 行元素。p+1 等价于 p[1]或a[1]的 地址 , *(p+1)等价于 p[1]或a[1],*(p+1)+1等价于 p[1][1] 的地址,*(*p+1)等价于 p[0][1]、a[0][1]。

被折叠的 条评论
为什么被折叠?



