【从浅入深,全面掌握数组的操作与优化技巧】

简介: 【从浅入深,全面掌握数组的操作与优化技巧】
#include<stdio.h>
#define N 10
int main()
{
    int a[N] = { 0 }; //定义并初始化数组
    return 0;
}

概念:数组是具有相同数据类型的集合。


数组的内存布局


#include<stdio.h>
int main()
{
  int a = 10;
  int b = 20;
  int c = 30;
  printf("%p\n", &a);
  printf("%p\n", &b);
  printf("%p\n", &c);
  return 0;
}


我们来看一下运行的结果



  • 我们发现,先定义的变量,地址是比较大的,后续依次减小。
  • 这是为什么呢?
  • a,b,c都在main函数中定义,也就是在栈上开辟的临时变量。而a先定义意味着,a先开辟空间,那么a就先入栈,所以a 的地址最高,其他类似。


#include<stdio.h>
#define N 10
int main()
{
  int a[N] = { 0 };
  for (int i = 0; i < N; i++) {
    printf("&a[%d]: %p\n", i, &a[i]);
  }
  return 0;
}



  • 我们发现,数组的地址排布是:&a[0] < &a[1] < &a[2] < ... < &a[9]。
  • 该数组在main函数中定义,那么也同样在栈上开辟空间
  • 数组有多个元素,那么肯定是a[0]先被开辟空间啊,那么肯定&a[0]地址最大啊,可是事实上并非如此!
  • 数组是整体申请空间的,然后将地址最低的空间,作为a[0]元素,依次类推!所以我们不能把数组认为是一个个独立的元素,它们是整体被开辟,整体被释放。


理解&a[0]和&a的区别


  • &a[0]取的是首元素的地址。
  • &a取的是整个数组的地址。


#include<stdio.h>
int main()
{
  char* c = NULL;
  short* s = NULL;
  int* i = NULL;
  double* d = NULL;
  printf("%d\n", c);
  printf("%d\n\n", c + 1);
  printf("%d\n", s);
  printf("%d\n\n", s + 1);
  printf("%d\n", i);
  printf("%d\n\n", i + 1);
  printf("%d\n", d);
  printf("%d\n\n", d + 1);
  return 0;
}



结论:对指针+1,本质加上其所指向类型的大小。


如果发生类型转化呢?



结论:


  • 如果发生强制类型转换,对指针+1,本质加上其所指向强制类型转换的大小。
  • 二级指针以以上所有的指针+1,在32位平台上,都是跳过4个字节。
#include<stdio.h>
int main()
{
  char arr[10] = { 0 };
  printf("%p\n", &arr[0]); //首元素的地址
  printf("%p\n", &arr[0] + 1); //第二个元素的地址
  printf("%p\n", &arr); //数组的地址
  printf("%p\n", &arr + 1); //下一个数组的地址
  return 0;
}


数组名使用的时候,只有两种情况代表整个数组

  1. &arr:数组的地址
  2. sizeof(arr):单独使用数组名


&arr[0] 和 &arr虽然地址数字一样大,但是类型意义完全不同。


为什么地址数字是一样大的呢???


       因为首元素的地址和数组的地址,在地址对应的字节是重叠的,所以地址的数据值相等。

       地址对应的字节都是变量开辟的空间中众多字节当中,地址最小的那个。


数组名a做为左值和右值的区别




数组只能整体被初始化,不能整体赋值,如果想要赋值,只能逐个元素进行赋值。

例如:arr[0]  =  1; arr[1] = 2;

相关文章
|
22天前
|
前端开发 JavaScript 开发者
揭秘前端高手的秘密武器:深度解析递归组件与动态组件的奥妙,让你代码效率翻倍!
【10月更文挑战第23天】在Web开发中,组件化已成为主流。本文深入探讨了递归组件与动态组件的概念、应用及实现方式。递归组件通过在组件内部调用自身,适用于处理层级结构数据,如菜单和树形控件。动态组件则根据数据变化动态切换组件显示,适用于不同业务逻辑下的组件展示。通过示例,展示了这两种组件的实现方法及其在实际开发中的应用价值。
28 1
|
29天前
|
缓存 关系型数据库 MySQL
一文彻底弄懂MySQL优化之深度分页
【10月更文挑战第24天】本文深入探讨了 MySQL 深度分页的原理、常见问题及优化策略。首先解释了深度分页的概念及其带来的性能和资源问题。接着介绍了基于偏移量(OFFSET)和限制(LIMIT)以及基于游标的分页方法,并分析了它们的优缺点。最后,提出了多种优化策略,包括合理创建索引、优化查询语句和使用数据缓存,帮助提升分页查询的性能和系统稳定性。
|
6月前
|
算法
二分查找算法的细节刨析 --适合有基础的朋友阅读
二分查找算法的细节刨析 --适合有基础的朋友阅读
|
6月前
|
搜索推荐 测试技术
【探索排序算法的魅力:优化、性能与实用技巧】(上)
【探索排序算法的魅力:优化、性能与实用技巧】
|
6月前
|
存储 算法 安全
【Java编程进阶之路 02】深入探索:红黑树如何重塑哈希表的性能边界
JDK 1.8之后,HashMap引入红黑树来优化性能,当链表长度超过阈值(默认为8)时,链表会转换为红黑树,从而提高高冲突时的查询效率。同时,HashMap也采用了扰动函数来增加哈希值的随机性,使键值对更均匀分布,提升性能。
78 0
|
6月前
|
存储 人工智能 搜索推荐
【探索排序算法的魅力:优化、性能与实用技巧】(下)
【探索排序算法的魅力:优化、性能与实用技巧】
|
6月前
|
搜索推荐
【探索排序算法的魅力:优化、性能与实用技巧】(中)
【探索排序算法的魅力:优化、性能与实用技巧】
|
缓存 运维 算法
三十一、 套路篇:磁盘 I/O 性能优化的几个思路
三十一、 套路篇:磁盘 I/O 性能优化的几个思路
399 0
三十一、 套路篇:磁盘 I/O 性能优化的几个思路
|
设计模式 SQL 数据库
《数据库系统原理》第一遍阅读
又是一年自考,总是听师哥师姐说,自考第一遍不过,第二遍再学习的时候感觉会不一样。很开心我有了一次重学《数据库系统原理》的机会,果然就像师哥师姐所说的,我收获到了知识之外的东西。第二遍学习,我体会到的不仅仅是自己的那份从容和淡定,更感受到了大脑自动编织知识网的神奇。
|
算法 搜索推荐
《十大排序算法》让你的思维流动起来。今天的主角又是排序思想你了解多少。每种算法的内容在代码中体现出来。
《十大排序算法》让你的思维流动起来。今天的主角又是排序思想你了解多少。每种算法的内容在代码中体现出来。
196 0
《十大排序算法》让你的思维流动起来。今天的主角又是排序思想你了解多少。每种算法的内容在代码中体现出来。