C语言书籍——A/陷阱之处

news2025/6/9 15:57:59

文章参考于文献:《C陷阱与缺陷》[美]Andrew Koening

 

🌈个人主页:慢了半拍

🔥 创作专栏:《史上最强算法分析》 | 《无味生》 |《史上最强C语言讲解》 | 《史上最强C练习解析》

🏆我的格言:一切只是时间问题。 

目录

词法陷阱 

一、= 不同于 ==

二、& 和 | 不同于 && 和 ||

三、词法分析中的“ 贪心法 ”

四、整型常量

五、字符与字符串

语法陷阱

一、理解函数声明

二、运算符的优先级问题

三、注意作为语句结束标志的分号

四、swith语句

五、函数调用

六、“悬挂”else引发的问题

语义陷阱

一、指针与数组

二、非数组的指针

三、作为参数的数组声明

四、避免“ 举隅法 ”

五、空指针并非空字符串

六、边界计算与不对称计算

七、求职顺序

八、逻辑运算符&&、| 和 !

九、整数溢出

十、为函数main提供返回值


词法陷阱 

一、= 不同于 ==

在 if 判断时容易出错。

=:赋值运算,a=3;表示的是将3赋值给a变量。
==:比较运算,a==3;表示判断a是否等于3,若等于则返回1,否则返回0。

二、& 和 | 不同于 && 和 ||

这是两个 逻辑操作符与位操作符的区别。

详见《逻辑操作符》与《位操作符》

三、词法分析中的“ 贪心法 ”

a---b;等于a-- -b;  //先a-b,再a--
不等于a- --b;  //--b先做自减运算,再a-b

四、整型常量

如果一个整型常量的第一个数字是0,则该常量会被当做是八进制数,因此10和010代表是分别是十进制的10和十进制的8。

五、字符与字符串

单引号引起来的字符代表的是该字符的ASCII码值

双引号引起来的字符串代表的是一个指向无名数组的起始字符的指针,该数组被双引号之间的字符以及一个额外’\0’(字符串标志)初始化。

