指针数组
如下所示:
特点::
(指针数组=存储指针的数组)
ps既是数组的地址也是数组中第一个元素的地址
数组中的元素都是一个int类型的指针
取值操作:
*ps 是对第一个元素取值,即取a的地址;
*(ps+1) 将地址向下移动,然后 对其取值,即取b的地址;
((ps+1))为取b的值
((ps))为取a的值
注意:int num[ ]={…} //普通数组,num不可以++操作;
代码示例
#include<stdio.h>
int main()
{ char *name[]={"rose","jack","lucy","shark"};
for(int i=0;i<4;i++)
{ printf("%s\n",*(name+i)); //name为第一个字符串的地址,数据类型为char *,即为字符指针,存储字符串常量,指向字符串首地址
char *p=*(name+i);
while(*p!='\0')
{ if(*p=='a')
{ printf("发现字母了a\n"); break;}
p++;
}
}
return 0;
}
数组指针
如下图所示;
普通数组的定义 int n[4],n=数组名=数组的地址=数组首元素的地址
类比定义数组指针 int(*p)[4],
*p=数组名=数组的地址=数组首元素的地址
p= 二维数组名=二维数组的地址=二维数组元素的首地址
对于一个二维数组,我们需要定义一个一维数组指针
特点:
数组指针=数组的指针
对于p来说,数据类型为一维数组指针即为int()[4],指针加一指向下一个一维数组,步长为一个一维数组
对于p来说,数据类型为一维数组元素,指针加一指向下一个元素,步长为一个数据类型.
注意: 如图,p指向的地址=*p指向的地址,只是每次对地址加一时的步长不一样
取值操作
p+i,表示第i行取地址
*(p+i)+j表示第i行第j列取地址
((p+i)+j)表示对第i行第j列取值
或者p[i][j]直接对其取值
代码示例:
#include<stdio.h>
int main()
{
int arr[3][4]={1,2,3,4,5,6,7,8,9,10,11,12};
int (*p)[4]=arr;
printf("%d\n%d\n",*(*(p+1)+2),p[1][2]);
return 0;
}
字符串的存储位置
栈区 , 全局区 , 堆区 -----可以修改其中内容;
常量区--------不可以修改其中内容;
栈区:局部变量,定义在main函数内部的普通字符串;如下
int main(){
char m[] = "good";
//good存储在常量区,数组m在栈中的开辟了一片空间,将常量区的字符串复制到栈中的数组空间中
//所以可以对其修改,其实是可以修改其在栈空间的备份内容.
m[0] = "c";
...
}
全局区:定义在main函数外的全局变量或者静态变量
#include <stdio.h>
char str[] = "Hello, World!"; //main函数外,为全局变量,存储在全局区,可以对其内容修改
int main() {
str[7] = 'C';
printf("%s\n", str);
return 0;
}
堆区:通过malloc或者realloc函数申请的空间内存储(通过scanf函数和strcpy函数修改存储的内容)
#include <stdio.h>
int main()
{
char *m=(char *)malloc(10);
strcpy(m, "jack");
*m = 'm'; // m指向的空间是堆区的
return 0;
}
常量区: 存储常量数据,包括字符串常量、全局常量等
注意:常量区不可以修改内容;
#include <stdio.h>
int main()
{
char *q = "lucy"; //q是一个指针,指向的是一个常量,存储在常量区,不可以修改
return 0;
}