目录
- 四、指针
7、字符串和指针
8、数组指针
9、数组名字取地址
10、指针变量和数组名的区别
11、多维数组中指针的转换
12、指针做函数的参数
- 四、指针
7、字符串和指针
a、 char string[100] = “I love C!”
定义了一个字符数组 string,用来存放多个字符, 并且用”I love C!”给 string 数组初始化
字符串“I love C! ” 存放在 string 中
b、 char *str = “I love C!”
定义了一个指针变量 str,只能存放字符地址编号,
所以说 I love C! 这个字符串中的字符不能存放在 str 指针变量中。
str 只是存放了字符 I 的地址编号, “I love C! ” 存放在文字常量区
c、 char *str =(char*)malloc(10*sizeof(char));//动态申请了 10 个字节的存储空间,首地址给 str 赋值。
strcpy(str, "I love C"); //将字符串“I love C!” 拷贝到 str 指向的内存里
字符数组:在内存(栈、 静态全局区) 中开辟了一段空间存放字符串
可修改,可直接初始化
字符串指针:在文字常量区开辟了一段空间存放字符串, 将字符串的首地址付给 str
不可修改,可直接初始化
堆:使用 malloc 函数在堆区申请空间, 将字符串拷贝到堆区
可修改,不能直接初始化
指针指向的内存是否能修改取决于指针指向的位置,指向文字常量区不可修改,指向栈、堆、静态全局区可修改
字符数组: 使用 scanf 或者 strcpy
buf_aver="hello kitty"; //错误,因为字符数组的名字是个常量
strcpy(buf_aver,"hello kitty"); //正确
scanf("%s",buf_aver); //正确
指向字符串的指针:
buf_point="hello kitty"; //正确,buf_point 指向另一个字符串
strcpy(buf_point,"hello kitty"); //错误,只读,能不能复制字符串到 buf_piont 指向的内存里取决于 buf_point 指向哪里。
8、数组指针(是指针)
概念:本身是个指针,指向一个数组,加一跳一个数组,即指向下一个数组
定义方法:指向的数组的类型 (*指针变量名) [指向的数组的元素的个数]
int (*p)[5];//定义了一个数组指针变量 p, p 指向的是整型的有 5 个元素的数组,即每一个小数组都有五个整形变量
p+1 往下指 5 个整型, 跳过一个有 5 个整型元素的数组。
区别 数组指针:int (*p) [5] 是指针,只有四个字节
int *p[5] 是数组,有五个整形指针
#include <stdio.h>
int main()
{
int a[3][5];//定义了一个 3 行 5 列的一个二维数组
int(*p)[5];//定义一个数组指针变量 p, p+1 跳一个有 5 个元素的整型数组
printf("a=%p\n",a);//第 0 行的行地址
printf("a+1=%p\n",a+1);//第 1 行的行地址, a 和 a +1 差 20 个字节
p=a;
printf("p=%p\n",p);
printf("p+1=%p\n",p+1);//p+1 跳一个有 5 个整型元素的一维数组
return 0;
}
$ 一维数组指针int(*p)[5] ; 配合每行有 5 个 int 型元素的二维数组来用
$ 二维数组指针int(*p)[4][5]; 配合三维数组来用, 三维数组中由若干个 4 行 5 列二维数组构成
$ ...
容易混淆的内容:
指针数组: 是个数组, 有若干个相同类型的指针构成的集合
int *p[10];
数组 p 有 10 个 int *类型的指针变量构成, 分别是 p[0] ~p[9]
数组指针: 本身是个指针, 指向一个数组, 加 1 跳一个数组
int (*p)[10];
P 是个指针, p 是个数组指针, p 加 1 指向下个数组, 跳 10 个整形。
指针的指针:
int **p;//p 是指针的指针,可以保存int *类型的地址
int *q;
p=&q;
9、数组名字取地址
指针:变量取地址
指针的指针:指针变量取地址
数组指针:数组名字取地址
int a[10];
a+1 跳一个整型元素, 是 a[1]的地址
a 和 a+1 相差一个元素, 4 个字节
&a 就变成了一个一维数组指针,是 int(*p)[10]类型的。
(&a) +1 和&a 相差一个数组即 10 个元素即 40 个字节。
c 语言规定, 数组名字取地址, 变成了数组指针。 加 1 跳一个数组
10、指针变量和数组名的区别
int a[10];
int *p;
p = a;
相同点:a和p指向相同的地址,在数组元素引用时等价
不同点:a是常量,p是变量;p可以赋值,a不能赋值
对a取地址是数组指针,对p取地址是指针的指针
11、多维数组中指针的转换
在二维数组中, 行地址 取 * 不是取值得意思, 而是指针降级的意思, 由行地址(数组指针) 变成这一行第 0
个元素的地址。 取*前后还是指向同一个地方, 但是指针的类型不一样了
#include <stdio.h>
int main(int argc, char *argv[])
{
int a[3][5];
printf("a=%p\n",a);
printf("a +1=%p\n",a+1);
printf("*a =%p\n",*a);// *a 变成了第 0 行第 0 列元素的地址
printf("(*a)+1 =%p\n",(*a)+1 ); //结果为第 0 行第 1 列元素的地址
return 0;
}
12、指针做函数的参数
调用函数的时候传变量的地址,在被调函数中通过*+地址俩改变驻点函数中变量的值
要想改变主调函数中变量的值,必须传入变量的地址,而且还得通过 *+地址 去赋值,无论这个变量是何类型
void fun(char **q)
{
*q="hello kitty";
}
int main()
{
char *p="hello world";
fun(&p);
printf("%s\n",p);//结果为: hello kitty
}
给函数传数组的时候不能将数组一次性全部传进去,只能传数组的地址
传一维数组时:void fun(int p[]) 或者 void fun(int *p) //二者等价,都是指针
传二维数组时:void fun(int p[][4]) 或者 void fun(int (*p)[4])
传指针数组时:
void fun(char **q) // char *q[]
{
int i;
for(i=0;i<3;i++)
printf("%s\n",q[i]);
}
int main()
{
char *p[3]={"hello","world","kitty"}; //p[0] p[1] p[2] char *
fun(p);
return 0;
}