《C专家编程》一1.6 它很棒,但它符合标准吗

本文涉及的产品
全球加速 GA,每月750个小时 15CU
简介:

本节书摘来自异步社区《C专家编程》一书中的第1章,第1.6节,作者 【美】Perter Van Der Linde,更多章节内容可以访问云栖社区“异步社区”公众号查看

1.6 它很棒,但它符合标准吗

不要添乱——立即解散ISO工作小组。

——匿名人士

ANSI C标准可以说是非常独特的,我们可以从好几个有趣的方面来说明这一点。它定义了下面一些术语,用于描述某种编译器的特点。如果你对这些术语有一个比较好的了解,就有助于你理解什么东西能被语言接受,什么东西不能被语言接受。前两个术语涉及不可移植的代码(unportable code),接下来的两个术语跟坏代码(bad code)有关,而最后两个术语则跟可移植的代码(portable code)有关。

不可移植的代码(unportable code):

由编译器定义的(implementation-defined)——由编译器设计者决定采取何种行动(就是说,在不同的编译器中所采取的行为可能并不相同,但它们都是正确的),并作好文档记录。

例如:当整型数向右移位时,要不要扩展符号位。

未确定的(unspecified)——在某些正确情况下的做法,标准并未明确规定应该怎样做。

例如:参数求值的顺序。

坏代码(bad code):

未定义的(undefined)——在某些不正确情况下的做法,但标准并未规定应该怎样做。你可以采取任何行动,可以什么也不做,也可以发出一条警告信息,或者可以中止程序以及让CPU陷入瘫痪,甚至可以发射核导弹(只要你安装了能发射核弹的硬件系统)。

例如:当一个有符号整数溢出时该采取什么行动。

约束条件(a constraint)——这是一个必须遵守的限制或要求。如果你不遵守,那么你的程序的行为就会变成像上面所说的属于未定义的。这就出现了一种很有意思的情况:分辨某种东西是否是一个约束条件是很容易的,因为标准的每个主题都附有一个“约束(constraint)”小节,列出了所有的约束条件。现在又出现了一个更为有趣的情况:标准规定[5]编译器只有在违反语法规则和约束条件的情况下才能产生错误信息!这意味着所有不属于约束条件的语义规则你都可以不遵循,而且由于这种行为属于未定义行为,编译器可以采取任何行动,甚至不必通知你!

例如:%操作符的操作数必须属于整型。所以,在非整数数据上使用%操作符肯定会引发一条错误信息。

不属于约束条件规则的例子:所有在C语言标准头文件中声明的标识符均保留,所以不能声明一个叫作malloc()的函数,因为在标准头文件里已经有一个函数以此为名。但由于这个规定不是约束条件,因此可以违反它,而且编译器甚至可以不警告你!关于“interpositioning”这一小节的更多内容,参见第5章。


1744f65d1127c9e86d0fa3cfd9afc8ba33245468

未定义的行为在IBM PC中引起CPU瘫痪!

未定义的软件行为引起CPU瘫痪的说法并不像它乍听上去那样牵强。

IBM PC的显示器以显示控制芯片所提供的水平扫描速率工作。回扫变压器(flyback transformer,一种产生高电压的装置,用于加速电子以点亮显示器上的荧光物质)需要保持一个合理的频率。

然而在软件中,程序员有可能把视频芯片的扫描速率设置成零,这样就会产生一个恒定的电压输出到回归变压器的输入端。这就使它起了电阻器的作用,只是把电能转换成热能,而不是传送到屏幕。这会在数秒之内就把显示器烧毁,那就是未定义的软件行为会导致系统瘫痪的理由。
可移植的代码(portable code):

严格遵循标准的(strictly-conforming)—— 一个严格遵循标准的程序应该是:

只使用已确定的特性。

不突破任何由编译器实现的限制。

不产生任何依赖由编译器定义的或未确定的或未定义的特性的输出。

这样规定的主要目的就是最大限度地保证可移植性。这样,不论你在什么平台上运行严格遵循标准的程序都会产生相同的输出。事实上,在所有遵循标准的程序中,属于这一类的程序并不多。例如,下面这个程序就不是严格遵循标准的:

#include <limits.h>
#include <stdio.h>
int main() { (void)printf("biggest int is %d", INT_MAX); return 0;}

/*并不严格遵循标准:其输出结果是由编译器定义的。*/

在本书的剩余部分,我们通常并不强求例子程序严格遵循标准。因为如果这样做会使文本看上去比较乱,而且不利于理解所讨论的要点。程序的可移植性是非常重要的,所以在你的现实编码中,应该始终要保证加上必要的类型转换、返回值等。

遵循标准的(conforming)——一个遵循标准的程序可以依赖一些某种编译器特有的不可移植的特性。所以,一个程序有可能在一个特定的编译器里是遵循标准的,但在另一个编译器里却是不遵循标准的。它可以进行扩展,但这些扩展不能修改严格遵循标准的程序的行为。但是,这个规则并不是一个约束条件,所以对于你的程序中不遵循标准之处,你不要指望编译器会给出一条警告信息指出你违反了规定!

上面所举的几个程序实例都是遵循标准的。

