心态崩了?int p[4];int (*p)[4];和int *p[4];三种数组定义详解

三种定义数组形式的区别

  • int p[4];
  • int (*p)[4];
  • int *p[4];

初学C语言时,很难分清楚到底三者有何区别,尤其还涉及c语言的灵魂——C指针,下面,我将详细介绍一下三种定义方式,希望对正困惑的你有所帮助。

1.分析第一种方式——int p[4];

我相信接触过数组的,不管是任何所学的编程语言,这种定义应该最常见也最方便理解的吧。

1.1定义解释

int p[4];表示定义了一个整型数组,数组名为p(数组名表示该数组在内存存放的首地址,故p为数组的首地址),此数组有4个元素,并且每个元素也都是int类型,定义该数组会开辟sizeof(int) * 4个字节的连续存储空间。

1.2数组在内存中的存放形式:

在这里插入图片描述

2.分析第二种方式——int (*p)[4];

这种定义方式经常与二维数组联用

2.1解释定义

int (*p)[4];表示p是一个指针变量,指向一个存放4个整型元素的一维数组,且p+1(或p-1)是向前(或向后)移动数组长度个字节的大小。其中,指针变量指向一维数组的指针变量,指向二维数组中的某一行。
而第一种方式的p+1(或p-1)是向前(或向后)移动int个字节的大小。

2.2该方式在与二维数组的联用

设有如下二维数组:

int (*p)[4];
int a[3][4] = {
	{1,2,3,4},
	{5,6,7,8},
	{9,10,11,12}
};

利用指向由4(二维数组列数)个元素组成的一维数组的指针变量引用二维数组
在这里插入图片描述
当执行 p = a时,内存存储情况变为:
在这里插入图片描述
当 p ++ 时:
在这里插入图片描述
即 此时p[0][0] 的值等于a[1][0]的值为5.

注:(*(a + i) + j)等价于 *(a[i] + j) 等价于a[i][j]*。
例如:(*(a + 1) + 2) =  *(a[1] + 2) = a[1][2]
	若:int (*p)[4];
		p = a;
	则:(*(p + 1) + 2) =  *(p[1] + 2) = p[1][2]
3.分析第三种方式——int *p[4];

这种定义方式等价于 int *(p[4]); 代表定义了一个指针数组,p是指针数组名,数组中的每个元素存放的是指向整型变量的指针(int * 类型)

3.1内存中的存放形式

在这里插入图片描述
和普通数组一样,指针数组在内存中分配连续的存储空间,指针数组也可以初始化。指针数组元素在使用时与同类型的指针变量相同。

3.2定义一字符型指针数组
char *name[] = {"Beijing","Hebei","Shanxi"};

则在内存中的存储形式:
在这里插入图片描述

#include<stdio.h>
#include<string.h>

int main()
{
	char *name[] = {"Beijing","Hebei","Shanxi"};
	puts(name[0]); //输出Beijing
	puts(*name);   //输出Beijing

	puts(name[2]); //输出Shanxi

	puts(*(name + 1));  //输出Hebei
	return 0;
}

如果是 char * s = name[1]; puts(s + 3) 则输出什么?
我们继续分析存储情况:
在这里插入图片描述
故输出:ei

讲到现在,我相信你对这三种定义方式大概有所熟悉,其实难理解的主要就是指针操作。C语言的指针,可以使得程序更加简洁、紧凑、高效。我们学习C语言的人,都应当熟练掌握指针操作,即使现在只是涉及入门内容。

  • 71
    点赞
  • 370
    收藏
    觉得还不错? 一键收藏
  • 14
    评论
这段代码存在一些问题,可能会导致程序溃或者输出错误结果。 1. 在函数 pstract 中,使用 sizeof(s1)/sizeof(int) 来计算数组 s1 的元素个数是不正确的。因为在函数中传递的数组参数 s1 实际上是一个指针,sizeof(s1) 返回的是指针类型的字节数,而不是数组的总字节数。应该在调用函数时,同时传递数组的长度信息。 2. 在函数 pstract 中,往数组 s1 中添加元素时,没有判断 s1 的长度是否足够。这可能会导致数组越界访问,从而导致程序溃或者输出错误结果。 3. 在主函数中,使用 printf("%s",s1) 来输出数组 s1 的内容,这是错误的。因为数组 s1 中存储的是整数类型的数据,而不是字符串类型的数据。应该使用循环逐个输出数组中的元素。 下面是一种可能的修改方案: ``` #include <stdio.h> int *pstract(int*, int*, int); int main(void) { int s1[5] = {1, 2, 3, 4, 5}; int s2[3] = {1, 2, 3}; int *w; w = pstract(s1, s2, 5); for (int i = 0; i < 5; i++) { printf("%d ", s1[i]); } printf("\n"); return 0; } int *pstract(int *s1, int *s2, int len) { int *q = s2; int *p = s1 + len - 1; while (*q != '\0' && p >= s1) { *p-- = *q++; } return s1; } ``` 修改后的程序中,将数组长度作为参数传递给函数 pstract,避免了使用 sizeof 计算数组长度的问题。在函数 pstract 中,加入了对 s1 数组长度的判断,避免了数组越界访问的问题。在主函数中,使用循环逐个输出数组 s1 中的元素,避免了将整数数组误认为字符串数组的问题。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 14
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值