C语言入门 – 一维数组

LongGuan_admin 发布于 3 天前 25 次阅读


数组概念

  • 存储相同数据类型的多个元素的复合的数据类型
    • 将逻辑上的一组数据存储在一段连续的内存中
      • 方便数据的管理
  • int score[5] 中,表示声明数组变量score长度为5每个元素的类型为int
    • score自身的数据类型为 int [5] 类型
  • 判断变量的自身类型
    • 去掉变量名后 剩余的就是自身类型

数组的初始化

  • 数组的初始化只有在声明(定义)时可以初始化,声明后不可以初始化
    • 原因是数组声明后不支持整体赋值 ,只能在声明时进行整体赋值
int arr1[5] = {1,2,3,4,5};
int arr2[5];
arr2 = {1,2,3,4,5}; //error 声明后不允许初始化

数组的特点

  • 数组中所有元素的数据类型都是一致的
  • 数组的内存是连续的,从低地址到高地址依次连续存放数组中的每一个元素

数组的赋值

  • 数组只有在声明的时候支持整体赋值
  • 数组如果初始化,可以在声明时省略数组长度,此时数组的长度将由编译器隐式指定
  • 数组的初始化可以部分赋值,没有赋值的元素会自动赋值0
  • 数组整体赋值,值长度不能超过数组的长度(不会报错,但是会产生段错误:非法访问内存)
  • 数组清零int arr[4] = {0};
  • 数组若没有初始化,不能省略数组长度,其内部的元素为随机数
  • 数组声明完毕后,只能通过下标逐个对元素进行赋值
    • 下标地址偏移
      • 下标就是地址偏移量,基于数组内存连续切元素大小相同的性质,偏移下标个元素自身大小的字节
      • 语法:数组名[下标]

  • 数组的长度计算
    • 数组的总大小 / 数组中首个元素的大小 = 数组内元素的个数
    • int arrLen = sizeof(arr) / sizeof(arr[0])

变长数组

  • 变长数组在定义时 使用变量作为数组的长度(长度可以是运行期变量)
    • 普通数组的长度必须是编译期常量
  • 变长数组不支持初始化
  • 变长数组不能是全局变量
    • 普通数组可以是全局变量,也可以是静态/局部变量
  • 变长数组部分编译器不支持
    • 普通数组所有C编译器都会支持

字符数组

数组元素是char(字符型)的数组,它可以是一维数组,也可以是二维数组

  • 以双引号括起来的称为字符串类型,可以将其看作char类型的字符集合,在结尾会又以给“\0”(表示空)
    • ‘\0' ASCII码为0
      • 作用是表示一串字符串的结束
        • 操作字符串时带入字符串的首地址,所以需要结束符来结束操作
  • <string.h>官方提供的字符串操作库
    • strcpy()函数
      • char *strcpy(char *dest, const char *src);
        • dest 目标字符数组
        • src 原字符串(const表示不改变源字符串)
  • 字符串长度 不一定等于 字符数组长度
    • 字符串长度: 字符起始位置到 \0 之间间隔的字符数量
char c1[2] = {'a','b','c'};//这不是一个字符串,右边全部被赋值,只能是一个字符数组
char c2[] = {"abc"};
//c3等价于c2数组
char c3[] = {'a','b'.'c','\0'};
char c4[3] = {'a','b','c'};//这是一个字符串 部分赋值后补0 相当于给结尾补了\0

数组名的含义

  • 在C语言程序中,数组的出现有两种的可能的含义
    • 代表整个数组
      • 声明时 int arr 此时数组可以整体赋值
      • 与sizeof使用时 sizeof(arr)
      • 取地址时 &arr
    • 代表首元素的地址
      • 其他情况一律表示首元素的地址
//数组的声明arr表示整个数组
int arr[] = {1,2,3,4};
//此处arr与sizeof结合,arr表示整个数组
printf("%ld \n", sizeof(arr));
//此处arr与&取地址符结合,aee表示整个数组
printf("%p \n", &arr);
//arr除了以上三种情况,都表示首元素的地址
printf("%p \n", arr);
等价于
printf("%p \n", &(arr[0]));
printf("%d \n", &arr);
printf("%d \n", arr[0]);

数组的下标运算符

arr[下标] 是 *(arr + 下标)的简写

  • 地址的(整数)加法运算
    • 本质上是地址指向的那段内存的偏移
