当前位置: 首页 > news >正文

指针和数组解析

数组名通常指的是首元素的地址,但有两个例外:
1.sizeof(数组名),sizeof里面单独存放数组名,这里的数组名代表整个数组。
2.&数组名,&后面单独接数组名,这里的数组名代表整个数组。

任意表达式都有两个属性,值属性和类型属性,sizeof只会计算表达式的类型属性,并不会对表达式的值属性进行修改

1.sizeof和整型数组

int a[] = { 1,2,3,4 };
printf("%d\n", sizeof(a));//数组名单独放在sizeof内部,代表整个数组,类型是int [4],大小16个字节
printf("%d\n", sizeof(a + 0));//这里的数组名并不是单独放在sizeof内部,代表首元素的地址,首元素的地址加0依旧是首元素的地址,是地址也就是指针大小就是4/8个字节
printf("%d\n", sizeof(*a));//数组名不单独放在sizeof内部,代表首元素的地址,解引用得到第一个元素,类型是int,大小是4个字节
printf("%d\n", sizeof(a + 1));//这里的数组名代表首元素的地址,加1代表第二个元素的地址,大小是4/8个字节
printf("%d\n", sizeof(a[1]));//a[1]是第二个元素,类型是int,大小4个字节
printf("%d\n", sizeof(&a));//数组名单独放在&后面代表整个数组,&a的类型是int(*)[4],是指针,大小是4/8个字节
printf("%d\n", sizeof(*&a));//数组名单独放在&后面,代表整个数组,*&a的类型是*(int(*)[4])==int [4],大小是16个字节
printf("%d\n", sizeof(&a + 1));//&a+1跳过了整个数组,类型是int(*)[4],大小是4/8个字节
printf("%d\n", sizeof(&a[0]));//&a[0]是首元素的地址,大小是4/8个字节
printf("%d\n", sizeof(&a[0] + 1));//&a[0]+1是第二个元素的地址,大小是4/8个字节

2.sizeof和字符数组

char arr[] = { 'a','b','c','d','e','f' };
printf("%d\n", sizeof(arr));//arr单独放在sizeof内部,代表整个数组,类型是char [6],大小是6个字节
printf("%d\n", sizeof(arr + 0));//这里的arr代表首元素的地址,加0依旧是首元素的地址,大小是4/8个字节
printf("%d\n", sizeof(*arr));//*arr代表首元素,类型是char,大小是1个字节
printf("%d\n", sizeof(arr[1]));//arr[1]代表第二个元素,类型是char,大小是1个字节
printf("%d\n", sizeof(&arr));//&arr取出的是整个数组的地址,类型是char(*)[6],大小是4/8个字节
printf("%d\n", sizeof(&arr + 1));//&arr+1是取出整个数组的地址后跳过整个数组,类型依旧是char(*)[6],大小是4/8个字节
printf("%d\n", sizeof(&arr[0] + 1));//&arr[0]是首元素的地址,加1是第二个元素的地址,类型是char*,大小是4/8个字节

3.字符数组和strlen

char arr[] = { 'a','b','c','d','e','f' };
printf("%d\n", strlen(arr));//strlen必须找到'\0'才停止,这里的arr是首元素的地址,但数组内没有存放'\0',结果是随机值
printf("%d\n", strlen(arr + 0));//这里的arr+0依旧是首元素地址,结果是随机值
printf("%d\n", strlen(*arr));//err
//*arr是首元素'a',ASCII码值为97
//strlen的参数部分需要传入一个地址,当我们传递的是'a'时,就是将97作为地址传递给strlen
//那么strlen就会从97这个地址开始统计字符串长度,这就非法访问了
printf("%d\n", strlen(arr[1]));//err
//arr[1]是第二个元素'b',ASCII码值是98,同样也造成了非法访问
printf("%d\n", strlen(&arr));//&arr取出的是整个数组的地址,但值是和数组首元素地址是一样的,所以strlen依旧是从数组的第一个元素开始查找,结果是随机值
printf("%d\n", strlen(&arr + 1));//&arr+1是取出整个数组的地址后加整个数组的大小,strlen将从数组的最后一个元素的下一个位置开始查找,结果依旧是随机值
printf("%d\n", strlen(&arr[0] + 1));//&arr[0]+1是第二个元素的地址,结果是随机值

