目录
指针数组
数组指针
指针和二维数组
通过指针访问二维数组
通过数组指针访问二维数组
用指针表示二维数组并访问
地址等级
0级地址:
一级地址:
二级地址:
三级地址:
总结
指针的指针
命令行参数
上一篇复习了指针函数和函数指针,这一节开始复习数组指针和指针数组的内容。
说明:我们学过单片机的一般都是有C语言基础的了,网上关于C语言的资料有很多,大家如果对C语言不熟悉的话可以先去详细学一下,再以这篇博文作为复习资料学习。
这篇博文的目的是复习C语言,我们会陆续以30多个编程题作为复习要点,这30多个编程题基本涵盖了C语言所有的内容了,只要你掌握了这30多个编程题,那么你的C语言基本就没什么问题了。
注意:由于本专栏是嵌入式全栈开发专栏,为了我们能熟悉以后实际工作中的开发环境,我们写C语言全部在Linux中的vim编辑器中写,这么做事为了我们能够熟练掌握Linux系统的常用命令以及Linux上的vim编辑器的常用工作命令,以达到对口训练的目的!
vim编辑器的一些工作命令在上一篇博文中已经详细介绍过了,如果不了解可以先去看看。
我们正式开始:
指针数组
指针数组是数组!一个数组的元素值为指针,则该数组是指针数组。
指针数组的所有元素都必须是具有相同存储类型和指向相同数据类型的指针变量。
指针数组说明的一般形式为:
类型说明符 *数组名[数组长度]
其中类型说明符为指针所指向的变量的类型。
例如: int *pa[3];
表示pa是一个指针数组,它有三个元素,每个元素值都是一个指针,指向整型变量。
数组指针
数组指针是一个指针!该指针指向数组(一维或二维都可以)。
例如:
int (*p)[5];
可以这么理解,p是一个指针,指向一个数组,该数组有5个元素,每个元素都是整型。
注意:
这样写是错误的:int b[5]={0}; int*p=&b;是错误的,因为&b取出来的是整个数组b的地址,而int*p是表示p指向int型的数,是4个字节,而&b一次取出来了20个字节,类型不兼容。
这样写是对的:int (*p)[5]=&b;此时这个p指向的是整个数组b
指针和二维数组
通过指针访问二维数组
示例:
int array[3][4]={{1,2,3,4}, {2,3,4,5}, {3,4,5,6}};
int *s1[3]={array[0], array[1], array[2]};
遍历:
示例:
int i;//行
Int j;//列for(i=0; i<sizeof(s1)/sizeof(s1[0]);i++){for(j=0;j<sizeof(array[0])/sizeof(array[0][0]);j++){printf(“%lu”,*(s1[i]+j)); //等价于s[i][j]}printf(“\n”);}
注意:不能写成j<sizeof(array[0])/sizeof(s1[0]),因为sizeof(s1[0])算出来是一个指针的大小
通过数组指针访问二维数组
int(*s1)[4]=array;//s1指向array的第一行,第一行相当于一个一维数组,有4个元素,每个元素是int型
遍历:
for(i=0; i<3;i++)
{
for(j=0;j<4;j++)
{
printf(“%d ”, *(*(S1+i)+j);
}
printf(“\n”);
}
注:**S1的含义:*S1取出来S1首元素的地址,
然后再**S1取出来首元素的值
用指针表示二维数组并访问
int *S1=&array[0][0];
for(i=0;i<12;i++)
{
printf(“%d ”,s1[i]);
}
printf(“\n”);
地址等级
0级地址:没有地址,就是元素本身;
一级地址:元素的地址,4字节;
二级地址:行的地址,16字节;
三级地址:数组的地址,48字节;(三行四列,12个元素,每个元素4字节)
0级地址:
a[0][0]:不存在地址,a[0][0]+1就是数值上的加1;
一级地址:
&a[0][0],a[0], *a;
二级地址:
a, &a[0], &a[1];
三级地址:
&a;
总结
对于二维数组a[3][4]:
注:*a的“*”取值号只是修改了含义,不是真正的访问内存中的数值,原本a是表示二维数组首行的地址,*取值后变成首行首元素的地址。我们可以这样记忆:原本a是二维数组的首行的地址,而一行的地址是用本行的第一个元素的地址表示的,*a里面存放的是首行的地址,即*a就是首行首元素的地址。*a的“*”主要是将二级地址变成一级地址。
1、不要把&a[i]简单的理解为a[i]的物理地址,因为并不存在a[i]这个变量。它只是一种地址的计算方法,能得到第i行的地址。
2、&a[i]和a[i]的值是一样的,但它的含义却不同。 &a[i]或a+i指向行,而a[i]或*(a+i)指向列。当下标j=0时,&a[i]和a[i]+j的值相等。*(a+i)只是a[i]的另一种表示形式。在二维数组中,a+i=a[i]=*(a+i)=&a[i]=&a[i][0]即它们的地址值是相等的。
指针的指针
指针的指针:指向指针的指针
下面这段代码存在什么问题?
void init_s(char *s1)
{s1 = malloc(1024);
}int main()
{char *s;init_s(s);strcpy(s, “helloworld”);return 0;
}
程序会死掉,因为 init_s(char *s1)的函数体运行完之后会释放掉空间,根本就无法将字符串拷贝进去。
可以改成:
void init_s(char **s1)//形参改成指针的指针
{s1 = malloc(1024);//将申请的空间的地址赋值给s1指向的那块内存
}int main()
{char *s;init_s(&s);//取指针的地址传过去strcpy(s, “helloworld”);return 0;
}
这是我之前的博文中也讲过的:如果要修改实参的值,一定要取地址!
命令行参数
main (int argc,char *argv[ ])
argc(第一个形参)必须是整型变量,
argv( 第二个形参)必须是指向字符串的指针数组。
argc参数表示了命令行中参数的个数(注意:文件名本身也算一个参数);
argv参数是字符串指针数组,其各元素值为命令行中各字符串(参数均按字符串处理)的首地址。 针数组的长度即为参数个数。
示例:
#include <stdio.h>int main(int argc, char*argv[ ])//argc是参数的个数,char*argv[ ]保存了参数的地址
{int i;for(i=0;i<argc;i++){ printf("第 %d 个参数是%s\n",i,argv[i]);} return 0;
}
运行结果:
以上就是这篇内容,如想了解更多,欢迎订阅本专栏!
如有问题可评论区或者私信留言,如果想要进交流群请私信!