int a;
char b;
double c;
//a是一个int类型的内存,大小为4,地址+1等于地址偏移一个(自身)内存(4)的大小
printf("地址 %p \n",&a); 
printf("地址 %p \n",&a + 1);
//b c 同理
int arr[5] = {1,2,3,4,5};
printf("地址 %p \n",arr);// 0xffffcbd0 首元素的地址
printf("地址 %p \n",&arr);// 0xffffcbd0 整个数组的地址

printf("地址 %p \n",arr + 1);// 首元素的地址 + 1,偏移1个首元素大小字节(+4) 0xffffcbd4
printf("地址 %p \n",&arr + 1); //整个数组的地址+1,偏移1个数组自身大小字节(+20)  0xffffcbe4
  • 地址与地址不能相加,但是地址可以和地址相减
    • 表示两个地址之间间隔相同元素大小的偏移量
      • 只有相同类型可以相减,不同类型不能相减
int d, e, f;
printf("d:%p \n e:%p \n f:%p \n", &d, &e, &f);
printf("%d \n", &d - &f );
//d:0xffffcbcc
//e:0xffffcbc8
//f:0xffffcbc4
//偏移量 2

解引用符

  • ’ * ‘ 解引用符
    • 根据内存地址找到某段内存获取其值
    • (缩小范围,范围缩到不能缩时取值)
  • ’ & ‘取地址符
    • 返回指定(变量)内存的地址
    • (地址向上扩大其范围)
int arr[5] = {1,2,3,4,5};
printf("%d \n", *arr); // arr表示首元素地址,* 根据首元素的地址找到首元素获取它的值
//arr == &(arr[0])
//*arr == *&(arr[0]) == arr[0]
printf("%d \n", *&arr); // arr首元素地址

int arr[5];
scanf("%c", arr); // 等价于scanf("%c", &(arr[0]));
scanf("%c", arr + 1);// 等价于scanf("%c", &(arr[1]));

%S 本质上是接受一个地址,向后读取字符直到\0 截止

字符串操作

  • 字符串常量
    • 在内存中存储,实质上是一个匿名数组(没有变量名)
      • 匿名数组
        • 满足数组两种涵义的规定
        • 匿名数组是只读的,字符串常量不可改变(编译不报错,运行会报错)
      • 程序运行时,内存分为栈、堆、数据段
        • 常量存储在数据段里
printf("%d\n", sizeof("abcd")); // 此处 "abcd" 代表整个数组
printf("%p\n", &"abcd");        // 此处 "abcd" 代表整个数组

printf("%c\n", "abcd"[1]); // 此处 "abcd" 代表匿名数组的首元素地址
char *p1 = "abcd";         // 此处 "abcd" 代表匿名数组的首元素地址
char *p2 = "abcd" + 1;     // 此处 "abcd" 代表匿名数组的首元素地址
  • 字符串的拷贝
    • 作用:将src字符串 拷贝到dest
      • char *strcpy(char *dest, const char *src);
      • dest 目标字符串 src:源字符串
  • 字符串的比较
    • 作用:比较两个字符串的是否相同
      • int strcmp(const char *s1, const char *s2);
      • 如果相同返回0,如果不同返回第一个不同字符的差值
  • 字符串的长度测量
    • int length = strlen(str1);
      • 长度不包括'\0'

字符串常量数组

char *arr["hello","world","aaa"];

helloworldaaa
首元素地址0x1230x4560x789
  • 上面的arr是一个数组
    • 里面的子元素起始只是字符串常量首元素的地址
    • arr长度为3 子元素类型为 char * (字符地址)类型
printf("%s", arr[0]); //本质上是把hello字符串的首地址传给%s,找到这段内存后顺序读取,直到\0结束,读取到hello并打印
printf("%s", arr[0] + 1); //本质上是0x123+1 等于0x124,等同于'e'的地址,然后向后输出
*(arr[0] + 1) 地址先进行加法运算(偏移),再解引用(根据地址(arr[0] + 1 == 0x124)取值)

*(arr[0] + 1) 地址先进行加法运算(偏移),再解引用(根据地址(arr[0] + 1 == 0x124)取值)

对于上述代码,可以有万能公式的转换

arr[0][1] == 'E' 不能修改,因为引用的hello是一个常量

此作者没有提供个人介绍。
最后更新于 2026-01-13