C陷阱与缺陷——第3章 语义陷阱

1. 指针和数组

C语言中只有一维数组,而且数组的大小必须在编译器就作为一个常数确定下来,然而在C语言中数组的元素可以是任何类型的对象,当然也可以是另外的一个数组,这样,要仿真出一个多维数组就不是难事。

对于一个数组,我们只能够做两件事:确定数组大小;获得指向该数组下标为0的元素的指针。

int calendar[12][31];

以上语句声明了calendar是一个数组,该数组拥有12个数组类型的元素,其中每个元素都是一个拥有31个整型元素的数组。

如果calendar不是用于sizeof的操作数,那么calendar总是被转换成一个指向calnedar数组的起始元素的指针。

任何指针都是指向某种类型的变量。

给一个指针加上一个整数,与给该指针的二进制表示加上同样的整数,两者的含义截然不同。

把两个指针相减也是有意义的,但是这两个指针必须指向同类型的变量,否则结果未定义。

当p是int指针,a是int一维数组名时,以下写法正确

p = a;

以下写法错误:

p = &a;

因为&a是一个指向数组的指针,而p是一个指向整型变量的指针。*a是数组a中下标为0的元素的引用。*(a+i)即数组a中下标为i的元素的引用,简记为a[i]。多数情况下i[a]和a[i]的意义相同,但是不推荐使用前面的写法。

calendar[4]是calendar数组的第5个元素,calendar[4]的行为表现为一个有着31个整型元素的数组的行为。

声明指向数组的指针的方法,举例如下:

int calendar[12][31];
int (*monthp)[31];
monthp = calendar;

2. 非数组的指针

假设我们用两个字符串s和t,我们希望将这两个字符串连接成单个字符串r,借助库函数strcpy和strcat正确写法如下:

char *r, *malloc();//声明malloc原型,这样后面就不用再写转换成char*类型了
r = malloc(strlen(s) + strlen(t) + 1); //字符串结尾为'\0',strlen不用加上这个计数1
if (!r)//当malloc无法完成内存分配时,会返回NULL
{complain();//报错exit(1);//退出
}
strcpy(r, s);
strcpy(r, t);//使用一段时间后free(r); //对动态分配内存程序员负责回收

主要注意到点是:

  • 字符串以空字符'\0'作为结束标志,库函数strlen返回参数中字符串所包含的字符数组,而结尾标志的空字符并未计算在内;
  • malloc函数有可能无法提供请求的内存,这种情况malloc函数通过返回一个空指针来作为“内存分配失败”事件的信号
  • malloc分配的内存使用完后应该及时释放,否则会导致内存泄露

3. 作为参数的数组声明

C语言中会自动地将作为参数的数组声明转换为相应的指针声明,也就是说下面两种写法完全等价

int strlen(char s[])
{}
int strlen(char* s)
{}

但是需要注意的是,在其他情况下这两者并不会等价,如

extern char* hello;
extern char hello[];

4. 注意整体代替部分的错误

指针的赋值并不会复制它们指向的内容,因此如下语句

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

的结果如下:

5. 空指针并非空字符串

当常数0被转换成指针使用时,这个指针绝对不能不能被解除引用dereference

if (p == (char *) 0)...

以上写法正确,因为没有解除引用

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

以上写法错误,因为strcmp会查看指针所指向内存的内容

同样以下写法也是错误的:

int *p = NULL;
printf(p);
printf("%s", p);

6. 边界计算与不对称边界

如果一个数组有10个元素,那么这个数组下标的允许范围是0-9

在多数C语言实现中,--n >= 0至少和n-->0一样快

可以用

if (bufptr == &buffer[N])

代替

if (bufptr > &buffer[N - 1])

数组中实际不存在的溢界元素的地址位于数组所占内存之后,这个地址可以用于进行赋值和比较。但不允许进行解引用。

7. 求值顺序

C语言中只有4个运算符(&&、||、?:和,)存在规定的求值顺序:

  • &&和||首先对左侧操作数求值,只有在需要时才对右侧操作数求值
  • a?b:c有三个操作数,操作数a首先被求值,根据a的值再求b或者c
  • 逗号运算符,首先对左侧操作数求值,然后丢弃该值,再对右侧操作数求值

注意:分隔函数参数的逗号并非逗号运算符,例如f(x,y)中求值顺序顺序是未定义的,而在g((x,y))中先求x的值,然后求y的值。

C语言中其他所有运算符对其操作数求值的顺序是未定义的,特别地,赋值运算符并不保证任何求值顺序。

