【C语言进阶】指针进阶(三)

指针进阶(三)

    • 9.指针和数组笔试题解析
    • 10.指针笔试题

9.指针和数组笔试题解析

数组名的理解
数组名是数组首元素的地址
但是有2个例外:

  1. sizeof(数组名),这里的数组名表示整个数组,sizeof(数组名)计算的是整个数组的大小,单位是字节
  2. &数组名,这里的数组名表示整个数组,&数组名取出的是数组的地址
#include<stdio.h>
int main()
{//一维数组int a[] = { 1,2,3,4 };//4个元素,每个元素使int类型(4个字节)printf("%d\n", sizeof(a));//16,数组名a单独放在sizeof内部,数组名表示整个数组,计算的是整个数组的大小单位是字节,是16字节printf("%d\n", sizeof(a + 0));//a并非单独放在sizeof内部,也没有&,所以数组名a是数组首元素的地址,a+0还是首元素的地址//是地址大小就是4/8 Byteprintf("%d\n", sizeof(*a));//a并非单独放在sizeof内部,也没有&,所以数组名a是数组首元素的地址//*a 就是 首元素,大小就是4Byte  //*a == *(a+0) == a[0]printf("%d\n", sizeof(a + 1));//a并非单独放在sizeof内部,也没有&,所以数组名a是数组首元素的地址,a+1就是第二个元素的地址//a+1 == &a[1]  是第2个元素的地址,是地址就是4/8个字节printf("%d\n", sizeof(a[1]));//a[1]就是数组的第二个元素,这里计算的就是第二个元素的大小,单位是字节 - 4printf("%d\n", sizeof(&a));//&a - 是取出数组的地址,但是数组的地址也是地址,是地址就是4/8个Byte//数组的地址 和 数组首元素的地址 的本质区别是类型的区别,并非大小的区别//a  -- int*             int * p = a;//&a -- int (*)[4]       int (*p)[4] = &a;printf("%d\n", sizeof(*&a));//16   对数组指针解引用访问一个数组的大小,单位是字节//sizeof(*&a) --- sizeof(a) //16printf("%d\n", sizeof(&a + 1));//&a数组的地址,&a+1还是地址,是地址就是4/8个字节printf("%d\n", sizeof(&a[0]));//&a[0]是首元素的地址, 计算的是地址的大小 4/8 个字节printf("%d\n", sizeof(&a[0] + 1));//&a[0]是首元素的地址,&a[0]+1就是第二个元素的地址,大小4/8个字节//&a[1]//&a[0]+1//a+1return 0;
}

运行结果:
在这里插入图片描述

#include<stdio.h>
#include <string.h>
int main()
{//字符数组char arr[] = { 'a','b','c','d','e','f' };//6printf("%d\n", sizeof(arr));//6 数组名arr单独放在sizeof内部,计算的是整个数组的大小,单位是字节printf("%d\n", sizeof(arr + 0));//arr是首元素的地址==&arr[0],是地址就是4/8个字节//char* //指针变量的大小和类型无关,不管什么类型的指针变量,大小都是4/8个字节//指针变量是用来存放地址的,地址存放需要多大空间,指针变量的大小就是几个字节//32位环境下,地址是32个二进制位,需要4个字节,所以指针变量的大小就是4个字节//64位环境下,地址是64个二进制位,需要8个字节,所以指针变量的大小就是8个字节//门缝里看指针,把指针给看扁了//printf("%d\n", sizeof(*arr));//arr是首元素的地址,*arr就是首元素,大小就是1Byteprintf("%d\n", sizeof(arr[1]));//1printf("%d\n", sizeof(&arr));//&arr是数组的地址,sizeof(&arr)就是4/8个字节printf("%d\n", sizeof(&arr + 1));//&arr+1 是跳过数组后的地址,是地址就是4/8个字节printf("%d\n", sizeof(&arr[0] + 1));//第二个元素的地址,是地址就是4/8Bytereturn 0;
}

运行结果:
在这里插入图片描述

