c语言中数组和数组的一些计算

其实你这个疑问是概念上的混淆,或者说对指针了解上上的欠缺

首先讲int a[3] = {2,3,4};
这里的a是这个数组的首地址,比如定义如:int *p = a;这时如果你进行如下操作:
p++;
printf("%d\n",*p);
结果会是输出2,也就是说p+1相当于数组索引加1,但是像你所问的为什么&a和a是相同的 ,首先要知道他们分别代表什么意思,a:像上面所说的是数组的首地址,做自加运算会根据数组类型来计算偏移量,那么&a是什么东西呢,实际上它也是一个指针,是指向一个具有3个元素的数组的指针,如何理解,看以下定义:

如果你定义int *q = &a;这时编译器肯定报错,绘制出数据类型不一致,那么你这样样定义就没有问题:int (*q)[3] = &a;这时如果你再对q进行++操作,那么加的就不同了,如相面的p++操作后p的值会加4,而这里q++操作后的值会加12,也就是跳过3个数组元素,然而,确实这两个指针的初始值是一样的,只是类型不一样而已,这对二维数组的访问时很方便的,这个你可以参照2维数组得到进一步理解,讲的有点乱,不知道你能不能理解


c语言中数组和数组的一些计算

1.数组的创建
元素类型 数组名 []     eg:int arr[10]
注意:[]内是一个常量表达式,用来指定数组的大小


2.数组的初始化
若指定数组大小,可以不进行初始化,若数组完全初始化后,可以不指定其大小
注意:字符串放在字符数组中,默认后面有'\0',字符数组是里面有哪些元素,就是哪些元素..


3.指针初步,指针是一个专门用来存放地址的变量,内存中一个内存单元对应一个地址,
注意:在32位平台上指针(地址)的大小始终为4个字节,64位平台上是8个字节...


4.数组的计算

维数组

(1)

  1. int main()
  2. {
  3. //一维数组
  4. int a[] = {1,2,3,4};
  5. //size of ----一个操作符,可以求出操作数的类型长度(以字节为单位)
  6. printf("%d\n",sizeof(a));//==16
  7. //本身数组名一般代表的是数组首元素的地址,但当数组名单独放在sizeof内部代表的是整个数组中全部元素,因此sizeof(a),求取的是 整个数组中所有元素的类型长度,数组中有4个整型元素,一个整型元素在内存中会占4个字节,因此求出来的类型长度为4*4==16个 字节;
  8. printf("%d\n",sizeof(a+0));//==4
  9. //sizeof(a+0),由以上叙述可以知道,此处sizeof后边的a代表的是数组首元素中的地址,加上0还是代表数组首元素的地址,而地址 在内存中占用的空间全部都是4个字节,因此,此处的长度为4;
  10. printf("%d\n",sizeof(*a));//==4
  11. //此时数组名同样没有单独放在sizeof内部,因此a代表数组首元素的地址,加上*,解引用后,表示的是此数组第一个元素--1,1作为 一个整型元素,在内存中占4个字节,因此求出的长度是4;
  12. printf("%d\n",sizeof(a+1));//==4
  13. //此时,a依然代表的是数组首元素的地址,加上1之后表示第二个元素的地址,地址在内存中占用的空间是4个字节,因此求出的长度 为4;
  14. printf("%d\n",sizeof(a[1]));//==4
  15. //a[1] == 2;2作为一个整型元素,在内存中占4个字节,因此求出的长度是4;
  16. printf("%d\n",sizeof(&a));//==4
  17. //&a代表的是整个数组的地址,依旧是个地址,而地址在内存中占用的空间全部都是4个字节,因此,此处的长度为4;
  18. printf("%d\n",sizeof(*&a));//==16
  19. //&a代表的是整个数组的地址,加*号解引用后,代表的是整个数组元素,数组中有4个整型元素,一个整型元素在内存中会占4个字 节,因此求出来的类型长度为4*4==16个字节;
  20. printf("%d\n",sizeof(&a+1));//==4
  21. //&a代表的是整个数组的地址,&a+1指向的跳过该数组的下一个地址,而地址在内存中占用的空间全部都是4个字节,因此,此处的 长度为4;
  22. printf("%d\n",sizeof(&a[0]));//==4
  23. //&a[0]代表的是数组第一个元素的地址,而地址在内存中占用的空间全部都是4个字节,因此此处的长度为4;
  24. printf("%d\n",sizeof(&a[0]+1));//==4
  25. //&a[0]代表的是数组第一个元素的地址,&a[0]+1指向的是第二个元素的地址,而地址在内存中占用的空间全部都是4个字节,因此此 处的长度为4;
  26. printf("%p\n",a);//==0038F9EC,数组首元素地址
  27. printf("%p\n",a+1);//==0038F9F0,数组中第二个元素地址,与上一个元素地址差4
  28. printf("%d\n",sizeof(*a));//==4,数组首元素地址解引用,代表数组第一个元素的值,占用4个字节的空间
  29. printf("%p\n",&a);//==0038F9EC,虽然&a代表整个数组的地址但为了方便起见,传回来的是首元素的地址
  30. printf("%p\n",&a+1);//==0038F9F0,&a代表整个数组的地址,+1后代表跳过数组后的那个一个地址值,与上一个差16;
  31. printf("%d\n",sizeof(*&a));//==16,&a代表的是整个数组的地址,加*号解引用后,代表的是整个数组元素,数组中有4个整型元素,一个整型元素在内存中会占4个字节,因此求出来的类型长度为4*4==16个字节;
  32. return 0;
  33. }