比如,从数组x中复制前n个元素到数组y中,以下做法是不对的:

i = 0;
while(i < n)y[i] = x[i++];

因为这里假设y[i]的地址i在自增操作前执行前被求值

正确的做法是:

i = 0;
while(i < n)
{y[i] = x[i];i++;
}

 8. 运算符&&、||和!和按位运算符&、|、~

按位运算符&、|、~对操作数的处理方式是将其视作一个二进制位序列,分别对其每个位进行操作。

逻辑运算符&&、||和!对操作数的处理方式是将其视作要么是真,要么是假,通常将0视为假,而非0视作真。

9. 整数溢出

当两个操作数都是有符号整数时,溢出有可能发生,而且溢出的结果是未定义的。

例如a和b是两个非负整型变量,我们需要检查a+b是否会溢出,以下的写法是错误的:

if (a + b < 0)complain();

正确的写法是将a和b都强制转换成无符号整数:

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

也可以使用以下写法:

if (a > INT_MAX -b)complain();

10. 为函数main提供返回值

大多数C语言实现都通过main的返回值来告知操作系统该函数执行是成功还是失败,典型的处理方式是返回值0表示程序执行成功,返回值非0表示程序执行失败。

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

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

相关文章

Mac电脑版程序创建工具 VMware InstallBuilder Enterprise mac最新

VMware InstallBuilder Enterprise 是一款功能强大、操作简单、跨平台支持的软件安装和部署工具&#xff0c;可以让开发者更加高效地创建和部署软件&#xff0c;并提供了丰富的功能和工具&#xff0c;适用于不同的用户需求和场景。 内置调试器 轻松排除应用程序安装过程中的故…

样品实验EPONEX1510氢化双酚A环氧树脂TDS说明书

样品实验EPONEX1510氢化双酚A环氧树脂TDS说明书 200克 500克 1KG/瓶

使用Docker安装Jenkins,解决插件安装失败,版本太低等问题

如果已经遇到插件安装部分失败&#xff0c;Jenkins版本太低&#xff0c;又要换什么清华镜像地址&#xff0c;不要犹豫&#xff0c;直接以下步骤卸载重装就好了 开始安装 yum 更新到最新 yum update到Jenkins官网查找最新的LST版本 最后的版本号一定要带&#xff0c;指定下载具…

深入探索Maven:优雅构建Java项目的新方式(二)

Meven高级 1&#xff0c;属性1.1 属性1.1.1 问题分析1.1.2 解决步骤步骤1:父工程中定义属性步骤2:修改依赖的version 1.2 配置文件加载属性步骤1:父工程定义属性步骤2:jdbc.properties文件中引用属性步骤3:设置maven过滤文件范围步骤4:测试是否生效 1.3 版本管理 2&#xff0c;…

Sass 安装

文章目录 前言SASS的系统要求安装Ruby例子后言 前言 hello world欢迎来到前端的新世界 &#x1f61c;当前文章系列专栏&#xff1a;Sass和Less &#x1f431;‍&#x1f453;博主在前端领域还有很多知识和技术需要掌握&#xff0c;正在不断努力填补技术短板。(如果出现错误&…

Informer辅助笔记:data/dataloader.py

以WTH为例 import os import numpy as np import pandas as pdimport torch from torch.utils.data import Dataset, DataLoader # from sklearn.preprocessing import StandardScalerfrom utils.tools import StandardScaler from utils.timefeatures import time_featuresim…

什么是光模块光模块看我这张就够啦!

1、什么是光模块 信号在光网络中传输时&#xff0c;必须进行光/电转换。光模块就是专门在光网络中完成光/电转换工作的部件。光模块的外观结构如图1所示&#xff0c;简单的来说&#xff0c;双绞线最大传输距离是100米&#xff0c;用的是电信号&#xff0c;那如果说传输距离超过…

骨传导能保护听力吗?使用骨传导有没有副作用?

先说结论&#xff0c;骨传导耳机是可以保护听力的&#xff0c;如果是正常的使用骨传导耳机&#xff0c;是不会有任何副作用的。 一、为什么说骨传导耳机能保护听力 1、佩戴方式更健康 由于骨传导耳机采用耳挂式佩戴&#xff0c;在使用的时候开放双耳&#xff0c;不会堵塞耳道…

如何使用vs2022通过excel.exe生成VC、C++能够使用的头文件

