2501d,d作者,炮打C语言!

原文

标准C定期改进,现在为C23.但是还是没有解决一些怪东西.Dlang社区在D语言编译器中嵌入了一个C编译器,这样可编译C.

C编译器(又名ImportC)是从头开始构建的.它提供了使用现代编译器技术修复这些缺点的机会.为什么标准C不修复它们?

1,计算常式

2,编译时单元测试

3,前向引用声明

4,导入声明

计算常式

请考虑以下C代码:

cpp 复制代码
int sum(int a, int b) { return a + b; }
enum E { A = 3, B = 4, C = sum(5, 6) };

gcc编译时:

cpp 复制代码
gcc c test.c
test.c:3:20: error: enumerator value for C is not an integer constant
 enum E { A = 3, B, C = sum(5, 6) };
                    ^

即,虽然C可在编译时通过常量折叠计算简单式,但它不能在编译时执行函数.但ImportC可以!

C语法中出现C常式的地方,只要这些函数无I/O,访问可变全局变量,系统调用等操作,编译器就应该可在编译时执行函数.

编译时单元测试

一旦C编译器可(CTFE)编译时求值函数,突然间,其他事情就变成可能.

如,在C代码中很少看到单元测试,很明显,在构建系统单元测试需要一个单独的目标,且必须按单独的可执行文件构建和运行.

有点麻烦表明它不可能!

cpp 复制代码
int sum(int a, int b) { return a + b; }
_Static_assert(sum(3, 4) == 7, "test #1");
>gcc c test.c
test.c:3:16: error: expression in static assertion is not constant
_Static_assert(sum(3, 4) == 7, "test #1");
               ^

ImportC可编译它.

这样不需要单独的构建,就可以单元测试编译时运行的函数.不需要额外的工作.每次编译代码时,都会运行单元测试.我在ImportC测试包广泛使用它.

前向声明引用

更多代码:

cpp 复制代码
int floo(int a, char *s) { return dex(s, a); }
char dex(char *s, int i) { return s[i]; }
gcc c test.c
test.c:4:6: error: conflicting types for dex
 char dex(char *s, int i) { return s[i]; }
      ^

test.c:2:35:注意:前dex的隐式声明在此:

cpp 复制代码
 int floo(int a, char *s) { return dex(s, a); }

如果floodex的顺序逆转,则编译正常.即编译器只知道它在词法上之前的内容.禁止前向引用.

这岂是石器时代的编译器设计?现代语言无此问题,为什么在CC++中持续存在?ImportC不是现代语言,但它是现代编译器,接受任意顺序全局声明.

为什么这很重要?一般表明每个前向定义需要一个额外的声明:

cpp 复制代码
char dex(char *s, int i); //声明
int floo(int a, char *s) { return dex(s, a); }
char dex(char *s, int i) { return s[i]; } //定义

这样做,只是毫无目的的折腾.这不仅烦人,还会促使倒过来布局声明.叶函数排在最前面,全局接口函数排在最后.就像自下而上读报纸文章一样.毫无意义.
ImportC可按任意顺序编译声明.

导入声明

给定三个floo.d,dex.h,dex.c文件:

cpp 复制代码
//floo.c
#include "dex.h"
int floo(int a, char *s) { return dex(s, a); }
//dex.h
char dex(char *s, int i);
//dex.c
#include "dex.h"
char dex(char *s, int i) { return s[i]; }

必须为每个外部模块制作一个.h文件是一项粗活,更差,如果.h文件与.c文件不完全匹配,你要花费大量时间找出问题所在.

答案是什么:导入dex.c!

cpp 复制代码
//floo.c
__import dex;
int floo(int a, char *s) { return dexx(s, a); }
//dex.c
char dexx(char *s, int i) { return s[i]; }

甚至不必编写.h文件.当然,这也适合ImportC.

参考
导入C
D语言

:如果你在翻译单元中工作,那会大大简化,但这样可在不重复大量代码做更多的事情.我想知道作者是如何解决它的?

你是正确的,因为正在求值的函数源码必须可供编译器使用.这可通过#include来完成.我在D中就是这样,并导入包含要求代码的模块.

:如果可按宏表示测试,这是可能的,如果添加第一点,则这就很简单.

当你想要测试函数时,按宏表示测试不管用.我给出的示例很简单,很容易理解.实际使用可能更复杂.