字符数组

(1)

  1. int main()
  2. {
  3. //字符数组
  4. char arr[] = {'a','b','c','d','e','f'};
  5. //size of ----一个操作符,可以求出操作数的类型长度(以字节为单位)
  6. //此时数组中元素有[a,b,c,d,e,f],一共6个元素
  7. printf("%d\n", sizeof(arr));//==6
  8. //数组名单独存放在sizeof中代表整个数组中所有元素,一个字符型元素在内存中占用空间1个字节,一共6个元素,因此求出的长度是6;
  9. printf("%d\n", sizeof(arr+0));//==4
  10. //sizeof(arr+0),此处sizeof后边的a代表的是数组首元素中的地址,加上0还是代表数组首元素的地址,而地址在内存中占用的空间全部都是4个字节,因此,此处的长度为4;
  11. printf("%d\n", sizeof(*arr));//==1
  12. //此时数组名同样没有单独放在sizeof内部,因此a代表数组首元素的地址,加上*,解引用后,表示的是此数组第一个元素__'a','a'作为一个字符型元素,在内存中占1个字节,因此求出的长度是1;
  13. printf("%d\n", sizeof(arr[1]));//==1
  14. //arr[1]代表的是第二个元素'b'个,作为一个字符型元素,在内存中占用1个字节的长度;
  15. printf("%d\n", sizeof(&arr));//==4
  16. //&arr代表的是整个数组的地址,依旧是个地址,而地址在内存中占用的空间全部都是4个字节,因此,此处的长度为4;
  17. printf("%d\n", sizeof(&arr+1));//==4
  18. //&arr代表的是整个数组的地址,&arr+1指向的跳过该数组的下一个地址,而地址在内存中占用的空间全部都是4个字节,因此,此处的长度为4;
  19. printf("%d\n", sizeof(&arr[0]+1));//==4
  20. //&arr[0]代表的是数组第一个元素的地址,&arr[0]+1指向的是第二个元素的地址,而地址在内存中占用的空间全部都是4个字节,因此此处的长度为4;
  21. return 0;
  22. }

(2)

  1. int main()
  2. {
  3. char arr[] = {'a','b','c','d','e','f'};
  4. //此时数组中元素有[a,b,c,d,e,f],一共6个元素
  5. //strlen函数,参数是要开始寻找元素字符串的起始地址,返回值是字符串中字符的数量(不包括最后'\0'这个结束标志)
  6. printf("%d\n", strlen(arr));//==随机值
  7. //arr 代表数组首元素地址,将数组首元素地址传给strlen函数,该函数从该地址开始数数,直到碰到'\0'为止,因此输出为随机值
  8. printf("%d\n", strlen(arr+0));//==随机值
  9. //arr+0 代表数组首元素地址,将数组首元素地址传给strlen函数,该函数从该地址开始数数,直到碰到'\0'为止,因此输出为随机值
  10. printf("%d\n", strlen(*arr));//==程序中断
  11. printf("%d\n", strlen(arr[1]));//==程序中断
  12. //上面*arr,对数组首元素地址解引用,表示第一个元素'a',而arr[1]也表示元素'a',这样会把字符a的ascii码值97传给strlen函数,而此函数是访问不到这个地址的,因此会程序中断!
  13. printf("%d\n", strlen(&arr));//随机值
  14. printf("%d\n", strlen(&arr+1));//随机值
  15. printf("%d\n", strlen(&arr[0]+1));//随机值
  16. //以上三个都是因为'\0',没有在数组中,因此会显示随机值!
  17. return 0;
  18. }

