数组的定义和运算

一维数组的定义和使用

一维数组的定义

  c 语言所有的变量,函数必须先声明后使用,就好比日本动漫一样,在出招之前必须先吼一嗓子,“橡胶火箭炮”,“螺旋丸”,然后才能打出这个技能。

  数组也不例外。一维数组的定义:类型标识符 数组名[元素个数],如 int a[5]。

  方括号[],在不同的地方有不同的含义,在声明的时候表示数组的个数,在声明以外表示访问数组的元素,也叫下标运算。

  数组的定义方式一:定义数组的同时,指定大小,并进行初始化。


#include <stdio.h>
#include <stdlib.h>

int main()
{ 
  int ary[5] = { 1, 2, 3, 4, 5};

  system("pause");
  return 0;
}

  如果初始化比较复杂,例如有运算,初始化的值等于某个函数返回值时,可以单独起一行。


#include <stdio.h>
#include <stdlib.h>

int main()
{ 
  int ary[5] = { 
    1, 
    2, 
    3, 
    4, 
    5
  };

  system("pause");
  return 0;
}

  单独起一行的好处在于,可以通过单步调试看到数组初始化时内存变化的过程。如果哪个值出现错误,可以清晰的发现。

  按 F10 进行单步调试,当执行赋值 1 之后,可以看到 0019ff1c 的地址填入了 00000001。

《数组的定义和运算》
  依次按 F10 ,可以看到 2, 3, 4, 5 依次成功被写进了内存中。

  当数组指定大小大于初始化个数时,分配数组指定大小的空间,初始化部分正常初始化,未初始化空间用 0 赋值。


#include <stdio.h>
#include <stdlib.h>

int main()
{ 
  int ary[5] = { 1, 2, 3};

  system("pause");
  return 0;
}

  按 F10 进行单步调试,编译器为数组分配了 5 个 int 类型的长度,前 3 个赋值为 1, 2, 3 后 2 个赋值为 0 。

《数组的定义和运算》
  数组的定义方式二:定义数组的同时,不指定大小,并进行初始化。


#include <stdio.h>
#include <stdlib.h>

int main()
{ 
  int ary[] = { 1, 2, 3};

  system("pause");
  return 0;
}

  编译器会以初始化列表的总个数,确定数组元素的大小,按 F10 进行单步调试,可以看到 1, 2, 3 被写进内存,占用长度为 3 个 int 型空间。

《数组的定义和运算》
  数组的定义方式三:定义数组时指定大小,但不进行初始化


#include <stdio.h>
#include <stdlib.h>

int main()
{ 
  int ary[5];

  system("pause");
  return 0;
}

  此时数组中的值,为栈上残留值。在 debug 模式下,默认是 cccccccc。

  按 F10 进行单步调试,此时编译器为数组分配了 5 个 int 类型的空间,内容为 cccccccc

《数组的定义和运算》

数组的运算

  数组名:表示数组第 0 个元素的地址常量

#include <stdio.h>
#include <stdlib.h>

int main()
{ 
  int ary[5];
  
  printf("%08x\r\n", ary);

  system("pause");
  return 0;
}

  按 F10 进行单步调试,可以看到数组 ary 是一个常量,也是数组第 0 个元素的地址常量

《数组的定义和运算》
  打印出来 ary 的值就是 0019ff1c

《数组的定义和运算》
  数组特性:数组元素类型一致,排列连续

   数组下标运算规则

  定义某类型的数组 type ary[M]……

  定义 int 类型变量 int n = ……

   以人类视角分析,ary[n] 是取得数组 ary 第 n 个元素的值。以机器视角分析,ary[n] 是计算数组 ary 第 n 个元素的地址并访问。

  在讲数组的下标运算之前,先假设有这样一个场景:一间教室,有一堵墙,第一张桌子距离墙面 120 cm,所有的桌子宽为 80 cm,并且这些桌子连续摆放。那么第 n 张桌子距离墙面的距离就有 120+80*(n-1) cm。

《数组的定义和运算》
   按人类的认知,数组的下标是从 1 计数的。假设数组的首地址为 0x0018ff30,第 n 个元素的地址公式就是 0x0018ff30+(n-1)*sizeof(type)。

   从公式可以看出,计算数组的地址,需要加法,减法,乘法,这时为了提高效率,数组的下标就不从 1 开始计数,而是从 0 开始计数,这样就可以减少一次减法运算。

   数组的下标从 0 计数,假设数组的首地址仍为 0x0018ff30 第 n 个元素的地址公式就是0x0018ff30+n*sizeof(type)。

   从而得出,通用的数组地址公式为:ary[n] 的地址是(int)ary + sizeof(type)*n。运用公式必须有两个操作数,一个操作数必须是某类型的地址,另一个操作数必须为整形类。取出某类型的地址代入到公式 ary 部分,取出整形代入到上述公式中 n 部分,取出数组元素的类型代入到上述公式中 type 部分。

   如果是这样,那么 &ary[2] 和 (int)ary + sizeof(int)*2 是等价的。&ary[n] 和 (int)ary + sizeof(int)*n 也是等价的。编写程序进行验证。

#include <stdio.h>
#include <stdlib.h>

int main()
{ 
  int n = 5;
  int ary[5];
  
  printf("%08x\r\n", &ary[2]);
  printf("%08x\r\n", (int)ary + sizeof(int)*2);
  
  printf("%08x\r\n", &ary[n]);
  printf("%08x\r\n", (int)ary + sizeof(int)*n);

  system("pause");
  return 0;
}

《数组的定义和运算》
《数组的定义和运算》
   为了验证上面对公式的理解,下面做一道题目,求出 printf 的值,通过调试,已知 ary 的值是 0x0019ff18。

#include <stdio.h>
#include <stdlib.h>

int main()
{ 
  //ary == 0x0019ff18
  int n = 5;
  int ary[5] = { 10, 20, 30, 40, 50};
  
  printf("%08x\r\n", &ary[2]);
  printf("%08x\r\n", &ary[-2]);
  printf("%08x\r\n", &ary[n+6]);
  printf("%08x\r\n", &ary[ary[2]]);
  printf("%08x\r\n", &n[ary]);

  system("pause");
  return 0;
}

   &ary[2] = 0x0019ff18 + 4*2 = 0x0019ff20

   &ary[-2] = 0x0019ff18 + 4*(-2) = 0x0019ff10

   &ary[n+6] = &ary[11] = 0x0019ff18 + 4*11(十六进制 2c) = 0x0019ff44

   &ary[ary[2]]=&ary[30] = 0x0019ff18 + 4*30(十六进制 78) = 0x0019ff90

   &n[ary] = ary + 4*5(十六进制 14) = 0x0019ff2c

   编译运行后,与手算的结果一致。

《数组的定义和运算》

想了解更多 C/C++ 或 网络安全知识,请关注公众号:大人物小城梦

《数组的定义和运算》

    原文作者:bmstd
    原文地址: https://blog.csdn.net/qq_42019874/article/details/111463050
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