4.字符串数组和sizeof

char arr[] = "abcdef";
//arr里面存放的是{'a','b','c','d','e','f','\0'},有7个元素
printf("%d\n", sizeof(arr));//arr单独放在sizeof内部,代表整个数组,类型是char [7],大小是7个字节
printf("%d\n", sizeof(arr + 0));//arr+0代表首元素的地址,类型是char*,大小是4/8个字节
printf("%d\n", sizeof(*arr));//*arr是首元素'a',类型是char,大小是1个字节
printf("%d\n", sizeof(arr[1]));//arr[1]是第二个元素'b',类型是char,大小是1个字节
printf("%d\n", sizeof(&arr));//&arr取出是是整个数组的地址,类型是char(*)[7],大小是4/8个字节
printf("%d\n", sizeof(&arr + 1));//&arr+1指向数组最后一个元素后面的地址,类型是char(*)[7],大小是4/8个字节
printf("%d\n", sizeof(&arr[0] + 1));//第二个元素的地址,类型是char*,大小是4/8个字节

5.字符串数组和strlen

char arr[] = "abcdef";
//arr里面存放的是{'a','b','c','d','e','f','\0'},有7个元素
printf("%d\n", strlen(arr));//arr在strlen内部代表首元素的地址,strlen能找到'\0',结果是6
printf("%d\n", strlen(arr + 0));//arr+0依旧是首元素的地址,结果是6
//printf("%d\n", strlen(*arr));//err
//*arr是'a',传入strlen会导致非法访问
//printf("%d\n", strlen(arr[1]));//err
//arr[1]是'b',传入strlen依旧会导致非法访问
printf("%d\n", strlen(&arr));//&arr的值和首元素地址的值相同,传入strlen就是strlen从首元素开始找,结果是6
printf("%d\n", strlen(&arr + 1));//&arr+1指向的位置已经跳到'\0'的后面一位,结果是随机值
printf("%d\n", strlen(&arr[0] + 1));//&arr[0]+1是第二个元素的地址,结果是5

6.常量字符串和sizeof

char* p = "abcdef";
printf("%d\n", sizeof(p));//p是一个指针变量,大小是4/8个字节
printf("%d\n", sizeof(p + 1));//p+1是一个指向'b'位置的指针变量,大小是4/8个字节
printf("%d\n", sizeof(*p));//*p就是'a',类型是char,大小是1个字节
printf("%d\n", sizeof(p[0]));//p[0]也是'a',类型char,大小是1个字节
printf("%d\n", sizeof(&p));//&p是p的地址,类型是char**,大小是4/8个字节
printf("%d\n", sizeof(&p + 1));//&p+1依旧是地址,大小是4/8个字节
printf("%d\n", sizeof(&p[0] + 1));//&p[0]+1是'b'的地址,大小是4/8个字节

7.常量字符串和strlen

char* p = "abcdef";
printf("%d\n", strlen(p));//strlen从字符串首元素地址开始找,结果是6
printf("%d\n", strlen(p + 1));//从第二个元素的地址开始找,结果是5
//printf("%d\n", strlen(*p));//*p依旧是'a',会非法访问,err
//printf("%d\n", strlen(p[0]));//p[0]是'a',传入strlen会非法访问,err
printf("%d\n", strlen(&p));//从&p的位置开始找'\0',结果是随机值
printf("%d\n", strlen(&p + 1));//从&p+1的位置开始找'\0',结果是随机值
printf("%d\n", strlen(&p[0] + 1));//从第二个元素的地址开始找'\0',结果是5