(3)

  1. int main()
  2. {
  3. char arr[] = "abcdef";
  4. //此时数组中含有[a,b,c,d,e,f,\0]
  5. printf("%d\n", strlen(arr));//==6
  6. //数组首元素地址传给函数,数组中有'\0',前有6个元素!
  7. printf("%d\n", strlen(arr+0));//==6
  8. ////数组首元素地址传给函数,数组中有'\0',前有6个元素!
  9. printf("%d\n", strlen(*arr));//error
  10. printf("%d\n", strlen(arr[1]));//error
  11. //上面*arr,对数组首元素地址解引用,表示第一个元素'a',而arr[1]也表示元素'a',这样会把字符a的ascii码值97传给strlen函数,而此函数是访问不到这个地址的,因此会程序中断!
  12. printf("%d\n", strlen(&arr));//==6
  13. //数组首元素地址传给函数,数组中有'\0',前有6个元素!
  14. printf("%d\n", strlen(&arr+1));//==随机值
  15. //&arr表示整个数组地址,+1表示跳过该数组后第一个地址,又在寻找'\0',所以是随机值!
  16. printf("%d\n", strlen(&arr[0]+1));//==5
  17. //将第二个元素地址传给函数,知道寻找到'\0',所以为5
  18. return 0;
  19. }

(4)

  1. int main()
  2. {
  3. char *p = "abcdef";
  4. //数组中内容[a,b,c,d,e,f,\0]
  5. //此时把数组中首元素地址,存放在指针变量p中去了
  6. printf("%d\n", sizeof(p));//==4
  7. //p是数组中首元素地址,地址在内存中均占用4个字节的位置,因此为4;
  8. printf("%d\n", sizeof(p+1));//==4
  9. //p是数组中首元素地址,p+1表示首元素地址后面的那个地址,地址在内存中均占用4个字节的位置,因此为4;
  10. printf("%d\n", sizeof(*p));//==1
  11. //p是数组中首元素地址,地址解引用,表示数组第一个元素'a',他是一个字符型元素,在内存中占用1个字节;
  12. printf("%d\n", sizeof(p[0]));//==1 == *(p+0) == *(arr+0) == arr[0yi]
  13. //p是数组中首元素的地址,而arr也表示数组中首元素的1地址,从某种角度来说,arr[0]和p[0]是等价的,表示首元素'a',他是一个字符型元素,在内存中占用1个字节;
  14. printf("%d\n", sizeof(&p));//==4
  15. printf("%d\n", sizeof(&p+1));//==4
  16. printf("%d\n", sizeof(&p[0]+1));//==4
  17. //以上三个都是一个类型,都是取出来的地址,地址在内存中占4个字节,因此为4!
  18. printf("%d\n", strlen(p));//==6
  19. //将数组元素首地址传递给给函数,数组中有'\0',所以有6个元素!
  20. printf("%d\n", strlen(p+1));//==5
  21. //将数组元素首地址的下一个地址,也就是第二个元素的地址,传递给给函数,数组中有'\0',所以有5个元素!
  22. printf("%d\n", strlen(*p));//error
  23. printf("%d\n", strlen(p[0]));//error
  24. //上面*p,对数组首元素地址解引用,表示第一个元素'a',而p[1]也表示元素'a',这样会把字符a的ascii码值97传给strlen函数,而此函数是访问不到这个地址的,因此会程序中断!
  25. printf("%d\n", strlen(&p));//随机值
  26. //&p表示对指针变量再取地址传入函数中,而中从此处开始查找的时候,后面并没有'\0',所以是随机值
  27. printf("%d\n", strlen(&p+1));//随机值
  28. //&p表示对指针变量再取地址,然后这个地址的下一个地址传入函数中,而中从此处开始查找的时候,后面并没有'\0',所以是随机值
  29. printf("%d\n", strlen(&p[0]+1));//==5
  30. ////将数组元素首地址的下一个地址,也就是第二个元素的地址,传递给给函数,数组中有'\0',所以有5个元素!
  31. return 0;
  32. }


