利用数组处理批量数据

5.1 数组的作用

什么是数组?

数组就是一串连续的内存空间

下面是很久以前看了《c和指针》的笔记,今天去网上查了一下,发现还有很多人持不同观点,于是准备重新梳理,按自己的理解总结下

数组通过首地址来查找到他,其实就是数组名,数组名其实就是个不能修改的指针常量,指向数组第一个位置;当数组名作为sizeof操作符或&操作数时,sizeof返回整个数组长度

原文是这个数组名和指针的区别,他认为 数组名绝对不等于指针,而且不是指针 ;我认为数组名确实不等于指针,但他是个指针,而且是个常量指针,不可修改;虽然不知道底层是不是一定就是用指针常量实现的,但从理解上,数组名外在就是表现了指针常量的特性

首先有一些基础概念

指针常量,也叫常指针,是指指针所指向的位置不能改变

1
类型 * const 指针名;

区别于指向常量的指针,是指指针指向的位置所存的值是前面申明的类型

1
const 类型 *指针名;

我认为数组名是个常指针,假设成立,那么数组名这个指针就因该有他的指针地址,指针里面存的值应该是数组的首地址,且这个值不能修改,通过代码验证

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <iostream>
int main()
{
int a = 1;
int *p=&a;
printf("a:%p\n", a);
printf("a地址:%p\n", &a);
printf("p:%p\n", p);
printf("&p地址:%p\n", &p);
int arr[2] = { 1,2 };
printf("arr:%p\n", arr);
printf("arr[0]:%p\n", arr[0]);
printf("arr地址:%p\n", &arr);
printf("arr[0]地址:%p\n", &arr[0]);
}

结果

部分汇编

1
2
3
    int arr[2] = { 1,2 };
008D2173 mov dword ptr [arr],1
008D217A mov dword ptr [ebp-24h],2

看到这,确实在声明数组的时候,并没有给数组名申请额外的地址空间,看上去数组名没有自己独立的空间,也就不算指针,也就得出数组名不是指针了;所以链接这篇是有道理的

后面我又查了《深入理解计算机系统》P176面有一句关于数组名的描述

它(数组)引入了标识符A(指数组名),可以用A来作为指向数组开头的指针;

所以,我最后我偏向于:数组名不等于指针,数组名不能修改就是因为它标记了数组的位置,改了之后就不是原来的数组了;但数组名底层很可能就是用常量指针实现的,表现出了它的一些特性,可以理解为类似常量指针;但是在汇编中并没有看到它为他专门分配空间,不等于底层一定没有这样做,所以也不能绝对,毕竟编译器在底层干了啥,优化了啥我们都不知道;

最后我去查了《c和指针》

5.2.1 一维数组元素的引用

数组名 [下标]

下标只能为整型常量或整型表达式,[]可以指针加上偏移量,下标引用和间接访问实际是一样的,不过有时下标引用可读性好一些

2[arr]也是合法的

5.2.2 一维数组的初始化

  数组初始化是在编译阶段进行的,所以初始化时就要确定数组长度

  1. 定义时初始化
1
int a[2]={1,2};

2.只赋值部分

1
int a[5]={1,2};

表示前两个赋初始值,后三个赋0

3.赋全0可以省略

1
int a[5]={0};

4.数组元素个数确定时,可以不指定数组长度

1
2
int a[5]={0,1,2,3,4};
int a[]={0,1,2,3,4};

字符型数组会初始化为 ‘\0’,指针数组会初始化为NULL

5.3 二维数组

5.3.1 定义二维数组

类型 数组名[行数] [列数];

5.3.2 二维数组的初始化

 二维数组可按行分段赋值,也可按行连续赋值。

  例如对数组 a[5][3]:
1) 按行分段赋值可写为:

1
int a[5][3]={ {80,75,92},{61,65,71},{59,63,70},{85,87,90},{76,77,85} };

复制

2) 按行连续赋值可写为:

1
int a[5][3]={ 80,75,92,61,65,71,59,63,70,85,87,90,76,77,85};

复制

  这两种赋初值的结果是完全相同的。

  对于二维数组初始化赋值还有以下说明:

  1. 可以只对部分元素赋初值,未赋初值的元素自动取0值。
  2. 如对全部元素赋初值,则第一维的长度可以不给出。

5.4 字符数组

5.4.1 定义字符数组

char 数组名[];

5.4.2 字符数组初始化

1
2
char a[5]={'a','b','c','d','e'};
char a[]={'a','b','c','d','e'};

5.4.5 如何输出输出字符串

1
2
3
4
char a[5];
scanf("%s",a)
char b[]={"hello"};
printf("%s",b)

5.4.7 字符串处理函数

传入的实参可以是字符串数组也也可以是字符指针

函数名 作用
puts(char const*strPtr) 输出字符串
gets(char *strptr) 输入字符串
const char str1,const char str2 连接两个字符数组,把2接到1后
strlen(char const*string) 获取字符串的长度,返回的是字符的个数,但是不会包括’\0’,结束符
strcpy(char *des,char*src); 将src指向的字符串拷贝到des指向的字符串数组中去,结束符也一同进行拷贝
strcmp(const char * str1,const char *str2); 按照ascii码来进行比较,以第一个不同的字符为准,大于0,字符串1大于字符串2,小于0,字符串1小于字符串2,
strlwe(char const*string) 转小写字符
strupr(char const*string) 转大写字符