8.二维数组和sizeof

int a[3][4] = { 0 };
printf("%d\n", sizeof(a));//a代表整个数组,类型是int [3][4],大小是3*4*4=48个字节
printf("%d\n", sizeof(a[0][0]));//第一行第一个元素,类型是int,大小是4个字节
printf("%d\n", sizeof(a[0]));//a[0]是第一行这个一维数组的数组名,单独放在sizeof内部,计算的是第一行整个一维数组的大小,类型是int [4],大小是16个字节
printf("%d\n", sizeof(a[0] + 1));//a[0]是第一行数组的数组名,没有单独放在sizeof内部,代表的也就是第一行首元素a[0][0]的地址,加1就是第一行第二个元素的地址,类型是int*,大小是4/8个字节
printf("%d\n", sizeof(*(a[0] + 1)));//第二行的首个元素,类型是int,大小是4个字节
printf("%d\n", sizeof(a + 1));//a是整个二维数组首元素的地址,类型是int(*)[4],加1是第二行的地址,类型依旧是int(*)[4],大小是4/8个字节
printf("%d\n", sizeof(*(a + 1)));//a+1的类型是int(*)[4],解引用后类型就成了int [4],大小是16个字节
printf("%d\n", sizeof(&a[0] + 1));//&a[0]是第一行的地址,&a[0]+1就是第二行的地址,类型是int(*)[4],大小是4/8个字节
printf("%d\n", sizeof(*(&a[0] + 1)));//对第二行的地址进行解引用,类型是int [4],大小是16个字节
printf("%d\n", sizeof(*a));//a是首元素的地址,也就是第一行的地址,类型是int(*)[4],解引用后的类型就是int [4],大小是16个字节
printf("%d\n", sizeof(a[3]));//a[3]的类型和a[0]的类型相同,是int [4],大小是16个字节

http://www.dtcms.com/a/441804.html

相关文章:

  • 【AI4S】3DSMILES-GPT:基于词元化语言模型的3D分子生成
  • Transformer推理优化全景:从模型架构到硬件底层的深度解析
  • MySQL 索引全解析:结构、优化与索引下推实战指南​
  • clear configuration interface概念及题目
  • 设计模式(C++)详解——策略模式(1)
  • 基于html5设计的网站建设做一些购物网站
  • Vivado综合通关指南:从IP打包失败到工具崩溃的四重考验
  • 语义分割概述
  • 数据结构之排序算法
  • 绍兴网站建设优化手机企业网站建设开发
  • 偏导数解释
  • Linux内核与设备管理:USB存储驱动usb_storage/uas的安全卸载与复原
  • fallocate: fallocate failed: Text file busy
  • visio实现扇形图绘制的方式方法-以三等分扇形为例
  • 以太坊私有链搭建与智能合约部署指南
  • 网站开发 教学大纲网页设计图片与图片的位置
  • python+flask_socketio+pyautogui实现简易远程桌面功能
  • flask_socketio+pyautogui实现的具有加密传输功能的极简远程桌面
  • 深入了解linux网络—— TCP网络通信(上)
  • Android Jetpack 核心组件实战:ViewModel + LiveData + DataBinding 详解
  • 商务厅网站建设意见怎么做网站注册推广
  • Fragment 崩溃恢复后出现重叠问题的复现方式
  • 设计模式(C++)详解——策略模式(2)
  • 使客户能够大规模交付生产就绪的人工智能代理
  • Layui 前端和 PHP 后端的大视频分片上传方案
  • 无状态HTTP的“记忆”方案:Spring Boot中CookieSession全栈实战
  • Java 内存模型(JMM)面试清单(含超通俗生活案例与深度理解)
  • 2015网站建设专业建网站设计公司
  • vue+springboot项目部署到服务器
  • QT肝8天17--优化用户管理