IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> 【C语言】指针笔试题详解 -> 正文阅读

[C++知识库]【C语言】指针笔试题详解

前言

??当前演示环境均为 x86环境(32位平台)

笔试题1🌕

下面代码的运行结果是什么:

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

在这里插入图片描述
解析:

#include <stdio.h>
int main()
{
    int a[5] = { 1, 2, 3, 4, 5 };
    int* ptr = (int*)(&a + 1);
    //&a 对数组进行取地址,&a就是int(*)[5] 数组指针类型;int (*p) = &a;-->int(*)[5]
    //&a+1 是数组+1,跳过一个数组指向数组的后面 
    //&a+1也是int(*)[5]数组指针类型,将&a+1强制转换为int*类型,再赋给ptr
    printf("%d,%d", *(a + 1), *(ptr - 1));
    //a 是数组名,数组名就是首元素的地址,数组名+1,就是首元素+1,
    //  跳过一个元素指向第二个元素,对a+1解引用就是2
    // a 是int*类型 a+1也是int*类型 a+1跳过一个整型,对a+1解引用就是2
    //ptr是int*类型,ptr-1向前挪一个整型,再解引用就是5
    return 0;
}

在这里插入图片描述

笔试题2🌖

考查指针加减整数的问题
假设p 的值为0x100000。 如下表表达式的值分别为多少?(X86环境下)
已知,结构体Test类型的变量大小是20个字节

#include <stdio.h>
struct Test
{
	int Num;
	char* pcName;
	short sDate;
	char cha[2];
	short sBa[4];
}*p;
int main()
{
	printf("%p\n", p + 0x1);
	printf("%p\n", (unsigned long)p + 0x1);
	printf("%p\n", (unsigned int*)p + 0x1);
	return 0;
}

在这里插入图片描述
解析:

#include <stdio.h>
struct Test
{
	int Num;
	char* pcName;
	short sDate;
	char cha[2];
	short sBa[4];
}*p;//p是结构体指针变量
int main()
{
	p = (struct Test*)0x100000;//将0x100000赋给p需要强制类型转换
	printf("%p\n", p + 0x1);//0x100014
	//0x1 就是1,p+0x1=>p+1
	//p+1就是p要跳过一个结构体,一个结构体的大小是20,0x100000 + 20 = 0x100014;
	//16进制14转换为10进制就是20;1x16^1+4x16^0 = 20
	printf("%p\n", (unsigned long)p + 0x1);//0x100001
	//这里将p强制类型转换为unsigned long 整型,整型+1就是+1,所以是0x100001
	printf("%p\n", (unsigned int*)p + 0x1);//0x100004
	//这里将p强制类型转换为unsigned int*指针类型,p指向的是无符号整型 4字节,
	//整型指针+1是跳过一个整型4字节,所以是0x100004
	return 0;
}

笔试题3🌗

下面代码的运行结果是什么:

#include <stdio.h>
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[4] = { 1, 2, 3, 4 };
    int* ptr1 = (int*)(&a + 1);
    //&a a是数组名,+1跳过一个数组,
    int* ptr2 = (int*)((int)a + 1);
    //a本来是int*类型,强制类型转换成int类型,整型+1就是+1,所以ptr2指向第一个元素的第二个字节
    printf("%x,%x", ptr1[-1], *ptr2);
    //ptr1[-1]=>*(ptr1-1);就是ptr1往前挪一个整型,再解引用就是4
    //ptr2是一个整型指针,是2个字节,所以要从第一个元素的第二个字节往后数四个字节 就是 00 00 00 02,
    //我们这里是小端存储要转换成16进制就是 0x 2 00 00 00 打印出来就是2000000
    return 0;
}

%p —— 打印地址
%x —— 是16进制的格式打印
在这里插入图片描述

笔试题4🌘

#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;
}

在这里插入图片描述
解析:

#include <stdio.h>
int main()
{
    int a[3][2] = { (0, 1), (2, 3), (4, 5) };
    //数组初始化内容有逗号表达式,逗号表达式是从左向右依次计算,逗号表达式的结果是最后一个表达式的结果
    //数组实际上初始化的是int a[3][2] = {1,3,5};
    int* p;
    p = a[0];//a[0] => a[0][0]
    printf("%d", p[0]); //p[0] => *(p+0) => *p =1
    return 0;
}

笔试题5🌑

下面代码的运行结果是什么:

#include <stdio.h>
int main()
{
    int a[5][5];
    int(*p)[4];
    p = a;
    printf("%p,%d\n", &p[4][2] - &a[4][2], &p[4][2] - &a[4][2]);
    return 0;
}

在这里插入图片描述
解析:

#include <stdio.h>
int main()
{
    int a[5][5];
    int(*p)[4];
    //p是一个指针,指向一个数组有四个元素,每个元素都是整型类型
    p = a;
    //a是数组名,数组名是首元素的地址,二维数组就是第一行的地址
    //a是int(*)[5]数组指针类型;p的类型是int(*)[4];将a的地址强制赋值给p,运行起来不会报错,但是编译器会报警告
    printf("%p,%d\n", &p[4][2] - &a[4][2], &p[4][2] - &a[4][2]);
    //p是int(*)[4],所以让p+1只会跳过4个字节
    //p[4][2] => *(*(p+4)+2);   p+4是一个整型指针,解引用访问4个字节;
    //p+4=>p[4]; 想象成一个二维数组,p[4]就是第5行的数组名;数组名表示首元素地址
    //指针和指针相减得到的是指针之间的元素个数,小地址减大地址是负数
    //&p[4][2] - &a[4][2] = -4
    //10000000000000000000000000000100 —— -4的原码
    //11111111111111111111111111111011 —— -4的反码
    //11111111111111111111111111111100 —— -4的补码
    //%d打印的是原码,就是-4;
    //%p打印的是地址,整型在内存中存的是补码,所以%p打印出来就是FFFFFFFC
    return 0;
}

