回顾基础篇 《十三、C语言 - 数组

一、 数组的定义

数组的定义形式:类型 数组名[元素个数];

int buf[100];

定义数组的目的

从相关内存区域划出一片连续的内存空间,从而批量的开辟出连续的变量空间,以便我们快速、方便的访问

(1)全局数组
空间开辟于静态区.data.bss

  • 未初始化:.bss
    未初始化时,所有元素(变量)就默认初始化为0
  • 初始化:.data

(2)静态局部数组
空间开辟于静态区.data.bss

  • 未初始化:.bss
    未初始化时,所有元素(变量)就默认初始化为0。
  • 初始化:.data

(3)自动局部数组

空间开辟于栈中,如果没有初始化的话,所有元素(变量)中放的就是随机值

(4)动态数组

空间开辟于堆中,如果没有对所有元素(变量)进行赋值的话,也是随机值


二、数组名的各种相关含义

比如:

int buf[100];

buf的各种相关含义:

1. 数组名(buf)

buf做为数组名时,代表整个数组空间,sizeof(buf)时,buf代表的就是整个数组空间

我们以普通变量为例来对比介绍

int a = 10;

a就是变量名,代表整个变量空间,sizeof(a)表示获取a这个变量的空间大小(字节数)

sizeof(buf)buf为数组名,代表的就是整个数组,
此时整个数组就是一个大号的变量,所以sizeof(buf)获取的就是整个数组的的空间大小

2. buf 做为指针时

代表数组第0个元素(变量)的第一个字节的地址,等价于&buf[0]
说白了就是数组第0个元素(变量)的指针,有关这一点,其实我们在第四章就讲过

1)例子1

int main(void)
{
    int buf[100];
    fun(buf); //&buf[0]

    return 0;
}

fun(buf) 等价于fun(&buf[0]),进行数组的传参时,此时的buf就是这个含义

2)例子2

int buf[100];
int *p = buf; //等价于int *p = &buf[0];

疑问:为什么第一个元素的指针有buf这种等价形式?

答:第一个元素的指针使用非常频繁,&buf[0]写法太过繁琐,所以给出了buf这种简洁的等价形式

3. buf是常量

buf++的本质写法是buf = buf + 1,前面课程说过,= 的左边必须是可以被写的变量空间,
但是buf是只读的常量,所以buf++是无法编译通过的

疑问:buf是个符号,符号可以是一个常量吗?

答:一个符号为常量并不奇怪,比如int a&aa的指针,&a也是一个常量,所以(&a)++也是不行的

4. &buf 为整个数组的指针,也就是“数组指针”

比如:

int (*p)[100] = &buf; // p是数组指针变量,类型为 int (*)[100]

存放“数组指针的变量”就是数组指针变量

整个数组的指针,其实为整个数组的第一个字节的地址,其实就是第一个元素的第一个字节,
虽然是同一个字节的地址,但是指针含义不同,buf为第一个元素的指针,&buf为整个数组的指针

所以buf&buf值虽然相等,但是因为数据类型不同,各自的含义作用也是不同的,
C语言中同一个数据,但是由于类型不同,而导致各自有不同的含义和用途,整个是非常常见

当然&buf也是常量,所以(&buf)++也是错误的


三、一维数组里面的 buf 与 &buf 的异同

int buf[10];

1. 相同点:值相等

buf&buf值相等,因为是同一个字节的地址

验证:

printf("buf=%p, &buf=%p\n", buf, &buf); // 值是一样的

2. 不同点:指针类型不同

buf:第0个元素的指针,类型int *
&buf:为整个数组的指针,类型为int (*)[10]

这两者类型不同,导致各自的共用不同。

验证:

printf("buf+1=%p, &buf+1=%p\n", buf+1, &buf+1);

由于各自的类型不同,所以各自加1时,所得到的地址是不一样的

  • buf+1:加的是一个元素空间的大小。
  • &buf+1:加的是整个数组空间的大小

整个数组看成一个大变量,数组指针就是数组这个大变量的指针,所以数组指针+1,加的就是一个数组空间的大小

由于指针类型不同,编译器在识别buf+1&buf+1时,识别的结果是不同的:

  • buf+1:被识别为buf + 1*sizeof(int)
  • &buf+1:被识别为&buf + 1*sizeof(buf)

四、buf、buf[0]、*buf含义

一维数组例子:

int buf[10];

buf是一维数组,buf[0]指的就是第0个元素空间

buf是第0个元素指针,*bufbuf[0]都是第0个元素空间,所以我们就可以把[]*号就看作是一次解引用

五、memcpy 实现数组复制

memcpy是内存拷贝函数,memcpy可以复制任意内容,例如字符数组、整型、结构体、类等

如何将“某个数组的值”复制给“另一个数组”

int buf1[6] = {0, 1, 2, 3, 4, 5};
int buf2[6];

1)方法1:

int i = 0;
for(i=0; i<6; i++)
{
    buf2[i] = buf1[i];
}

2)方法2:通过memcpy函数来实现

函数原型:

void *memcpy(void *dest, const void *src, size_tn);
  • dest:指向目标空间
  • src:指向源空间
  • size_tn:要复制空间的大小
memcpy((void *)buf2, (void *)buf1, sizeof(buf1));

等价于

memcpy((void *)&buf2[0], (void *)&buf1[0], sizeof(buf1));

buf1中的sizeof(buf1)个字节的内容复制到buf2数组空间