在双引号引起来的字符串中,注释符号/*属于字符串的一部分;在注释中出现的双引号“”又属于注释的一部分。

因此,语句:printf("The world") 和以下语句是等价的:

char str[]= {'T','h','e',' ','w', 'o','r','l','d','\n'};
printf(str);

语法陷阱

一、理解函数声明

指针例题

二、运算符的优先级问题

详见 优先级

三、注意作为语句结束标志的分号

//代码1
if(x[i] > b);
	b = x[i];
//代码2
if(x[i] > b){}
	b = x[i];

//代码3
if(x[i] > b)
	b = x[i];

一个分号就代表一个语句的结束。代码1与代码2是等价,if和赋值语句是两个独立的语句;而第三句中赋值语句在if中。

四、swith语句

语句详解

五、函数调用

C语言要求:在函数调用时即使函数不带参数也应该包括参数列表。因此,如果f是一个函数,

f();

是一个函数调用语句。


f;

却是一个什么也不做的语句。更精确地说,这个语句计算函数f的地址,却并不调用该函数。

六、“悬挂”else引发的问题

if (x == 0)
		if (y == 0) error();
	else {
			Z = X + Y;
			f(&z);
		 }

 两种解读:

解读一:

if (x == 0) 
{
	if (y == 0) error();
	else 
	{
		Z = X + Y;
		f(&z);
	}
}

 解读二:

if (x == 0)
{
	if (y == 0) error();
}
	else
	{
		Z = X + Y;
		f(&z);
	}

语义陷阱

一、指针与数组

深入理解指针系列文章

二、非数组的指针

三、作为参数的数组声明

四、避免“ 举隅法 ”

常见错误解释:避免以整体代表部分,或者以部分代表整体。

常见错误:混淆指针与指针所指向的数据。

char *p,*q;
p ="xyz";

上面的赋值语句使得p的值就是字符串"xyz",然而实际情况并不是这样,实际上,p的值是一个指向由'x'、'y'、’z"和\0 4个字符组成的数组的起始元素的指针。

因此,如果我们执行下面的语句:q=p;

p和q现在是两个指向内存中同一地址的指针,但这个赋值语句并没有同时复制内存中的字符。

复制指针并不同时复制指针所指向的数据,因此,当我们执行完下面的语句之后:q[1]='y';q所指向的内存现在存储的是字符串'xyz’。因为p和q所指向的是同一块内存,所以p指向的内存中存储的当然也是字符串’xyz'。

五、空指针并非空字符串

在C语言中将一个整数转换为一个指针,最后得到的结果都取决于具体的C编译器实现。这个特殊情况就是常数0,编译器保证由0转换而来的指针不等于任何有效的指针。

出于代码文档化的考虑,常数0这个值经常用一个符号来代替:#define NULL 0

当然无论是直接用常数0,还是用符号ULL,效果都是相同的。

需要记住的重要一点是,当常数0被转换为指针使用时,这个指针绝对不能被解除引用(dereference)。换句话说,当我们将0赋值给一个指针变量时,绝对不能企图使用该指针所指向的内存中存储的内容。

合法格式:

if(p == (char *) 0)

非法格式:

if(strcmp(p,(char*)0) == 0)

原因在于库函数 strcmp 的实现中会包括查看它的指针参数所指向内存中的内容的操作。

六、边界计算与不对称计算

七、求职顺序

八、逻辑运算符&&、| 和 !

九、整数溢出

C语言中存在两类整数算术运算,有符号运算与无符号运算。

1、两个无符号算术运算中,没有所谓的“溢出”一说:所有的无符号运算都是以2的n次方为模,这里n是结果中的位数。

2、一个操作数是有符号整数,另一个是无符号整数,那么有符号整数会被转换为无符号整数,“溢出”也不可能发生。

3、当两个操作数都是有符号整数时,“溢出”就有可能发生,而且“溢出”的结果是术定义的。当一个运算的结果发生“溢出”时,作出任何假设都是不安全的。

正确的方式是将a和b都强制转换为无符号整数:

if ((unsigned)a + (unsigned)b > INT_MAX)
		complain();

此处的 INT_MAX是一个已定义常量,代表可能的最大整数值。ANSIC标准在<limits.h>中定义了INTMAX:如果是在其他C语言实现上,读者也许需要自己重新定义。

//不需要用到无符号算术运算的另一种可行方法是:
if(a >INT_MAX - b)
    complain();

十、为函数main提供返回值

函数 main 与其他任何函数一样,如果并未显式声明返回类型,那么函数返回类型就默认为是整型。但是这个程序中并没有给出任何返回值。

通常说来,这不会造成什么危害。一个返回值为整型的函数如果返回失败,实际上是隐含地返回了某个“垃圾”整数。只要该数值不被用到,就无关紧要。

严格说来,我们前面的最简单的C程序应该像下面这样编写代码:

int main()
{
	//语句

	return 0;
}

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

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

相关文章

杨辉三角(C语言)

杨辉三角 一.什么是杨辉三角 一.什么是杨辉三角 每个数等于它上方两数之和。 每行数字左右对称&#xff0c;由1开始逐渐变大。 第n行的数字有n项。 前n行共[(1n)n]/2 个数。 … 当前行的数上一行的数上一行的前一列的数 void yanghuisanjian(int arr[][20], int n) {for (int i…

3.9Code

基于顺序存储结构的图书信息表的图书去重 #include<iostream> #include<stdlib.h> #include<string.h>typedef int status;#define OK 1using namespace std;typedef struct{char no[50];char name[50];float price; }Book;typedef struct{Book* elem;int …

Linux 学习(持续更新。。。)

wc命令 命令直接执行&#xff0c;输出包含四项&#xff0c;分别代表&#xff1a;行数、字数、字节数、文件。 例子:编译下列代码: #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include <fcntl.h> #inclu…

七、软考-系统架构设计师笔记-数据库设计基础知识

1、数据库基础概念 数据库基本概念 数据(Data)数据库(Database)数据库管理系统(DBMS)数据库系统(DBS) 1.数据(Data) 是数据库中存储的基本对象&#xff0c;是描述事物的符号记录。 数据的种类&#xff1a; 文本、图形、图像、音频、视频等。 2.数据库(Database, DB) 数据库…

JavaScript代码混淆与防格式化功能详解

在前端开发中&#xff0c;为了增加代码的安全性&#xff0c;防止恶意分析和逆向工程&#xff0c;有时候会采用一些防格式化的技术。这些技术主要通过混淆和难以阅读的方式来防止代码的易读性&#xff0c;提高代码的复杂度&#xff0c;增加攻击者分析的难度。 1. 代码压缩与混淆…

docker 使用官方镜像搭建 PHP 环境

一、所需环境&#xff1a; 1、PHP&#xff1a;7.4.33-fpm 的版本 2、Nginx&#xff1a;1.25.1 的版本 3、MySQL&#xff1a; 5.7 的版本 4、Redis&#xff1a;7.0 的版本 1.1、拉取官方的镜像 docker pull php:7.4.33-fpm docker pull nginx:1.25.1 docker pull mysql:5.7 do…

Character类

Character类 功能&#xff1a;实现了对 基本型数据的类包装。 构造方法&#xff1a; (char c) 常用方法&#xff1a; • public static boolean (char ch)//ch是数字字符返回true。 • public static boolean (char ch)//ch是字母返回 true。 • public static char (char c…

商家转账到零钱申请失败怎么办

商家转账到零钱是什么&#xff1f; 商家转账到零钱是微信商户号里的一个功能&#xff0c;以前叫做企业付款到零钱。从 2022 年 5 月 18 日开始&#xff0c;原企业付款到零钱升级为商家转账到零钱&#xff0c;已开通商户的功能使用不受影响&#xff0c;新开通商户可前往产品中心…

简介:图灵机和图灵测试

一、图灵机&#xff08;Turing machine&#xff09; 图灵机&#xff08;Turing machine&#xff09;是由英国数学家Alan Turing于1936年提出的一种抽象计算模型&#xff0c;阿兰图灵在24岁时发表论文《On Computable Numbers, with an Application to the Entscheidungsproble…

指针总结及例题总结

1 定义 指针是用来存放地址的变量 不同类型的指针变量所占用的存储空间是相同的&#xff0c;sizeof(int)sizeof(char)sizeof(double)... *是解引用操作符&#xff0c;&是取地址操作符&#xff0c;两者有着抵消作用 int a20;int* p&a;*p*&a20; 2&#xff0c;…

windows更改账户名

win R输入netplwiz 点击用户名进去&#xff0c; 修改用户名之后重启即可。

echarts 模拟时间轴播放效果

使用echarts柱状图模拟时间轴播放控制。开始/暂停/快进/慢进/点选 代码可直接放echart官方示例执行 let start new Date(2024-01-01); let end new Date(2024-01-10); let diff end - start; let dotLen 200;let data [start, end]; option {color: [#3398DB],tooltip: …

【笔记】Android ServiceStateTracker 网络状态变化逻辑及SPN更新影响

业务简介 在网络状态变化的时候&#xff08;数据或WiFi&#xff09;&#xff0c;会更新SPN。 基于Android U的代码分析。 分类&#xff1a;SPN Data_Dic-的博客-CSDN博客 功能逻辑 状态说明 飞行模式下注册上WFC的话&#xff0c;注册状态MD上报 regState: NOT_REG_MT_NOT…

Igraph入门指南 4

二、图的创建 图分有向图和无向图&#xff0c;所以图的创建有各自的实现方式。 1、手工创建图&#xff1a; 1-1 通过文本创建&#xff1a;graph_from_literal 通过每项提供两个顶点名&#xff08;或ID号&#xff09;作为一条边的格式&#xff0c;手动创建图&#xff0c;顶点…

RocketMQ-存储与弹性伸缩

存储与弹性伸缩 一、介绍二、存储架构图1.CommitLog2.ConsumeQueue3.IndexFile 三、消息读写流程1.写入流程1.1 获取Topic元数据1.2 消息投递1.3 消息写入 2.读取流程2.1 获取Topic元数据2.2 消息拉取2.3 消息消费 四、消息持久化1.页缓存2.刷盘2.1 同步刷盘2.2 异步刷盘 五、集…

力扣199. 二叉树的右视图(DFS,BFS)

Problem: 199. 二叉树的右视图 文章目录 题目描述思路解题方法复杂度Code 题目描述 思路 无论是DFS还是BFS我们都要思考到达二叉树的每一层&#xff08;或者每一层中的每一个节点&#xff09;时&#xff0c;我们都该如何按题目要求做出对应得处理!!!在本体中我们主要是&#x…

为什么不用 index 做 key?

“在 Vue 中&#xff0c;我们在使用 v-for 渲染列表的时候&#xff0c;为什么要绑定一个 key&#xff1f;能不能用 index 做 key&#xff1f;” 在聊这个问题之前我们还得需要知道 Vue 是如何操作 DOM 结构的。 虚拟DOM 我们知道&#xff0c;Vue 不可以直接操作 DOM 结构&am…

使用docker部署redis集群

编写脚本 批量创建目录文件&#xff0c;编写配置文件 [rootlocalhost ~]# cat redis.sh #/bin/bash for port in $(seq 1 6); do mkdir -p /mydata/redis/node-${port}/conf touch /mydata/redis/node-${port}/conf/redis.conf cat << EOF >>/mydata/redis/node-…

吴恩达deeplearning.ai:倾斜数据集的误差指标精确率、召回率

以下内容有任何不理解可以翻看我之前的博客哦&#xff1a;吴恩达deeplearning.ai专栏 文章目录 倾斜数据集的误差指标罕见病预测精确率和召回率 精确率和召回率的权衡精确率和召回率的矛盾关系 F1算法 倾斜数据集的误差指标 在神经网络中&#xff0c;如果你的数据集中正例和负…

吉林大学 容斥原理 章节作业

作业题填空题解答题 作业题 填空题 聚会上&#xff0c;5位先生各自寄存自己的帽子。在返还时&#xff0c;有( )种方法使得至少有一位先生拿到的是自己原来的帽子。 【答案】76 计算多重集 S { 4 ⋅ a , 3 ⋅ b , 4 ⋅ c , 6 ⋅ d } S\{4 \cdot a, 3 \cdot b, 4 \cdot c, …