//strlen 求字符串长度
//统计的是在字符串中\0之前出现的字符的个数
//
int main()
{//字符数组char arr[] = { 'a','b','c','d','e','f' };//6printf("%d\n", strlen(arr));//随机值,arr是首元素的地址printf("%d\n", strlen(arr + 0));//随机值,arr是首元素的地址, arr+0还是首元素的地址//printf("%d\n", strlen(*arr));//err,arr是首元素的地址, *arr就是首元素 - 'a' - 97//站在strlen的角度,认为传参进去的'a'-97就是地址,97作为地址,直接进行访问,就是非法访问//printf("%d\n", strlen(arr[1]));//err, 'b' - 98printf("%d\n", strlen(&arr));//随机值//&arr -- char (*)[6]//const char*printf("%d\n", strlen(&arr + 1));//随机值printf("%d\n", strlen(&arr[0] + 1));//随机值return 0;
}

运行结果:
在这里插入图片描述

int main()
{char arr[] = "abcdef";//a b c d e f \0printf("%d\n", sizeof(arr));//7数组名arr单独放在sizeof内部,计算的是整个数组的大小,单位是字节printf("%d\n", sizeof(arr + 0));//arr是首元素的地址==&arr[0],是地址就是4/8个字节printf("%d\n", sizeof(*arr));//arr是首元素的地址,*arr就是首元素,大小就是1Byteprintf("%d\n", sizeof(arr[1]));//1printf("%d\n", sizeof(&arr));//4/8 &arr是数组的地址,sizeof(&arr)就是4/8个字节printf("%d\n", sizeof(&arr + 1));//4/8 &arr+1 是跳过数组后的地址,是地址就是4/8个字节printf("%d\n", sizeof(&arr[0] + 1));//4/8 第二个元素的地址,是地址就是4/8Bytereturn 0;
}

运行结果:
在这里插入图片描述

#include<stdio.h>
int main()
{char arr[] = "abcdef";printf("%d\n", strlen(arr));//6 arr是首元素的地址printf("%d\n", strlen(arr + 0));//6 arr是首元素的地址, arr+0还是首元素的地址//printf("%d\n", strlen(*arr));//err arr是首元素的地址, *arr就是首元素 - 'a' - 97//printf("%d\n", strlen(arr[1]));//err 'b' - 98printf("%d\n", strlen(&arr));//6 printf("%d\n", strlen(&arr + 1));//随机值printf("%d\n", strlen(&arr[0] + 1));//5
}

运行结果:
在这里插入图片描述

int main()
{char* p = "abcdef";printf("%d\n", sizeof(p));//4/8 计算的是指针变量的大小printf("%d\n", sizeof(p + 1));//p+1还是地址,大小是4/8个字节printf("%d\n", sizeof(*p));//1个字节, *p == 'a'printf("%d\n", sizeof(p[0]));//1个字节, p[0]--> *(p+0) --> *p == 'a';printf("%d\n", sizeof(&p));//4/8个字节,&p 是地址printf("%d\n", sizeof(&p + 1));//&p是地址,&p+1还是地址,是地址就是4/8个字节printf("%d\n", sizeof(&p[0] + 1));//4/8return 0;
}

运行结果:
在这里插入图片描述

int main()
{char* p = "abcdef";printf("%d\n", strlen(p));//6printf("%d\n", strlen(p + 1));//5//printf("%d\n", strlen(*p));//err//printf("%d\n", strlen(p[0]));//errprintf("%d\n", strlen(&p));//随机printf("%d\n", strlen(&p + 1));//随机printf("%d\n", strlen(&p[0] + 1));//5return 0;
}

在这里插入图片描述

运行结果:
在这里插入图片描述

