《c语言深度解剖》--一套非常经典的笔试题
学习完c语言,需要对所学知识进行一个检测,下面有一套笔试题,
你有四十分钟进行检测,每道题五分,严格要求自己打分。
根据作者原话:在没有何提示的情况下,如果能得满分,那你可以扔掉本书了,因为你的水平已经大大超过了作者;如果能得80分以上,说明你的C语言基础还不错,学习本书可能会比较轻松;如果得分在50分以下,也不要气馁,努力学习就行了;如果不小心得了10分以下,那就得给自己敲敲警钟了;如果不幸得了0分,那实在是不应该,因为毕竟很多题是很简单的。
答案解析:
1.根据隐式类型转换存储规则:
long double
double
float
unsigned long int
long int
unsigned int
int
当连个不同类型的值比较或相加减时,默认从低到高转换,即向上转换
所以,a和b相加时,b会隐式转换成unsigned int类型,对于-20来说,其补码为:
100000000 00000000 00000000 00010100 -- 原码
1111111111 111111111 111111111 11101011 -- 反码
1111111111 111111111 111111111 11101100 -- 补码
此时b是无符号整型,首位不再被当成符号位,所以b成了一个很大的数字,加上a当然比6大。
2.运行到strcpy的时候可能会发生异常,因为str1存储了10个字符a之后,后面存储的不是’\0’,
strcpy拷贝时会寻找’\0’作为结束标志,str1中第10个字符a之后的空间不是str1的,是内存的空间,
strcpy从此地方开始向后寻找’\0’时,会造成内存的非法访问,可能会导致程序出现异常。
3.i = 10,j = 1.
由于静态的局部变量是再内存中的静态区存储,静态局部变量在初始化一次后不会被销毁,且只初始化一次,在下一次使用时仍然保持上一次的值。所以i只初始化一次,每次继续调用该函数时,仍然保留上一次i的值。
对于j来说,j是静态全局变量,每次调用函数都会被初始化.
4.除了(3)是400以外,其余全都是4。
(1)p是指针,被置为空, 所以p所指向的地址就是一个空地址,既然是地址,题目限定了在32位系统下,所以就是4个字节。
(2)p其实就是对p进行解引用,p是所指向的对象是一个int类型,计算p其实就是计算int类型的大小。
(3)对于数组来说,数组名表示数组首元素地址,除了下面两个例外:
1.sizeof(数组名),即数组名单独放在sizeof内部,表示的是整个数组的大小。
2.&数组名,取到的是整个数组的地址。
除了上面两个特例,其余的数组名都是表示数组首元素地址。
很明显:(3)中的数组名单独放在sizeof内部,计算的就是整个数组大小,a数组有100个元素,每个元素是int类型,总大小就是400字节。
(4)a[100]就是计算a的第100个元素的大小,虽然a[100]并不存在,也不影响计算a的第100个元素的大小,也是一个int类型。比如说:int b[1] = {0}; 计算sizeof(b[10]),大小仍为4个字节。
(5)&a,是上面两个特例中的第二个特例,取到的是整个数组的地址,其实,整个数组的地址就是首元素的地址,只是如果取到整个数组的地址后+1,会跳过整个数组。
既然它是地址,地址就是4个字节。
(6)&a[0],就是取首元素地址,是地址就是4字节。
(7)这是一个典型的数组传参问题,b传参时,因为b是数组首元素地址,本质上传的是一个int*的指针,形参部分int b[100],实际上这是一个指针,所以计算b的大小,就是计算指针的大小,即4个字节。(b不再是数组首元素地址,b是一个指针)
5.对于数组a来说,它的元素类型是signed char类型,范围是-128~127。a[0] = -1,a[1] = -2,…a[127] = -128,此时a[128]不可能是-129,因为:
-128的二进制原码是:
100000000 00000000 00000000 10000000
补码是:
11111111 11111111 11111111 10000000
存入a[127]中会发生截断,补码的低8位放进去,即
10000000放入,转化成原码为:
1 00000000
而该原码规定就是-128。
而-129的二进制原码为:
100000000 00000000 00000000 10000001
补码为:
11111111 11111111 11111111 01111111
截取低8位存入a[128]中,是
01111111
转换成二进制原码是:
01111111
这是正数,正数的原码反码补码相同,转换成十进制是127.
所以a[128] = 127, a[129] = 126… ,直到a[255] = 0;
strlen计算长度时,就需要找’\0’作为结束标志,而0就代表’\0’。所以计算数组的长度时,大小为255.
6.(1)const放在p之前,限制的是 * p,所以p不可更改,但是p未被限制,所以p指向的对象可以更改。
(2)同(1),同样放在*p之前,结果同(1)
(3)const放在p之前,p之后,限制的是p,所以p指向的对象不可更改,p可以更改
(4)p和p都被限制了,所以p指向的对象和p都不可更改。
7.代码(1):这时候编译器对代码进行优化,因为在代码(1)的两条语句中,i没有被用作左值(没有被赋值)。这时候编译器认为i的值没有发生改变,所以在第1条语句时从内存中取出i的值赋给j之后,这个值并没有被丢掉,而是在第⒉条语句时继续用这个值给k赋值。编译器不会生成出汇编代码重新从内存里取i的值(不会编译生成装载内存的的汇编指令﹐比如ARM的LDM指令),这样提高了效率。但要注意:两条语句之间i没有被用作左值(没有被赋值)才行。
代码(2)的使用时机:如果i是一个寄存器变量、表示一个端口数据或者是多个线程的共享数据,那么就容易出错,所以说
volatile可以保证对特殊地址的稳定访问。
代码(2)的使用时机:如果i是一个寄存器变量、表示一个端口数据或者是多个线程的共享数据,那么就容易出错,所以说
volatile可以保证对特殊地址的稳定访问。
8.这道题需要画图理解。结果是 5,2000000
数组a的5个元素的十六进制表示形式在内存中的布局如上图:
对于ptr1来说,&a取到了整个数组的地址,+1跳过了整个数组,再强转成int*,所以ptr1指向的是数组的后一位的地址。如下图:
以16进制的形式打印ptr[-1]时,其实可以理解成打印 *(ptr-1),指针-1,跳过指针所指向对象的类型,ptr1指向的对象是int类型,所以-1跳过一个int。如下图:
指针指向的对象是一个int类型,所以一次取出4个字节。
由于计算机是小端存储模式,所以,低位放在低地址处,高位放在高地址处,拿出来就是 00 00 00 05,以十六进制的形式打印,5前面的0是不显示的,没什么意义,所以打印出来就是5。
对于ptr2来说,a是数组首元素地址,强转成(int),所以a的地址就被强转成了一个整型,假设a的地址为:0x0012ff40,该地址就被强转成了一个整型,此时0x0012ff40是一个整型,整型+1之后,就是0x0012ff41,加了一个字节(整型+1就是+1)。0x0012ff41再强转成一个int*的指针赋给ptr2。此时ptr2指向的位置如下图:
ptr2指向的对象是int类型,所以ptr2一次性会读取4个字节,即读取
00 00 00 02,由于计算机是小端存储,低位放在低地址,高位放在高地址。
所以以十六进制的形式表示是0x 02 00 00 00,以十六进制的形式打印出来是2 00 00 00,(02中的0会被去掉)
9.值为32
+号的优先级高于<<,先计算2+3,再计算0x01<<, 即
0x01<<5,
将0x01的十六进制补全是 0x00 00 00 01,转换成二进制的形式为:
00000000 00000000 00000000 00000001
<<操作符移动的是二进制位,左移5位后变成:
00000000 00000000 00000000 00100000
转换成十进制是32
10.答案:
#define SQR(x) ((x)*(x))
然而,该宏是有缺陷的,如果传入x++,++x这样有副作用的参数,宏就会出现问题。
(指出宏有缺陷者满分)
11.结构体在内存中的存储较为复杂,具体请看
结构体内存对齐
这里直接说明答案即可:
(在未说明的情况下,默认对齐数为8)
代码(1)的结构体大小为12字节,代码(2)的结构体大小为8字节。
12.实际上,这道题目是存在一点问题的,实际中不能随便找一个地址,就对该地址的内容进行访问,这是野指针问题,是非法访问的问题,对编译器来说这是违法行为。
相当于题目让你闯红灯,闯红灯本来就是违法行为。(这里没有针对任何人,只是就本道题说一下我的看法);
可能题目是想让写题人知道指针的强大和灵活,让写题人重视指针的运用。
不过如果真的要写,就是下面的写法:
int *p = (int*)0x12ff7c;
*p = 0x100;
13.
a表示数组首元素地址,a+1跳过了一个元素的大小,所以a+1就是a[1]的地址,*(a+1) 就拿到了a[1],所以结果是1。
对ptr来说,&a取到的是整个数组的地址,+1跳过了整个数组,所以ptr指向了元素5的后一位, * (ptr-1) 就指向5,打印出来就是5。
14. 0x100014,0x100001,0x010004
(1)
首先需要知道结构体的大小是多少,由上面结构体内存存储模式可知,该结构体大小为20字节。
p是一个结构体指针,指针+0x1,跳过了一个结构体的大小,所以p+1跳过了20字节,因为p的值为0x100000,所以p+1为0x100014,(20)转换为十六进制是14。
(2)
将p强转成unsigned long类型后,p的值就是一个长整型,即0x100000是unsigned long类型,整型+1就是+1.
结果为:0x100001
(3)将p强转成unsigned int*的指针,+1后跳过一个int类型,所以结果为0x100004
15.考察逗号表达式。
(0,1)计算的结果是1,(2,3)计算结果是3,(4,5)计算结果是5
a初始化后的结果为:
1 2
5 0
0 0
a[0]就是第一行元素的地址,此时p就是指向第一行元素的地址,然后打印p[0],相当于找到了第一行第一个元素,打印结果为1
16.(1)传参的时候有问题,b[10]实际上是不存在的。
(2)fun的参数部分,如果它是想对数组的a[3]进行修改,传参应该传b即可,因为b是数组名,数组名表示首元素地址,类型是char* ,想改变它的值,应该使用char*的指针来接收。
编译器会有一个警告,说类型不匹配,因为b[10]的类型是char,而函数参数类型是char*。
17.(1)在使用完pstu后没有置空,这是一个野指针问题。
(2)结构体的成员name也是一个指针,代码并没有给该指针申请空间,直接使用name会出现越界访问问题。
18,典型的递归问题,直接上答案:
0
1
2
5
10
19.
getchar函数的返回类型是一个int,但是c是一个char类型,将一个int类型放入char类型中会发生截断。‘
假如读取失败,getchar会返回EOF,EOF是一个宏,其本质是-1,
但有可能getchar读取失败返回的EOF不再-128~127这个范围内,导致if条件判断语句不进入,存在潜在的危险。
20.方法1:
int main()
{int a = 1;int ret = *((char*)&a);if (ret == 1){printf("小端\n");}else{printf("大端\n");}
}
方法2:
union un
{int a;char c;
}s;int main()
{s.a = 1;if (s.c == 1){printf("小端\n");}else{printf("大端\n");}return 0;
}
在没有何提示的情况下,如果能得满分,那你可以扔掉本书了,因为你的水平已经大大超过了作者;如果能得80分以上,说明你的C语言基础还不错,学习本书可能会比较轻松;如果得分在50分以下,也不要气馁,努力学习就行了;如果不小心得了10分以下,那就得给自己敲敲警钟了;如果不幸得了0分,那实在是不应该,因为毕竟很多题是很简单的。
相关文章:
《c语言深度解剖》--一套非常经典的笔试题
学习完c语言,需要对所学知识进行一个检测,下面有一套笔试题, 你有四十分钟进行检测,每道题五分,严格要求自己打分。 根据作者原话:在没有何提示的情况下,如果能得满分,那你可以扔掉本书了,因为你的水平已经…...
【数据结构与算法】单调队列 | 单调栈
🌠作者:阿亮joy. 🎆专栏:《数据结构与算法要啸着学》 🎇座右铭:每个优秀的人都有一段沉默的时光,那段时光是付出了很多努力却得不到结果的日子,我们把它叫做扎根 目录👉…...
openh264解码h264视频帧主流程
一 解析一帧的入口int32_t WelsDecodeSlice (PWelsDecoderContext pCtx, bool bFirstSliceInLayer, PNalUnit pNalCur) {// 解码slicePDqLayer pCurDqLayer pCtx->pCurDqLayer;PFmo pFmo pCtx->pFmo;int32_t iRet;int32_t iNextMbXyIndex, iSliceIdc;PSlice pSlice &a…...
【个人笔记】C语言位域
一句话解释位域:指定结构体内变量的的位宽,从而节省空间 例子: #include <stdio.h> struct _test {int bit1:3; // 第一个字节0 ~ 2位 int :0; // 空域:表示第一个字节 3~7都为0int bit2:1; // 第二个字节第0位int :3;…...
ROS笔记(1)——ROS的核心概念
目录 节点与管理器 话题通信 服务通信 参数——全局共享字典 节点与管理器 节点——执行单元 (1)执行具体任务的进程、独立运行的可执行文件 (2)不同节点可使用不同的编程语言,可分布式运行在不同的主机 ÿ…...
动态SQL使用【JavaEE】
动态SQL使用 1. if 标签 判断一个参数是否有值,如果没值,那么就会隐藏 if 中的 sql 语法: <if test"username!null">username#{username} </if>表达式:username 的参数是否为空 如果结果为 true,…...
leetcode刷题
1、stack栈相关 top():返回一个栈顶元素的引用,类型为 T&。如果栈为空,返回值未定义。 push(const T& obj):可以将对象副本压入栈顶。这是通过调用底层容器的 push_back() 函数完成的。 push(T&& obj)࿱…...
移动设备安全管理基础指南
什么是移动安全管理 (MSM) 移动安全管理是指为保护企业中的移动设备和企业数据而采取的行动。这些操作可以进一步被归类为反应性的或主动的,基于该操作是在数据和设备被破坏之前还是之后执行的。除了管理移动设备外,大多数MDM解决…...
【Java|多线程与高并发】 使用Thread 类创建线程的5种方法如何查看程序中的线程
文章目录前言线程创建1.继承Thread类重写run()方法如何查看程序中的线程?2.实现Runnable接口3.使用匿名内部类,继承Thread4.使用匿名内部类,实现Runnable5.⭐使用Lambda表达式,创建线程(重要)Thread 的常见构造方法总结前言 在这里主要补充说明一些问题,方便更好地理解下面的…...
零基础学MySQL(五)-- 详细讲解数据库中的常用函数
目录🎇一、聚合函数1️⃣count 函数(1)基本语法(2)基本练习(3)注意细节2️⃣sum 函数(1)基本语法(2)基本练习(3)注意细节3…...
第4章 流程控制-if-else,Switch,For循环(循环守卫,循环步长,倒叙打印),While循环,多重循环...
第 4 章 流程控制-if-else,Switch,For循环(循环守卫,循环步长,倒叙打印),While循环,多重循环 4.1 分支控制 if-else 让程序有选择的的执行,分支控制有三种:单分支、双分支、多分支 4.1.1 单分支 1)基本语法…...
2.4G-WiFi连接路由器过程
一、概述 WiFi的数据通信基于802.11协议进行,无线AP在工作时会定时向空中发送beacon数据包,基站(STA)从beacon中解析出AP的名称、加密方式等信息,从而发起连接。 二、WiFi连接路由器的详细过程 WiFi连接过程主要可以…...
3. SpringMVC Rest 风格
1. REST 简介 REST(Representational State Transfer),表现形式状态转换,它是一种软件架构风格。 当要表示一个网络资源的时候,可以使用两种方式: 传统风格资源描述形式 http://localhost/user/getById?…...
Python3简介
Python 是一个高层次的结合了解释性、编译性、互动性和面向对象的脚本语言。 Python 的设计具有很强的可读性,相比其他语言经常使用英文关键字,其他语言的一些标点符号,它具有比其他语言更有特色语法结构。 Python 是面向对象语言: 这意味着P…...
如何学习PMP?
★基础要打牢 方法:“基础不牢,地动山摇”,如果基础不牢那么就很难拿高分,因为连最基础的题目分都不一定能拿到。 可以在针对基础知识,把PMBOK看一两遍,再次加深印象,再把平时做章节练习、每日5…...
【DSP视频教程】第11期:插补算法,曲线拟合丝滑顺畅,统计函数和基础函数加速实现,汇集SIMD,饱和和MAC乘累加应用实战(2023-02-12)
视频教程汇总帖:https://www.armbbs.cn/forum.php?modviewthread&tid110519 DSP视频教程有段时间没有更新了。 当前DSP库从CMSIS软件包里面独立出来,并且更新非常频繁,所以本期视频教程优先给大家简单介绍下新版DSP, 然后为…...
分类模型评估:混淆矩阵、准确率、召回率、ROC
1. 混淆矩阵 在二分类问题中,混淆矩阵被用来度量模型的准确率。因为在二分类问题中单一样本的预测结果只有Yes or No,即:真或者假两种结果,所以全体样本的经二分类模型处理后,处理结果不外乎四种情况,每种…...
算法 ——世界 一
个人简介:云计算网络运维专业人员,了解运维知识,掌握TCP/IP协议,每天分享网络运维知识与技能。个人爱好: 编程,打篮球,计算机知识个人名言:海不辞水,故能成其大;山不辞石…...
2023年3月AMA-CDGA/CDGP数据治理认证考试这些城市可以报名
目前2023年3月5日CDGA&CDGP开放报名的城市有:北京、上海、广州、深圳、杭州、重庆,西安,成都,长沙,济南,更多考场正在增加中… DAMA认证为数据管理专业人士提供职业目标晋升规划,彰显了职业…...
Java变量和数据类型,超详细整理,适合新手入门
目录 一、什么是变量? 二、变量 变量值互换 三、基本数据类型 1、八种基本数据类型 2、布尔值 3、字符串 四、从控制台输入 一、什么是变量? 变量是一种存储值的容器,它可以在程序的不同部分之间共享;变量可以存储数字、字…...
Echarts 设置折线图拐点的颜色,边框等样式,hover时改变颜色
第014个点击查看专栏目录上一篇文章我们讲到了如何设置拐点大小,图形类型,旋转角度,缩放同比,位置偏移等,这篇文章介绍如何设置拐点的颜色、边框大小颜色等样式。hover轴线时候,拐点的填充颜色改变文章目录示例效果示例…...
做 SQL 性能优化真是让人干瞪眼
很多大数据计算都是用SQL实现的,跑得慢时就要去优化SQL,但常常碰到让人干瞪眼的情况。 比如,存储过程中有三条大概形如这样的语句执行得很慢: select a,b,sum(x) from T group by a,b where …; select c,d,max(y) from T grou…...
SpringBoot(3)之包结构
根据spring可知道,注解之所以可以使用,是因为通过包扫描器,扫描包,然后才能通过注解开发。 那么springboot需要扫描哪里呢? springboot的默认包扫描器,扫描的是自己所在的包和子包,例子如下 我…...
test2
物理层故障分析 一、传输介质故障 a.主要用途简述 传输介质主要分为 导向传输介质和非导向传输介质。前者包括双绞线(两根铜线并排绞合,距离过远会失真)、同轴电缆(铜质芯线屏蔽层,抗干扰性强,传输距离更…...
LoadRunner安装教程
备注:电脑最好安装有IE浏览器或者360极速版浏览器 一、下载安装包 提前下载安装文件,必须下载。 链接: https://pan.baidu.com/s/1blFiMIJcoE8s3uVhAxdzdA?pwdqhpt 提取码: qhpt 包含的文件有: 二、安装loadrunner 注意,以…...
VHDL语言基础-Testbech
目录 VHDL仿真概述: 基本结构: VHDL一般仿真过程: 仿真测试平台文件: 编写测试平台文件的语言: 一个测试平台文件的基本结构如下: 测试平台文件包含的基本语句: 产生激励信号的方式: 时钟信号: 复位信号: 周期信性信号: 使用延迟DELAYD: 一般的激励信号…...
机器学习基础总结
一,机器学习系统分类 机器学习系统分为三个类别,如下图所示: 二,如何处理数据中的缺失值 可以分为以下 2 种情况: 缺失值较多:直接舍弃该列特征,否则可能会带来较大噪声,从而对结果造成不良影…...
linux的三权分立设计思路和用户创建(安全管理员、系统管理员和审计管理员)
目录 一、三权分立设计思路 1、什么是三权 2、三员及权限的理解 3、三员之三权 4、权限划分 5、“三员”职责 6、“三员”配置要求 二、linux三权分立的用户创建 1、系统管理员 2、安全管理员 3、审计管理员 一、三权分立设计思路 1、什么是三权 三权指的是配置、…...
revit中如何创建有坡度的排水沟及基坑?
一、revit中如何创建有坡度的排水沟? 先分享一张有坡度排水沟的族的照片给大家加深一下印象,有了一个粗略的直观认识,小编就来说说做这个族的前期思路吧。 一、前期思路: 1、 用拼接的方式把这个族形状拼出来,先用放样࿰…...
Web自动化测试——selenium篇(一)
文章目录一、环境准备二、Web 自动化测试 Demo三、元素定位常用方法四、元素定位失败可能原因五、测试对象操作六、等待操作七、信息打印在学习 Web 自动化测试的过程中,selenium 是其中的常用工具。除了其开源免费,包含丰富的 API 以外,它还…...
html 企业网站模板/在线网站流量查询
有没有遇到过,导航UITableView,在push,back回来之后,当前cell仍然是选中的状态。当然,解决办法简单,添加一句[tableView deselectRowAtIndexPath:indexPath animated:YES]即可。令人纠结的时,在…...
网站alexa排名/微信推广方式有哪些
什么是位置参数,Python位置参数 位置参数,有时也称必备参数,指的是必须按照正确的顺序将实际参数传到函数中,换句话说,调用函数时传入实际参数的数量和位置都必须和定义函数时保持一致。 实参和形参数量必须一致 在…...
专门做音效的网站/冯站长之家官网
CP.200: Use volatile only to talk to non-C memoryCP.200:使用volatile只能表明该变量是非C内存Reason(原因)volatile is used to refer to objects that are shared with "non-C" code or hardware that does not follow the C memory model.volatile用于表明参照…...
威海网站开发制作/上海网站建设方案
快速排序是一种分治的排序算法,其主要思想是通过选择一个基准数,将数组划分成两个子序列,左边的数都比基准数小,右边的数都比基准数大,然后对这两个子序列分别进行快速排序,以此达到最终排序的目的。 在Jav…...
株洲网络/北京seo网站设计
一个事务中有多个对数据库操作的点 一个点完成了 事务没有结束 在数据库中就差不到这个变化 mysql的默认隔离级别 可重复读 也就是必须最起码读到已经提交了的数据 SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;这行代码 将当前的会话的隔离级别设置为 读未提交…...
做网站需要备案吗/沈阳网站关键词优化多少钱
一、定位 定位:定位是一种更加高级的布局手段。通过定位可以将元素放在页面的任意位置。position:通过position来设置定位。可选值:static 默认值,元素是静止,没有开启定位relative 开启元素的相对定位absolute 开启元素的绝对…...