在这里插入图片描述

笔试题6🌒

下面代码的运行结果是什么:

#include <stdio.h>
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()
{
    int aa[2][5] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
    int* ptr1 = (int*)(&aa + 1);
    //aa是数组名,&aa+1就是跳过整个数组指向数组的后面
    //将&aa+1 数组指针,强制类型转换为整型指针,赋给ptr1
    int* ptr2 = (int*)(*(aa + 1));
    //aa是数组名,数组名就是首元素的地址,二维数组就是第一行的地址,aa+1指向第二行
    //*(aa + 1)=>aa[1],aa[1]就是第二行的数组名,没有单独放在sizeof内部,也没有&,就是首元素的地址
    //*(aa + 1)=>aa[1]=>&aa[1][0],拿到的就是就是一个int*类型的整型指针
    printf("%d,%d", *(ptr1 - 1), *(ptr2 - 1));
    //ptr1是int*类型,ptr1-1就是向前挪一个整型,解引用就是10
    //ptr2是int*类型,ptr2-1就是向前挪一个整型,解引用就是5
    return 0;
}

在这里插入图片描述

笔试题7🌓

下面代码的运行结果是什么:

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

在这里插入图片描述
解析:

#include <stdio.h>
int main()
{
	char* a[] = { "work","at","alibaba" };
	//数组a的每个元素都是char*类型每个元素都是char*指针
	//字符串作为表达式存放的是首字符的地址
	char** pa = a;
	//a是数组名,数组名表示首元素地址,a的每个元素都是char*类型,
	//a的地址就是char**二级指针,pa指向a的第一个元素是合理的
	pa++;
	//pa++要跳过一个char*的元素指向下一个元素
	printf("%s\n", *pa);
	//pa指向第二个元素,解引用就是at
	return 0;
}

在这里插入图片描述

笔试题8🌔

下面代码的运行结果是什么:

#include <stdio.h>
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;
}

在这里插入图片描述
解析:

#include <stdio.h>
int main()
{
	char* c[] = { "ENTER","NEW","POINT","FIRST" };
	//数组C的每个元素都是char*类型每个元素都是char*指针
    //字符串作为表达式存放的是首字符的地址
	char** cp[] = { c + 3,c + 2,c + 1,c };
	//c是数组名,数组名表示首元素地址,所以c指向数组c的第一个元素,c+3是首元素+3
	//c的每个元素都是char*类型,数组名表示首元素地址,所以c的地址就是char**二级指针
	//cp是一个存放二级指针的数组,元素类型为char**
	char*** cpp = cp;
	//cpp里面存放cp,cp是数组名,数组名表示首元素地址,所以cpp指向cp的第一个元素
	//cp的每个元素都是char**类型,数组名表示首元素地址,所以cp的地址就是char***三级指针
	//cpp里面存放cp,所以cpp的类型是char***
	printf("%s\n", **++cpp);
	//++cpp是前置++,cpp自增然后指向cp的第二个元素,这一次cpp的指自增会影响下一次的计算
	//**++cpp第一颗*解引用的结果是c+2,第二颗*解引用的结果是POINT
	printf("%s\n", *-- * ++cpp + 3);
	//++cpp是前置++,上一次计算中cpp自增指向cp的第二个元素,这一次再自增就指向cp的第三个元素
	//*++cpp得到的结果是c+1;--c+1 =>c,c指向数组c的第一个元素,*--*++cpp = *c[0]
	//解引用得到c[0]的地址是E,E的地址+3,得到的是后面的E,打印的是R往后的字符就是ER
	printf("%s\n", *cpp[-2] + 3);
	//cpp[-2] = *(cpp-2); *cpp[-2] + 3 =**(cpp-2)+3
	//cpp现在指向数组cp的第三个元素,cpp-2就指向数组cp的第一个元素,
	// *(cpp-2)=c+3,**(cpp-2) = *c[3],解引用得到c[3]的地址是F,再+3就是S,打印的结果就是ST
	printf("%s\n", cpp[-1][-1] + 1);
	//cpp[-1][-1] = *(*(cpp-1)-1); cpp[-1][-1] + 1 = *(*(cpp-1)-1) +1
	//此时的cpp还是指向数组cp的第三个元素,cpp-1就指向数组cp的第二个元素
	//*(cpp-1) = c+2, ==> *(cpp-1)-1 = c+1,c+1指向数组c的第二个元素
	//*(*(cpp-1)) = *c[1],解引用得到c[1]的地址是N,c[1]的地址+1就是E,所以打印的结果是EW
	return 0;
}
//注:cpp只有在++或者--的时候才会影响下一次cpp的计算,非++或者--不影响下一次运算

在这里插入图片描述

本章到这里就结束啦,如果有哪里写的不好的地方,请指正。
如果觉得不错并且对你有帮助的话请给个三连支持一下吧!
Fighting!!!?

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-10-08 20:22:11  更:2022-10-08 20:22:30 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/19 7:05:36-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码