int main()
{int a[3][4] = { 0 };printf("%zd\n", sizeof(a));//48-数组名a单独放在了sizeof内存,表示整个数组,sizeof(a)计算的是数组的大小,单位是字节printf("%zd\n", sizeof(a[0][0]));//4-a[0][0]是数组的第一行第一个元素,这里计算的就是一个元素的大小,单位是字节printf("%zd\n", sizeof(a[0]));//16 - a[0]是第一行这个一维数组的数组名,数组名单独放在了sizeof内部//a[0]就表示整个第一行这个一维数组,sizeof(a[0])计算的整个第一行这个一维数组的大小printf("%zd\n", sizeof(a[0] + 1));//4/8 - a[0]并非单独放在sizeof内部,也没有&,所以a[0]表示第一行这个一维数组首元素的地址//也就是第一行第一个元素的地址//a[0] <---> &a[0][0]//a[0]+1 ---> &a[0][1]printf("%zd\n", sizeof(*(a[0] + 1)));//4 - a[0] + 1是第一行第二个元素的地址,*(a[0] + 1))就是第一行第二个元素//printf("%zd\n", sizeof(a + 1));//4/8//a 作为二维数组的数组名,并没有单独放在sizeof内部,也没有&,a就是数组首元素的地址,也就是第一行的地址, a 的类型是 int(*)[4]//a+1 就是第二行的地址,类型是:int(*)[4]//printf("%zd\n", sizeof(*(a + 1)));//16 a+1是第二行的地址,*(a+1)就是第二行,计算的就是第二行的大小//另外一个角度理解:*(a+1) -- a[1]//sizeof(a[1]) - a[1]这个第二行的数组名,单独放在了sizeof内部,计算的是第二行的大小printf("%zd\n", sizeof(&a[0] + 1));//4/8//a[0]是第一行的数组名,&a[0]取出的是数组的地址,取出的是第一行这个一维数组的地址,类型就是int(*)[4]//&a[0]+1 就是第二行的地址,类型就是int(*)[4]printf("%zd\n", sizeof(*(&a[0] + 1)));//*(&a[0] + 1)得到的就是第二行,计算的就是第二行的大小printf("%zd\n", sizeof(*a));//16//a表示数组首元素的地址,也就是第一行的地址//*a 就是第一行,也就相当于是第一行的数组名//*a--> *(a+0) -- a[0]//printf("%zd\n", sizeof(a[3]));//16-不会越界,//a[3] --    arr[0]//int [4]    int [4]return 0;
}

运行结果:
在这里插入图片描述

10.指针笔试题

int main()
{int a[5] = { 1, 2, 3, 4, 5 };int* ptr = (int*)(&a + 1);printf("%d, %d", *(a + 1), *(ptr - 1));return 0;
}

运行结果:
在这里插入图片描述

//由于还没学习结构体,这里告知结构体的大小是20个字节
//X86 环境下演示
struct Test
{int Num;char* pcName;short sDate;char cha[2];short sBa[4];
} * p;
//假设p 的值为0x100000。 如下表表达式的值分别为多少?
//已知,结构体Test类型的变量大小是20个字节
//0x开头的数字是16进制的数字
int main()
{p = (struct Test*)0x100000;printf("%p\n", p + 0x1);printf("%p\n", (unsigned long)p + 0x1);printf("%p\n", (unsigned int*)p + 0x1);return 0;
}

运行结果:
在这里插入图片描述

int main()
{int a[4] = { 1, 2, 3, 4 };int* ptr1 = (int*)(&a + 1);int* ptr2 = (int*)((int)a + 1);printf("%x,%x", ptr1[-1], *ptr2);return 0;
}

运行结果:
在这里插入图片描述

#include <stdio.h>
int main()
{int a[3][2] = { (0, 1), (2, 3), (4, 5) };int* p;p = a[0];printf("%d", p[0]);//?return 0;
}

运行结果:
在这里插入图片描述

int main()
{int a[5][5];int(*p)[4];//数组指针p = a;//类型合适吗?   //a - int(*)[5]//p - int(*)[4]printf("%p, %d\n", &p[4][2] - &a[4][2], &p[4][2] - &a[4][2]);////%p是打印地址,认为内存中存储的补码就是地址//return 0;
}

运行结果:
在这里插入图片描述

int main()
{int aa[2][5] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };int* ptr1 = (int*)(&aa + 1);int* ptr2 = (int*)(*(aa + 1));printf("%d,%d", *(ptr1 - 1), *(ptr2 - 1));return 0;
}

运行结果:
在这里插入图片描述

#include <stdio.h>
//阿里的笔试题
int main()
{char* a[] = { "work","at","alibaba" };char** pa = a;pa++;printf("%s\n", *pa);return 0;
}

在这里插入图片描述

int main()
{char* c[] = { "ENTER","NEW","POINT","FIRST" };char** cp[] = { c + 3,c + 2,c + 1,c };char*** cpp = cp;printf("%s\n", **++cpp);printf("%s\n", *-- * ++cpp + 3);printf("%s\n", *cpp[-2] + 3);printf("%s\n", cpp[-1][-1] + 1);return 0;
}

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/144596.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Topaz Photo AI forMac/win:革命性的图片降噪软件

Topaz Photo AI是一款革命性的图片降噪软件&#xff0c;它利用人工智能技术对图片进行降噪处理&#xff0c;让你的照片焕然一新。与传统的降噪软件不同&#xff0c;Topaz Photo AI不仅降噪效果更出色&#xff0c;而且操作简单&#xff0c;让你可以轻松地提升图片质量。 Topaz …

Java —— 方法的使用

