首页 >>  正文

c语言基本结构图

来源:baiyundou.net   日期:2024-09-23

【CSDN 编者按】在研发过程中,编程语言的优劣对应用程序的性能有着巨大的影响。近些年间,随着应用程序规模的扩大,越来越多的公司开始关注其安全性能,如 Google、微软、亚马逊等科技巨头纷纷开始推荐 Rust 这类为安全而生的语言,欲取代过往的 C/C++,甚至美国国家安全局也于不久之前发布建议:弃用 C/C++,使用更安全的 Rust、C# 等!

不过,在本文作者、也是一位软件开发者、计算系统设计师看来,Rust、C++ 都没有 C 香,以下他列出了 7 大理由!

原文链接:https://gavinhoward.com/2023/02/why-i-use-c-when-i-believe-in-memory-safety/

声明:本文为 CSDN 翻译,未经允许,禁止转载。

作者 | Gavin Daniel Howard

译者 | 弯月 责编 | 屠敏

出品 | CSDN(ID:CSDNnews)

最近,美国国家安全局发布了一些关于软件内存安全的建议(https://media.defense.gov/2022/Nov/10/2003112742/-1/-1/0/CSI_SOFTWARE_MEMORY_SAFETY.PDF):

其鼓励多个组织将编程语言从 C/C++ 转为使用内存安全的语言,如 C#、Rust、Go、Java、Ruby 和 Swift,主要原因是这样可以帮助软件开发者和使用者预防并缓解软件内存安全问题,这些问题占可利用漏洞的很大一部分。

这份文档引起了很大骚动。其实,这些都是常识性建议,如非有充分的理由,我们都应该遵循这些建议。

不过,C++ 之父 Bjarne Stroustrup 认为 C++ 并没有那么糟,他表示美国国家安全局忽略了 C/C++ 三十多年来的进步。

Bjarne Stroustrup 还说:

“例如,Microsoft Visual Studio 分析器和内存安全评测器已能提供大部分的 CG 支持,而现在任何优秀的静态分析器(例如 Clang tidy 就提供了部分 CG 支持)都可以设置为提供这样的保证……”

但我非常不赞同这个观点。事实上,我认为 C++ 的复杂性使其比 C 更糟。

美国国家安全局人员 Jimmy Hartzel 如此评价,我非常同意他的看法:

“就内存安全而言,‘大部分’是完全不够的,而‘可以设置为’实际上也没有价值。从根本上来看,关键的一点是 C++ 的内存安全仍在积极开发中,已经很接近其他的语言了。同时,Rust(和 Swift、C#、Java 等)已经实现了内存安全。”

虽然我不太喜欢 Rust,但不可否认的是,Rust 是当前 C 或 C++ 程序员的最佳选择。

然而,我的当前项目仍然是用 C 语言编写的。

为什么我这么喜欢 C 语言?理由如下。

文档

第一个理由是,我可以记录一切。

从很多方面来说,Rust 很棒,而且该语言本身也很擅长提供代码的文档。

例如,对于显式指针类型,很容易看出如何正确使用函数的参数。

C 只有值和指针类型。指针可以动态分配或指向祖先栈中的某些元素。但也可以是完全不相关的东西。

Rust 具有更好的类型安全。你给 C void*,它会欣欣然接受这个有可能指向任何东西的指针。

客观地说,从这些方面来看,Rust 的表现更好。

我通过各种方式来写文档:

记录所有能想到的假设,而且通常是在代码中利用断言来记录。

记录每个函数及其参数和用途。

记录每个结构、每个字段、每个枚举。

我还写了很多设计文档和开发文档。

如此一来,我不仅享受到了 Rust 的许多优点,而且还有很好的文档,这对我的用户来说无疑是一件好事。

我并不是说 Rust 更好,只不过这样可以迫使我编写文档。

单独工作

其次,我需要独自将脑海中的想法变成代码。

Rust 非常适合团队,因为它消除了许多团队合作编写代码时的风险因素。

然而,我是单独工作,因为我喜欢把代码记在脑子里,与他人一起工作则意味着部分代码只在他们的脑子里。

这也意味着,语言越大,我脑子里留给代码的空间就越少。

不幸的是, 对于我的小脑袋来说,Rust 太大了。

我觉得 Rust 不够有趣

这引出了下一个原因:我不喜欢 Rust。

注意,这纯粹是个人喜好, 我并不是说 Rust 不好。

我使用过很多语言编写代码:

C

C++

Rust

Haskell

Go

Python

PHP

Ruby

Zig

Bash

POSIX sh

bc

dc

JavaScript

Clojure

Java

C#

Various assembly languages

GLSL

Common Lisp

Racket

Julia

Tcl

Vim script

此外,我还研究过以下语言:

ML

OCaml

HAL/S

Pascal

Objective-C

MATLAB

Modula-2

Coq

Isabelle/HOL

Ada/SPARK

等等。

若论编程的乐趣,我讨厌所有这些语言。除了 C 语言。

没错,C 是唯一我真正喜欢的编程语言。

我不是在说笑,相较于其他语言,我用 C 编写代码的效率高出几个数量级。我的脑子只适合用 C 思考,我也不知道为什么。

这对我来说非常重要。根据以往的经验,我是一个很容易情绪化的程序员,如果周遭的环境不合适,我就无法有效地编程。

如果累了,我就无法有效地编程。

如果一边写代码一边听音乐,我也无法有效地编程。

如果被一项任务压得喘不过气来,我就无法有效地编程。

如果无法想象整个软件,我就无法有效地编程。

如果老婆跟我闹脾气,我就无法有效地编程。

最后,我无法使用不喜欢的语言进行有效的编程。

我曾经拒绝过一份工作邀请,因为他们使用的是 C++,而我讨厌 C++。

所以我不使用 Rust 或其他内存安全语言,因为我已经尝试过,但我无法使用这些语言有效地编程。

我知道这是个人问题,跟 Rust 无关。

但是,我很擅长 C 语言,虽然并不完美。

自律

这引出了我的下一个原因:我很自律,而且能通过这种能力编写高水平的 C 代码。

我的自律可以通过多种形式表现出来:

我只使用无符号整数,以此避免未定义的行为。我甚至会使用无符号整数模拟有符号的二补数。

如果我编写的函数的返回值没有被使用,我会使用一个宏让 Clang 报错。

我使用 -Wall、-pedantic 和 -Werror 来运行 Clang 和 GCC。 这意味着,我在开发的阶段就消除了警告。

我甚至用 -Weverything 运行 Clang,除了 -Wpadded,因为我不关心结构中的填充(我会仔细安排它们的布局);还有-Wc++98-compat,因为我不关心 C++ 98 兼容性 ,因为它与 C11 stdalign.h 相互干扰。

我会在测试套件中运行健全性测试,并消除一切错误。是的,一切,甚至是误报。

我会在测试套件中运行 Valgrind,并消除一切错误。

我会在测试套件中运行 Helgrind ,并消除一切错误,甚至是误报。

我会运行静态分析,并消除一切错误,甚至是误报。

你不了解一次又一次地运行 Valgrind、Clang、ASan 或 TSan,一次又一次地消灭 bug,最后什么都不剩下的感觉有多么好。

我感到无比的幸福和满足。

这也算是一种编程强迫症吧。

经验

下一个原因:经验。

我花了很多时间用 C 来解决各种 bug,因此我花在 C 上的时间远超其他编程语言。我对 C 语言的了解远胜其他语言。

这种经验上的差距很难弥补。如果从今天开始使用 Rust,我相信我需要大约十年的时间才能像 C 一样精通 Rust。

为此,我需要付出大量的时间。

编译时间

下一个核心原因:编译时间。

我知道如今 Rust 已经得到了很大提升,非常棒。

但 Rust 仍然很慢。我的电脑是 16 核的,在相同的时间里,用 C 语言我可以构建整个项目(包括测试套件),而用 Rust 我只能构建一个文件。

另一个方面是 C 文件包含模型,尽管不尽如人意,而且并行非常尴尬。Rust 很好,只不过还没有那么好。

自定义内存安全

下一个原因是,在使用 C 语言期间,关于内存安全,我已经开发出了自己的软件设计风格。

我使用特殊的数组类型来代替普通指针,这些数组会存储自己的边界。

我有一些宏,在访问数组索引时会进行边界检查。

我有一些宏,在计算数组指针时会进行边界检查。

我有一个栈分配器,我可以借助这个栈分配器在每个平台上实现 alloca() 。

我可以借助栈分配器将每个分配都放在同一个栈帧内。

栈分配器知道析构函数,因此它会在释放内存时调用析构函数。

如果我调用一个特定的函数,栈分配器会释放作用域内分配的所有内存。

如果我调用一个特定的函数,栈分配器会释放函数中分配的所有内存。

我使用结构化并发,这意味着如果将数据传递给新线程,我可以确保线程的寿命不会超过传递给它的数据。

简而言之,每条数据都可以追溯栈中特定位置上的祖先,数据永远不会传递给生命周期有可能超过自己的对象。

也就是我们常说的RAII(Resource Acquisition Is Initialization,资源获取即初始化),这意味着我能够控制生命周期和所有权,可以使用借用,以及我用 C11 重写了 Rust 的精华部分。

一般来说,让编译器静态地强制一切规则是最好的。

所有这一切都意味着,内存的分配和释放必须在同一个函数内,或者作为父对象的一部分被释放。

这大大减少了双重释放和释放后使用。因为我的所有代码都采用了这种写法,无一例外,所以我可以通过充分的测试来消除所有错误。

此外,边界检查可以大幅减少缓冲区溢出。

当然,引用 Jimmy Hartzell 的一句话:任何不完美的东西都不够好。

换句话说,我使用的不是 C 语言,而是内存安全的 C 语言。

总结

所以,上述就是我坚持使用 C 语言的全部理由。

当然,你有可能不同意我的看法。

只不过,我这个人遇到不喜欢的软件,就无法享受编写的过程。而我只喜欢 C 语言。

所以,对我个人而言,坚持使用 C 仍然是不二的选择。

","force_purephv":"0","gnid":"9248e5d7e808e130e","img_data":[{"flag":2,"img":[{"desc":"","height":"80","s_url":"https://p0.ssl.img.360kuai.com/t0186957a1ca5352752_1.gif","title":"","url":"https://p0.ssl.img.360kuai.com/t0186957a1ca5352752.gif","width":"640"}]}],"original":0,"pat":"art_src_1,fts0,sts0","powerby":"hbase","pub_time":1675907293000,"pure":"","rawurl":"http://zm.news.so.com/e3c00a04a7df58594e684850baeba775","redirect":0,"rptid":"e7fdb7bbbee9bcd3","s":"t","src":"CSDN","tag":[{"clk":"ktechnology_1:tcl","k":"tcl","u":""},{"clk":"ktechnology_1:内存","k":"内存","u":""}],"title":"为什么我相信使用 C 语言可以保证内存安全?

台标曼2206C语言三种基本结构分别包含什么语句? -
鲜卞华19159715862 ______ 1、顺序结构 ... 2、选择结构 if(...) if(..) {...} else {...} 3、循环结构 for(i=0;i<=5;i++){ ...... } 没写全,只各写了个代表.

台标曼2206C语言画流程图和书写程序结构! -
鲜卞华19159715862 ______ (1) include<stdio.h> main() { int a,b,c,s,av; s=a+b+c; av=s/3; scanf("%d%d%d",&a,&b,&c); printf("%d%d",s,av);} }

台标曼2206怎样编程序 -
鲜卞华19159715862 ______ 编程前需要:1 找一本关于计算机高级语言的教材(如要学C语言,建议用谭皓强编的《C程序设计》);2 然后好好学习该语言的语法;3 再学习过程中,要注意理解和总结各种算法;4 开编.编一个程序时(以C语言为例):1 首先明确编程...

台标曼2206C程序的基本结构是怎样的?
鲜卞华19159715862 ______ C程序的基本结构 通常一个C程序包括一个或多个函数,其中必有一个main函数,称为主函数.C函数的定义主要分两部分:函数说明部分和函数体.其中函数体由C语言的语句序列组成,实现函数的功能.C程序总是从主函数开始执行.

台标曼2206什么是C语言?详细点
鲜卞华19159715862 ______ c语言是高级语言,但由于它可以通过指针对内存进行访问,具有了低级语言的特性,因此很多人也称它是中级语言.按照内容来说C语言有自己的语言符号和语句规则,他有3种基本的结构:顺序结构,选择结构、循环结构.然后按照不同的需要通过用这三种结构的不同“组合”(当然不是拼凑那种简单组合)就可以编出不同功能的程序了. 当然还有指针和结构体等其他一些内容,但编程强调的是算法能力.算法即是你要做一件事的步骤,在编程里面体现的就是你要实现一个功能要知道编写的内容有几部分每一部分大概用什么方法去实现.

台标曼2206《数据结构(C语言版)》的内容主要是什么?
鲜卞华19159715862 ______ C语言的数据结构是用C 语言描述数据结构的,主要有顺序表(是用数组实现的),顺序链表(要用到指针),串(就是C语言中的字符串),堆栈【顺序堆栈(用数组实现)和链接堆栈(用链表实现)】,树(主要是讲二叉树),图,再就是内排序,外排序,文件的查找. 链表,二叉树,图是最重要的. 基本就是这样!!!!

台标曼2206什么是C语言?
鲜卞华19159715862 ______ C语言是Combined Language(组合语言)的中英混合简称.是一种计算机程序设计语言.它既具有高级语言的特点,又具有汇编语言的特点.它可以作为工作系统设计语言,编写系统应用程序,也可以作为应用程序设计语言,编写不依赖计算...

台标曼2206C语言程序的基本结构是什么 -
鲜卞华19159715862 ______ C语言程序的基本结构是函数

台标曼2206C语言的基础是什么? -
鲜卞华19159715862 ______ C语言基础语句目录C语言基础语句C程序的语句1.表达式语句2.函数调用语句3.控制语句条件判断4.复合语句5.空语句编辑本段C语言基础语句 从程序流程的角度来看,程序可以分为三种基本结构, 即顺序结构、分支(选择)结构、循环结构. ...

台标曼2206计算机C语言 -
鲜卞华19159715862 ______ C语言是一种计算机程序设计语言.它既具有高级语言的特点,又具有汇编语言的特点.它可以作为系统设计语言,编写工作系统应用程序,也可以作为应用程序设计语言,编写不依赖计算机硬件的应用程序.因此,它的应用范围广泛.主要有...

(编辑:自媒体)
关于我们 | 客户服务 | 服务条款 | 联系我们 | 免责声明 | 网站地图 @ 白云都 2024