:性能
D的编译速度C编译器快,主要是因为:
1.C预处理器是一头需要多次传递无可救药的猪.我知道,我从头开始实现了多次.C预处理器发明时是个很好的设计选择.

今天,它已变成化石.我仍对为什么C++从未来得及弃用它感到敬畏.
2.D使用导入而不是#include.这样更快,因为不需要一遍遍地编译.h文件.

D的策略是分开解析与分析语义.我想它确实慢了一点,但它也不必重新编译重复的声明折叠成一个.

当然,执行编译时函数,可能是个瓶颈,但这(当然)根据它的使用程度.喜欢轻触使用它,性能很好.如果使用它实现编译器,它可能会很慢.

我并不是建议删除C#include.导入的东西将是额外的.

:对这些问题有什么想法吗?

如果你正在使用黑客,来在C语言中用模板,则你已超越了这门语言,需要一个更强大的语言.D拥有顶级的元编程-如常,其他模板语言也在追随D的路径.

:不能使用预编译头文件?

你提到它很有趣.我在90年代为SymantecCC++实现了它们.

我再也不想这样做了!

它们很脆,是维护的噩梦.不过,它们确实加快了编译速度,但没有提供语义优势.

使用D时,我非常关注快速编译,以至于预编译的头文件无法提供足够的加速,因此值得付出痛苦.

:我个人不喜欢前向引用,因为它会使代码更难读.你不能再依赖图的拓扑顺序.

正如文章所写的,这会强制在顶部有私有叶函数,而公共接口在文件尾.可以说,正常方式是在顶部放置公共接口,而实现则在"首屏下方".

作者是D的创建者,所以他可能对D没问题.D大概是25岁.而Zig只是一个蹒跚学步的孩子.

是的.D其他语言许多最新功能源头.

我开始研究D的原因是CC++非常不愿意向前发展.

但更重要的是,Zig故意没有实现D一大堆事情.

有时需要吝啬.zig基本上是c--+,其中+常式的东西.

它会不断添加D功能,比如常式.

没人使用C++模块,因为它们使用起来很笨拙.D很容易.注意:你可以自由复制D的模块设计.这是最好的.

:C++常式

经过17年的发展,仍落后D.在D中,垃集器使得很容易分配内存.此外,只有通过函数取的路径需要与CTFE兼容,其他则不需要.

C语言:

cpp 复制代码
#include <stdio.h>
void main()
{
    int i;
    for (i = 0; i < 10; ++i);
        printf("%d\n", i);
}
//99%的C程序员找不到八哥!

而等价的D语言:

cpp 复制代码
import core.stdc.stdio;
void main()
{
    int i;
    for (i = 0; i < 10; ++i);
        printf("%d\n", i);
}

给你:

cpp 复制代码
test.d(5): Error: use `{ }` for an empty statement, not `;`

赶紧的,标准C,修复它!

相关推荐
泡泡鱼(敲代码中)2 小时前
数据结构二叉树-C语言
c语言·开发语言·数据结构·笔记·学习
Coding Happily2 小时前
VScode 配置 C语言环境
c语言·ide·vscode
我想学LINUX2 小时前
【2024年华为OD机试】(B卷,200分)- 跳格子1 (Java & JS & Python&C/C++)
java·c语言·javascript·python·华为od
比特在路上2 小时前
初阶数据结构【双链表及其接口的实现】
c语言·数据结构·链表
我想学LINUX3 小时前
【2024年华为OD机试】(B卷,100分)- 组成最大数 (Java & JS & Python&C/C++)
java·c语言·javascript·python·华为od·c/c++
我想学LINUX3 小时前
【2024年华为OD机试】 (A卷,100分)- 插队 (Java & JS & Python&C/C++)
java·c语言·c++·python·华为od
仰望星空的凡人6 小时前
【嵌入式常识篇】一个C项目工程在IDE中是怎么一步步编译成一个固件包的
c语言·开发语言
L_09076 小时前
【C】初阶数据结构2 -- 顺序表
c语言·数据结构
似水এ᭄往昔6 小时前
【c语言】指针 (完结)
c语言·开发语言
do_yo7 小时前
6、原来可以这样理解C语言_函数(1/8)函数的概念
c语言·开发语言·数据结构·c++·算法