目录 1. 方法的概念及使用 1.1 什么是方法(method) 1.2 方法定义 方法语法格式 1.3 方法调用的执行过程 方法调用过程 1.4 实参和形参的关系 2. 方法重载 2.1 为什么需要方法重载 2.2 方法重载概念 3. 递归 3.1 递归的概念 3.2 递归执行过程分析 汉诺塔问题 编程中, 某段功能的…

vant组件是使用?

首先 在vue项目中使用的时候 要先下载组件 使用npm安装 # Vue 3 项目&#xff0c;安装最新版 Vant npm i vant# Vue 2 项目&#xff0c;安装 Vant 2 npm i vantlatest-v2 使用yarn安装或pnpm # 通过 yarn 安装 yarn add vant# 通过 pnpm 安装 pnpm add vant 在框架中引入即…

codeforces (C++ Morning)

题目&#xff1a; 翻译&#xff1a; 思路&#xff1a; 1、要将四位数显示&#xff0c;每次操作可以选择移动光标&#xff08;移动到相邻的位置&#xff09;或者显示数字&#xff0c;计算最少需要多少次操作。 2、用flag表示当前光标位置&#xff0c;sum为记录操作次数&#…

X32位汇编和X64位区别无参函数分析(一)

前言 一、X32汇编函数无参无返回分析 二、X64汇编函数无参无返回分析 总结 前言 提示&#xff1a;以下是个人学习总结&#xff1a;如有错误请大神指出来&#xff0c;只供学习参考&#xff0c;本内容使用使用VS2017开发工具&#xff1a;语言是C&#xff0c;需要一些常见的汇编指…

mac 升级node到指定版本

node版本14.15.1升级到最新稳定版18.18.2 mac系统 先查看一下自己的node版本 node -v开始升级 第一步 清除node的缓存 sudo npm cache clean -f第二步 安装n模块【管理模块 n是管理 nodejs版本】 sudo npm install -g n第三步升级node sudo n stable // 把当前系统的 Node…

【C语言练习题】添加逗号

✨博客主页&#xff1a;小钱编程成长记 &#x1f388;博客专栏&#xff1a;C语言练习题 添加逗号 1. 题目2.讲解3.代码总结 1. 题目 牛客网在线OJ 2.讲解 因为数字位数可能不全是3的倍数&#xff0c;比如&#xff1a;23&#xff0c;445&#xff0c;555。所以我们从后向前进行&…

uni-app:对数组对象进行以具体某一项的分类处理

一、原始数据 这里定义为五个数组&#xff0c;种类product有aaa,bbb两种 原始数据在data中进行定义 res: {"success": true,"devices": [{no: 0,product: aaa,alias: "设备1",assign: [["a1", "a2", "a3"],[&q…

24-数据结构-内部排序-基数排序

基数排序 基数排序&#xff0c;给关键字分成d位&#xff08;组&#xff09;&#xff0c;&#xff0c;对每一位的情况&#xff0c;可能会出现的值位r&#xff08;基数&#xff09;个&#xff0c;然后分成r个队列&#xff0c;对每个对林进行分配耗时O(n)&#xff0c;最后按照改位…

行业追踪,2023-10-20

自动复盘 2023-10-20 凡所有相&#xff0c;皆是虚妄。若见诸相非相&#xff0c;即见如来。 k 线图是最好的老师&#xff0c;每天持续发布板块的rps排名&#xff0c;追踪板块&#xff0c;板块来开仓&#xff0c;板块去清仓&#xff0c;丢弃自以为是的想法&#xff0c;板块去留让…

基于Java的旅游网站系统设计与实现(源码+lw+部署文档+讲解等)

文章目录 前言具体实现截图论文参考详细视频演示为什么选择我自己的网站自己的小程序&#xff08;小蔡coding&#xff09; 代码参考数据库参考源码获取 前言 &#x1f497;博主介绍&#xff1a;✌全网粉丝10W,CSDN特邀作者、博客专家、CSDN新星计划导师、全栈领域优质创作者&am…

在没有康托尔对角化方法的情况下证明实数的不可数性

乔治康托尔 |图片来源&#xff1a; 维基百科 一、说明 对于那些对数学感兴趣的人来说&#xff0c;无穷大实际上可以有不同的大小&#xff0c;这可能是一个众所周知的事实。事实上&#xff0c;最著名的例子是所有实数的集合比所有自然数的集合“大”。你可能知道&#xff0c;这实…