相关文章
|
4月前
|
存储 Java 开发工具
探索安卓应用开发:从新手到专家的旅程
【8月更文挑战第30天】在数字时代,掌握安卓应用开发的技能不仅是职业发展的利器,也是个人技术成长的象征。本文将带你了解如何从零基础开始,逐步深入安卓开发的奥秘,最终成为一名能够独立开发高质量应用的专家。通过实际的代码示例和清晰的步骤指导,我们将一起构建你的第一个安卓应用程序,并探讨如何提升至更高水平。无论你是编程新手还是希望提高现有技能的开发者,这篇文章都将为你提供宝贵的知识和启发。
|
4月前
|
机器学习/深度学习 前端开发 程序员
探索编程之道:从小白到专家的旅程
【8月更文挑战第29天】本文将引导读者踏上一段从编程新手到资深开发者的旅程。我们将通过一个实际的项目案例,探讨如何从零开始学习编程,逐步掌握关键技能,并最终成长为一名能够独立解决复杂问题的专家。在这个过程中,我们将分享实用的学习资源、策略和心态调整方法,帮助读者在编程之路上不断前进。
|
4月前
|
存储 Java Android开发
探索安卓应用开发:从初学者到专家的旅程
【8月更文挑战第24天】在这篇文章中,我们将一起踏上一段激动人心的旅程,从零基础开始,逐步深入到安卓应用开发的世界。通过简单易懂的语言和实际的代码示例,我们将解锁创建精美安卓应用的秘密。无论你是编程新手还是希望提升现有技能的开发者,这篇文章都将为你提供宝贵的知识和灵感。让我们一起构建你的第一个安卓应用吧!
|
1月前
|
存储 Java 数据处理
探索安卓开发:从新手到专家的旅程
【10月更文挑战第42天】在这篇文章中,我们将一起踏上一段激动人心的旅程,从安卓开发的基础知识开始,逐步深入到高级概念。我们将通过实际的代码示例和清晰的解释,帮助你理解安卓开发的核心原理,并学会如何构建你自己的应用程序。无论你是刚刚入门的新手,还是已经有一定经验的开发者,这篇文章都将为你提供有价值的见解和技巧。让我们一起开始吧!
|
1月前
|
存储 JavaScript Java
后端开发的艺术:从新手到专家的旅程
在数字化时代,后端开发是构建现代应用程序不可或缺的一部分。本文将探讨后端开发的核心概念、技术栈选择、最佳实践以及如何从初学者成长为专家。我们将通过一系列实用的建议和策略,帮助读者理解并掌握后端开发的精髓,从而在这个充满挑战和机遇的领域中取得成功。
|
2月前
|
测试技术 持续交付 开发者
编程之道:开发者的自我提升之旅
在软件开发的世界里,每位开发者都是用代码绘出数字化画卷的艺术家。本文从技术深度与广度的平衡、代码的简洁之美、持续集成与部署、代码审查、测试驱动开发、有效沟通、时间管理和面对失败的勇气等八个方面,分享了职业心得,帮助开发者在技术和心灵上共同提升,勇敢面对每一次挑战,在编程之路上不断前行。
|
4月前
|
人工智能 JavaScript Java
深入浅出后端开发:从新手到专家的旅程
在数字时代的浪潮中,后端开发如同宇宙中的暗物质,虽不为人所见,却支撑着整个互联网的运行。本文将带你探索后端开发的奥秘,从基础概念到技术栈选择,再到实战应用,我们将一起构建知识的桥梁,连接起初学者与资深开发者之间的鸿沟。你将了解到,如何通过不断学习和实践,像乔布斯所预见的那样,让生命中的每一个点在未来某个时刻连接起来,最终成为你希望在世界上看到的改变。
|
4月前
|
数据采集 小程序 数据挖掘
探索代码之美:从初学者到专家的技术成长之旅
编程,一门将创意与逻辑结合的艺术,其学习过程充满了挑战与发现。本文通过个人经历,探讨了如何从一个对代码一无所知的初学者成长为一个能够熟练解决问题的专家。文章不仅分享了学习编程的实用技巧和策略,还讨论了在技术成长过程中保持动力和持续学习的重要性。
38 1
|
4月前
|
自然语言处理 算法 搜索推荐
探索代码之美:从小白到专家的编程之旅
【8月更文挑战第30天】在数字时代的浪潮中,编程已成为一门艺术和科学。本文将通过个人的技术感悟,带领读者走进编程世界的大门,从基础语法到复杂算法,从单一语言到多语言融合,我们将一探究竟。文章不仅分享编程技巧和经验,还将探讨如何培养解决问题的能力,以及如何保持学习的热情和动力。无论你是编程新手还是有经验的开发者,这篇文章都将为你提供新的视角和启发。
|
5月前
|
敏捷开发 安全 程序员
编码之旅:从初学者到专家的蜕变
【7月更文挑战第29天】在编程的世界里,每一个代码块都是探险者手中的指南针。本文将带你踏上一场从零开始的编程旅程,探索如何通过实践、学习与反思,逐步解锁编程的奥秘。我们将一起经历从基础语法的学习到复杂项目的管理,从错误中汲取经验,直至成长为能够独立解决难题的编程专家。这不仅仅是技术的成长,更是逻辑思维和解决问题能力的飞跃。
下一篇
DataWorks