C语言 一维数组详解

Posted 流楚丶格念

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C语言 一维数组详解相关的知识,希望对你有一定的参考价值。

一维数组

在程序中可以使用下标变量,即说明这些变量的整体为数组,数组中的每个变量的数据类型是相同的。

当数组中每个元素都只带有一个下标时,称这样的数组为一维数组

一维数组是由数字组成的以单纯的排序结构排列的结构单一的数组。一维数组是计算机程序中最基本的数组。二维及多维数组可以看作是一维数组的多次叠加产生的。

上面是文字性的定义描述,下面我们从其他角度来说明什么是一维数组。

多角度看一维数组

  • 元素类型角度:数组是相同类型的变量的有序集合
  • 内存角度:连续的一大片内存空间

一维数组声明

查看下面这些声明:

int a;
int b[10];

我们把a称作标量,因为它是个单一的值,这个变量是的类型是一个整数。我们把b称作数组,因为它是一些值的集合。

下标和数名一起使用,用于标识该集合中某个特定的值。例如,b[0]表示数组b的第1个值,b[4]表示第5个值。每个值都是一个特定的标量。

问题1:那么b的类型是什么呢?它所表示的又是什么?

一个合乎逻辑的答案是它表示整个数组,但事实并非如此

在C中,在几乎所有数组名的表达式中,数组名的值是一个指针常量,也就是数组第一个元素的地址。它的类型取决于数组元素的类型:如果他们是int类型,那么数组名的类型就是“指向int的常量指针”;如果它们是其他类型,那么数组名的类型也就是“指向其他类型的常量指针”。

问题2:指针和数组是等价的吗?

答案当然是否定的。

数组名在表达式中使用的时候,编译器才会产生一个指针常量。但是本身数组是伴随着程序存在在内存当中的。

问题3:那么数组在什么情况下不能作为指针常量呢?

在以下两种场景下:

  • 当数组名作为sizeof操作符的操作数的时候,此时sizeof返回的是整个数组的长度,而不是指针数组指针的长度。
    例如:

    sizeof(arr);
    
  • 当数组名作为&操作符的操作数的时候,此时返回的是一个指向数组的指针,而不是指向某个数组元素的指针常量。
    例如:

    typeid(&arr).name()
    

问题3 参考代码

#include<iostream>

void test()
{
	int arr[10];
	//arr = NULL; // arr作为指针常量,不可修改
	int *p = arr; // 此时arr作为指针常量来使用
	printf("sizeof(arr):%d\\n", sizeof(arr));			// 此时sizeof结果为整个数组的长度
	printf("&arr type is %s\\n", typeid(&arr).name());	// int(*)[10]而不是int*
}

int main()
{
	test();
	return 0;
}

下标引用

例如下面数组

int arr[] = { 1, 2, 3, 4, 5, 6 };

问题1:*(arr + 3),这个表达式是什么意思呢?

首先,我们说数组在表达式中是一个指向整型的指针,所以此表达式表示arr指针向后移动了3个元素的长度。然后通过间接访问操作符从这个新地址开始获取这个位置的值。这个和下标的引用的执行过程完全相同。所以如下表达式是等同的:

arr[3];

问题2:数组下标可否为负值?

答案是可能为负值,哈哈哈。

当然你要分清声明还是语句。

  • 声明里的中括号里的数字不能为负。例如 int a[-2]; 是错的,数组大小不能为负。
  • 语句里的中括号,C/C++ 看成运算符,不叫标点符号,可以为负数。

数组元素和指针有恒等关系:

a[i] == *(a+i)

所以,i 为 负 的时候,a[i] == *(a- fabs(i))。只要 a-fabs(i) 这个地址里 有 数值,就可以拿来运算使用。

当然还是不建议这样写的,因为如果a[-1]的地址是不确定的,万一它指向了操作系统的某块内存,则可能影响到操作系统的运行。所以不建议数组下标为负的写法。

问题2:请阅读如下代码,说出结果:

int arr[] = { 1, 2, 3, 4, 5, 6 };
int *p = arr + 2;
printf("*p = %d\\n", *p);
printf("*p = %d\\n", p[-1]);

运行结果为:

问题3: a[i]==i[a]==*(i+a)==*(a+i)?

从汇编角度去说,这样是没问题的,在编译器的眼里,数组名a不过是一段连续内存的首地址。获取某个元素a[i]不过是在a对应的首地址上做偏移,找到对应的内存地址后从中取出其中的内容即可。

我也在VS里试了试,真的是可以。

测试代码:

#include<iostream>

void test()
{
	int a[] = { 1, 2, 3, 4, 5, 6 };

	for (int i = 0; i < 6; i++)
	{
		printf("*p = %d\\n", i[a]);
	}
}

int main()
{
	test();
	return 0;
}

运行结果:

以上是关于C语言 一维数组详解的主要内容,如果未能解决你的问题,请参考以下文章

[C语言]数组详解

详解C语言指针

java怎么用一个一维数组输出杨辉三角(补充完整下列代码)

C语言中怎样区分一维指针和二维指针?

C语言指针指向一维数组与二维数组?

指针的这些知识你知道吗?C语言超硬核指针进阶版3w+字详解+指针笔试题画图+文字详细讲解