《C陷阱与缺陷》读书笔记1

news2024/7/4 6:30:27

在这里插入图片描述

词法分析:贪心法

主要就是解释词法分析时的原则,即:

编译器将程序分解为符号时,从左到右一个字符接一个字符的读入。如果编译器的输入流截止至某个字符之前都已经被分解为一个个符号,那么下一个符号将包括从该字符之后可能组成符号的最长字符串。

就是说编译器也得一个字符接一个字符地读文本,但是读入的文本(也就是当前分析的符号)有歧义(有二义性)时,就按照能组成当前符号的最长字符串算。

例如:

int a = 3,b = 4;
a = a---b;
printf("%d %d",a,b);
// Output: -1 4

那么它读到---,就会解读为(a--) - b而不是a - (--b)

类似的问题还有:

a=-1可以被人理解为a =- 1a = -1

y=x/*p可以被人理解为y=x /* py=x / *p


说“被人理解为”是因为计算机表示这样理解,人的理解有二义性,但是计算机一定会遵循某种规则理解出唯一的含义

当然,学习的目的就是为了去消除二义性,一方面读到这种2b代码时知道该怎么理解(这种代码多出现在做题中),另一方面知道如何避免,(不难从上面看出解决方法)也就是善用分隔符,书写固定规范的代码。

整型常量

如果整型常量第一个字符是0,那么该常量将被视为八进制数

例如十进制141就是八进制的0215

int a = 0215,b = 4;
printf("%d %d",a,b);
// Output:141 4

函数声明

float ((f));

((F))返回类型是float,可推知f返回类型是float,亦即f为浮点型

float ff();

ff()求值结果是浮点数,ff()本身是个函数,即ff()是返回浮点值的函数。

float *g();

等价于float* g(),返回指向浮点数的指针的函数。按优先级()结合优先级高于*故先有g()为一个函数

()结合优先级高于*


然后复杂的就来了:

float (*h)();

h是个函数指针,它指向的函数返回值是float

推理过程:

h // 变量名
*h // 指针变量
(*h)() // 指向函数,由于优先级得给*h用括号围起来
float (*h)() // 明确函数的返回值

作为一个函数指针,首先它指向的得是函数,所以最右侧有(),然后函数的返回值毋庸置疑也是写在最左侧的。也就是float __ ()现在剩下下划线部分得继续填空。

// 这是一个函数指针的例子
// p的类型为 int(*)(int,int)
int(*p)(int, int);

那么进一步地,(float (*)())表示“指向返回值为浮点类型的函数的指针”的类型转换符。


难度增加:

(*(void(*)())0)();

毋庸置疑,这首先是一个函数调用,因为xxx();是函数调用最显而易见的形式。

调用的函数是哪个呢?得看最右侧括号左面的。显然(*(void(*)())0)()符合函数指针调用函数的样子,即(*fp)();,这是经由函数指针fp调用它所指向的函数,,ANSI C允许简写为fp()

由上,既然*fp表示它fp所指向的函数,那么类比过来*(void(*)())0也表示一个函数

进一步地,虽然*(void(*)())0没见过,但是*(float)0我们能理解:0是int型,然后给它强制转换为float,然后对它使用解引用运算符,也就是把0当做地址,解引用得到这个地址的内容。

所以说float规定了*(float)0是按float格式解引用得到数据,并且void(*)()float意思相近。那么void(*)()要将0这个地址转换为void(*)()这个类型(即指向返回值为void类型的函数的指针),函数指针解引用得到的就是函数本身。

换句话说,我们把0强制转化为了一个指针类型的数据。那么指针变量指向内容就是这个地址0。

如果在这个基础上,指针是函数指针,那么0就是函数的地址

在编译时系统就会为这个函数代码分配一段存储空间,这段存储空间的首地址称为这个函数的地址

所以最终就是调用首地址为0的子例程。


显然,在使用typedef后能有效地简化代码,降低阅读难度:

typedef void (*funcptr)();

(*(funcptr)0)();
// 等价于(*(void(*)())0)();

书中的最后一个例子是取自signal.h,其中有这样一个函数声明:

void (*signal(int sig, void (*handler)(int)))(int);

意思是signal函数接受两个参数,分别是一个被捕获的信号整数值sig,另一个是指向由用户提供的函数的指针handlerhandler指向的函数接受一个int参数,返回值为void,用于处理捕获到的信号。

然后整个函数签名的理解就分为两部分,一部分是handler,另一部分是signal函数,分别来看:

// handler
void (*handler)(int);
// signal
void (*signal(...))(int);

其中...signal函数的参数类型,由于signal函数的定义长得像void f(int);这种,也不难发现对于signal(...)解引用应当得到一个函数,也就是说signal函数的返回值是一个指向返回值为void类型的函数的指针,这样才能进一步解引用得到一个函数。

函数signal具有参数时,其函数签名可能看起来比较奇怪,但是倒也不是无法理解:毕竟对void (*signal(...))(int);解引用才得到返回值是void且接受一个int的函数,这也就表明了signal函数的返回值。

使用typedef简化得:

typedef void (*HANDLER)(int);
HANDLER signal(int, HANDLER);

这样看就很明了了,signal函数的返回值是一个函数指针,它指向的函数无返回值,有一个int类型参数。

像是高阶函数。


再提一下,对于下列程序

#include <stdio.h>
void f(int a){
	printf("%d",a);
} 
int main()
{		
	printf("%d %d %d",f,&f,*f);
}

这里输出是一样的,函数名就是函数入口地址。

看了看为什么c语言中对函数名取地址和解引用得到的值一样这个问题

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Linux文件锁的使用

文件是一种共享资源,多个进程对同一文件进行操作的时候,必然涉及到竞争状态&#xff0c;因此引入了文件锁实现对共享资源的访问进行保护的机制&#xff0c;通过对文件上锁&#xff0c; 来避免访问共享资源产生竞争 状态。 一、文件锁的分类 1.建议性锁 建议性锁本质上是一种协…

Java并发编程——Threadlocal源码解析

Threadlocal源码解析一、基本结构二、ThreadLocal操作set操作get操作remove操作三、内存泄露&#xff1f;四、ThreadLocalMap核心变量数组下标计算方式阈值计算扩容下标冲突&#xff08;hash冲突&#xff09;从名称上来看可以理解为线程本地变量&#xff0c;也可以认为是线程局…

(JAVA)认识Java中的数据类型和变量

文章目录前言1.字面常量2. 数据类型3.变量3.1 变量概念3.2 语法格式3.3 整形变量3.4 浮点型变量3.5 字符型变量3.6布尔类型变量3.7 类型转换3.7.1 隐式转换&#xff08;自动类型转换&#xff09;3.7.2 显示转换 &#xff08;强制类型转换&#xff09;3.8 类型提升4. 字符串类型…

驱动开发:内核层InlineHook挂钩函数

在上一章《驱动开发&#xff1a;内核LDE64引擎计算汇编长度》中&#xff0c;LyShark教大家如何通过LDE64引擎实现计算反汇编指令长度&#xff0c;本章将在此基础之上实现内联函数挂钩&#xff0c;内核中的InlineHook函数挂钩其实与应用层一致&#xff0c;都是使用劫持执行流并跳…

三类基于贪心思想的区间覆盖问题【配套资源详解】

博主主页&#xff1a;Yu仙笙 配套资源&#xff1a;三类基于贪心算法覆盖问题-C文档类资源-CSDN下载 目录 三类基于贪心思想的区间覆盖问题 情形1&#xff1a;区间完全覆盖问题 描述&#xff1a; 样例&#xff1a; 解题过程: 例题&#xff1a; 题意&#xff1a; 例题&#xff1a…

深入理解Kafka服务端之索引文件及mmap内存映射

深入理解Kafka服务端之索引文件及mmap内存映射 - 墨天轮 一、场景分析 Kafka在滚动生成新日志段的时候&#xff0c;除了生成日志文件(.log)&#xff0c;会同时生成一个偏移量索引文件(.index)、一个时间戳索引文件(.timeindex)和一个已中止事务索引文件(.txnindex)。 由于索引写…

JVM面试高频问题

一、进程与线程 在谈JVM的这些问题前&#xff0c;我们先来复习一下有关线程和进程的关系 进程可以看作是程序的执行过程。一个程序的运行需要CPU时间、内存空间、文件以及I/O等资源。操作系统就是以进程为单位来分配这些资源的&#xff0c;所以说进程是分配资源的基本单位。线…

C语言函数章--该如何学习函数?阿斗看了都说会学习了

前言 &#x1f47b;作者&#xff1a;龟龟不断向前 &#x1f47b;简介&#xff1a;宁愿做一只不停跑的慢乌龟&#xff0c;也不想当一只三分钟热度的兔子。 &#x1f47b;专栏&#xff1a;C初阶知识点 &#x1f47b;工具分享&#xff1a; 刷题&#xff1a; 牛客网 leetcode笔记软…

【Python入门指北】 发邮件与正则表达式

文章目录邮件发送一、群发邮件二、指定用户发邮件正则表达式一、预备知识正则1. 正则介绍2. 陷阱3. 特殊的字符二、 re 模块的方法1 常用方法2. 正则分组总结邮件发送 #第三方模块 yagmail #pip3 install yagmailimport yagmail""" 项目需求 yag yagmail.SMTP(u…

MyBatis Plus实现动态字段排序

利用周末时间&#xff0c;对已有的项目进行了升级&#xff0c;原来使用的是tkmybatis&#xff0c;改为mybatis plus。但是由于修改了返回数据的格式&#xff0c;前端页面字段排序失效了&#xff0c;需要刷新表格才会排序。页面效果如下 easyui的数据表格datagrid支持多字段排序…

【仿牛客网笔记】Spring Boot实践,开发社区登录模块-账号设置,检查登录

首先访问账号设置的页面。 新建一个Controller,用过RequestMapping生成访问路径 上传头像 首先打开配置文件&#xff0c;配置一下将文件配置到哪里。 直接在Controller存了&#xff0c; 更新的时候掉Map&#xff0c;参数为id和路径。 注入日志对象后&#xff0c;通过Val…

SpringBoot项目启动执行任务的几种方式

经过整理后得到以下几种常用方式&#xff0c;供大家参考。 1. 使用过滤器 init() &#xff1a;该方法在tomcat容器启动初始化过滤器时被调用&#xff0c;它在 Filter 的整个生命周期只会被调用一次。可以在这个方法中补充想要执行的内容。 Component public class MyFilter …

CTF竞赛网络安全大赛(网鼎杯 )Web|sql注入java反序列化

CTF竞赛网络安全大赛题目考点 sql注入 java反序列化 网鼎杯解题思路 题目一打开是这样的界面 下载题目的附件,并用jd-gui.exe打开 核心代码如下 Test代码 `` package 部分class;import cn.abc.common.bean.ResponseCode; import cn.abc.common.bean.ResponseResult; impor…

持续交付中流水线构建完成后就大功告成了吗?别忘了质量保障

上期文章我结合自己的实践经验&#xff0c;介绍了持续交付中流水线模式的软件构建&#xff0c;以及在构建过程中的3个关键问题。我们可以看出&#xff0c;流水线的软件构建过程相对精简、独立&#xff0c;只做编译 和打包两个动作。 但需要明确的是&#xff0c;在持续交付过程…

网课查题接口使用方法

网课查题接口使用方法 本平台优点&#xff1a; 多题库查题、独立后台、响应速度快、全网平台可查、功能最全&#xff01; 1.想要给自己的公众号获得查题接口&#xff0c;只需要两步&#xff01; 2.题库&#xff1a; 查题校园题库&#xff1a;查题校园题库后台&#xff08;点…

Hadoop面试题汇总-20221031

Hadoop面试题汇总 HDFS部分 1、请描述HDFS的写流程。 答&#xff1a; 首先由客户端向 NameNode 发起文件上传请求&#xff0c;NameNode 检查文件要上传的目录&#xff0c;并鉴权。如果上传用户对此目录有权限&#xff0c;则允许客户端进行上传操作。客户端接收到允许指令后&…

本科毕业论文内容必须有国内外文献综述吗?

不知不觉间整个暑假变过去了&#xff0c;现在大部分的大学生都已经开学了。2023届毕业的学生现在也开始借鉴毕业论文的选题工作。但是无论是现在正在选题的大四的同学们还是还在上大一大&#xff0c;二大三的同学们都对毕业论文这4个字有着天生的恐惧感。因为对于大多数人来说&…

阿里为何禁止在对象中使用基本数据类型

大家好&#xff0c;我是一航&#xff01; 前两天&#xff0c;因为一个接口的参数问题&#xff0c;和一位前端工程师产生了一些分歧&#xff0c;需求很简单&#xff1a; 根据一个数值类型&#xff08;type 取值范围1&#xff0c;2&#xff0c;3&#xff09;来查询数据&#xff…

HTML+CSS+JavaScript七夕情人节表白网页【樱花雨3D相册】超好看

这是程序员表白系列中的100款网站表白之一&#xff0c;旨在让任何人都能使用并创建自己的表白网站给心爱的人看。 此波共有100个表白网站&#xff0c;可以任意修改和使用&#xff0c;很多人会希望向心爱的男孩女孩告白&#xff0c;生性腼腆的人即使那个TA站在眼前都不敢向前表白…

pandas 基本数据

目录 1. pandas 简介 2. pandas 基本数据结构 2.1 Series 类型 2.1.1 索引-数据的行标签 2.1.2 值 2.1.3 切片 2.1.4 索引赋值 2.2 DataFrame 类型 1. pandas 简介 一般导入的形式&#xff1a;import pandas as pd 2. pandas 基本数据结构 python 的数据结构&#xff1a…