我们在开发MFC、VC、C项目时&#xff0c;有时候需要操作excel文件的读写&#xff0c;我们一般常用方式是调用微软的excel驱动方式调用&#xff0c;但调用驱动前&#xff0c;我们需要生成我们C能够调用到的头文件&#xff0c;一般常用文件有&#xff1a; #include "CAppli…

GPT-4 惨遭削弱;拼多多市值一度超阿里;雷军回应个人向武汉大学捐款 13 亿元丨 RTE 开发者日报 Vol.96

开发者朋友们大家好&#xff1a; 这里是 「RTE 开发者日报」 &#xff0c;每天和大家一起看新闻、聊八卦。我们的社区编辑团队会整理分享 RTE &#xff08;Real Time Engagement&#xff09; 领域内「有话题的 新闻 」、「有态度的 观点 」、「有意思的 数据 」、「有…

卷轴模式:金融领域的新趋势

卷轴模式在金融领域逐渐崭露头角&#xff0c;成为一种新型的投资策略。这种模式基于完成任务或达成特定目标来获取积分&#xff0c;利用这些积分进行投资或获取现实物品。它不同于传统的资金盘&#xff0c;而是以一种更稳健的方式运作&#xff0c;避免了资金盘的风险。 一、卷轴…

智能优化算法应用:基于帝国主义竞争算法无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用&#xff1a;基于帝国主义竞争算法无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用&#xff1a;基于帝国主义竞争算法无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.帝国主义竞争算法4.实验参数设定5.算…

供应商关系管理软件:如何使用它来改善供应商关系?

从最基本的角度来说&#xff0c;企业需要供应商为其生产和销售的产品或服务提供原材料&#xff0c;或者为其提供资源和服务来经营自己的业务。 建立稳定而健康的供应商关系的最大优势之一&#xff0c;就是可以为企业带来更高的价值。企业对供应商了解越多&#xff0c;供应商对…

富必达API:一站式无代码开发集成电商平台、CRM和营销系统

一站式无代码开发的连接解决方案 电子商务、客户服务系统以及其它商业应用&#xff0c;是现代企业运营的重要部分。然而&#xff0c;将这些系统进行有效的整合往往需要复杂的API开发&#xff0c;这对很多企业来说是一个巨大的挑战。富必达API以其一站式的无代码开发解决方案&a…

Java小游戏 王者荣耀(简易版)

GameFrame类 所需图片&#xff1a; package 王者荣耀;import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyAdapter; import java.awt.event.KeyEvent; import java.io.File; import java.util.ArrayList…

亚信科技AntDB数据库完成中国信通院数据库迁移工具专项测试

近日&#xff0c;在中国信通院“可信数据库”数据库迁移工具专项测试中&#xff0c;湖南亚信安慧科技有限公司&#xff08;简称&#xff1a;亚信安慧科技&#xff09;数据库数据同步平台V2.1产品依据《数据库迁移工具能力要求》、结合亚信科技AntDB分布式关系型数据库产品&…

AI伪原创软件-AI伪原创工具下载

在当今数字化时代&#xff0c;创作者们在追求独特创意的同时&#xff0c;也面临着时间和灵感的双重挑战。AI伪原创技术应运而生&#xff0c;为创作者提供了一种快捷而便利的解决方案。本文将专心分享两款备受瞩目的AI伪原创工具&#xff0c;147SEO伪原创、百度文心一言伪原创&a…

赴日开发做什么?日本签证很难拿?

日本的IT行业历史比较悠久&#xff0c;业务以上层前端业务为主&#xff0c;如设计和构建软件。日本IT公司组织庞大&#xff0c;行业内部有着严格的分工和部署&#xff0c;工作会被细分化。分配给个人的工作量不会太大&#xff0c;难度也不会很高。 在日本IT公司就业&#xff0…

分油问题C++求解

原题 3个油桶&#xff0c;容量分别为&#xff08;大桶&#xff09;20&#xff0c;&#xff08;中桶&#xff09;9&#xff0c;&#xff08;小桶&#xff09;7&#xff0c;初始时大桶满油&#xff0c;如何操作可以分出17的油&#xff1f; 代码 #include<iostream> #inc…

使用VScode通过内网穿透在公网环境下远程连接进行开发

文章目录 前言1、安装OpenSSH2、vscode配置ssh3. 局域网测试连接远程服务器4. 公网远程连接4.1 ubuntu安装cpolar内网穿透4.2 创建隧道映射4.3 测试公网远程连接 5. 配置固定TCP端口地址5.1 保留一个固定TCP端口地址5.2 配置固定TCP端口地址5.3 测试固定公网地址远程 前言 远程…