<think>好的,用户现在问的是C语言数组的有效数据数组长度的区别。之前他们问过关于if语句的问题,现在转向数组,可能是在学习基础语法。需要先理解这两个概念的定义,然后找出它们的区别。 首先,数组长度是指数组在定义时分配的内存空间能容纳的元素个数,是固定的,比如int arr[10]的长度是10。而有效数据是指实际存储的有意义的数据数量,比如数组长度10,但可能只用了前5个元素,后面的是未初始化的垃圾值。 用户可能混淆这两个概念,特别是刚学的时候,容易以为数组长度就是当前存储的数据量。需要明确区分,数组长度是固定的大小,有效数据是实际使用的部分,有效数据不能超过数组长度。 另外,用户可能在实际编程中遇到问题,比如遍历数组时如何处理有效数据,或者如何动态管理有效数据。可能需要进一步解释如何用变量跟踪有效数据,比如使用一个计数器,或者用特殊标记(如-1或NULL)表示结束。 还要注意C语言数组长度是编译时确定的,不能动态改变,而有效数据可以在运行时变化,但必须手动管理,避免越界。可能需要提醒用户注意数组越界的风险,以及如何处理有效数据超出数组长度的情况。 总结回答的结构:先分别定义数组长度有效数据,再对比它们的区别,最后举例说明,并给出使用建议。确保语言简洁明了,适合初学者理解。</think>在 C 语言中,**数组的有效数据****数组长度**是两个完全不同的概念,它们的区别如下: --- ### **1. 数组长度(Array Length)** - **定义**:数组在声明时通过方括号 `[]` 定义的固定容量,表示该数组最多能存储多少元素。 - **特点**: - 在编译时确定,无法动态修改。 - 通过 `sizeof(arr)/sizeof(arr[0])` 可以计算数组的总长度(仅限静态数组)。 - 即使未全部使用,内存空间仍然被分配。 - **示例**: ```c int arr[10]; // 数组长度固定为 10 ``` --- ### **2. 有效数据(Valid Data)** - **定义**:数组中实际存储的有意义的数据数量。例如,一个长度为 10 的数组可能只填充了前 5 个元素。 - **特点**: - 由程序员手动管理,需通过变量(如 `count`)记录当前有效数据的数量。 - 有效数据量 ≤ 数组长度(否则会越界)。 - 未使用的元素可能包含随机值(垃圾值),需初始化后才能安全使用。 - **示例**: ```c int arr[10] = {1, 2, 3}; // 数组长度为 10,有效数据为 3 int count = 3; // 需要额外变量记录有效数据量 ``` --- ### **核心区别** | **对比项** | **数组长度** | **有效数据** | |--------------|-------------------------------|-------------------------------| | **定义** | 数组的容量(最大元素数量) | 实际存储有意义的数据数量 | | **内存分配** | 固定,声明时确定 | 动态,由程序员控制 | | **管理方式** | 编译器自动分配 | 需手动记录(如变量 `count`) | | **越界风险** | 操作下标超过长度会越界 | 操作下标超过有效数据可能逻辑错误 | --- ### **示例代码** ```c #include <stdio.h> int main() { int arr[5] = {10, 20, 30}; // 数组长度为 5,有效数据为 3 int count = 3; // 记录有效数据量 // 输出数组长度 printf("数组长度: %zu\n", sizeof(arr)/sizeof(arr[0])); // 输出 5 // 输出有效数据 for (int i = 0; i < count; i++) { printf("%d ", arr[i]); // 输出 10 20 30 } return 0; } ``` --- ### **注意事项** 1. **越界问题**:若有效数据超过数组长度(如 `count > 数组长度`),会导致未定义行为(程序崩溃或数据污染)。 2. **初始化**:静态数组未初始化的元素可能是随机值,需显式初始化或动态填充。 3. **动态管理**:有效数据通常需要结合循环、计数器等逻辑手动管理(例如动态输入数据时)。 如果需要动态调整存储空间,可以考虑使用指针动态内存分配(如 `malloc`),但需注意内存泄漏越界问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值