我也反对​​丢弃​​​二进制字面.虽然我不经常使用它们,但有几次我确实需要它们,我很高兴它们​​在那里​​​.它是​​C缺少​​​的​​D优点​​​之一,如果放弃它会相当​​失望​​​.不得不求助于​​模板​​​来使用​​二进制​​​字面会很痛苦.
八进制的丢弃也没有那么成功.应该选择​​​0o​​​ 编译器仍在​​正确​​解析​​八进制字面​​.
​0o​​对八进制完全有意义,就像​​0x​​对十六进制完全有意义一样
编译器中有​​类型推导​​逻辑:

import std.conv:=octal;

void main(){
auto x0=o!1000000000;
static assert(is(typeof(x0)==int));
auto x1=o!10000000000;
static assert(is(typeof(x1)==long));
}

​C++11​​​起就有用户定义的​​字面​​​.一般以​​"_字面"​​​结尾,如​​300_km​​​.支持串和值​​字面​​​.
好处是D可以让你用下划线对位分组.
因此,可能会喜欢​​​0b11_111_101_001​​​这使它更易管理,并且可像在​​文档​​​中,分组​​标志​​​寄存器.
作为语言功能的东西都应该是保持该功能开箱即用的​​​对象​​​.
这有明显的​​​视觉含义​​,但在十六进制中很难阅读.

0b111111
0b100001
0b100001
0b111111

​对象​​​是​​隐式​​​导入的,因此可在全局命名空间中获取内容.模块系统有办法消歧,但我一般还是更喜欢​​显式导入​​​来保持清晰,特别是如果没有​​导入​​​来清理它,​​错误消息​​​可能会相当糟糕.
​​​throw new Exception("串")​​​不好,但最方便.
删除几十年来拥有的​​​二进制字面​​​会​​*伤害*​​​D.
​​​摆脱​​​奇怪的​​极端​​​情况和​​任意限制​​​.
​​​ImportC​​​对D来说是一个​​巨大​​​的胜利.我应该一开始就这样做.
是否会再次忽略​​​社区​​​几乎一致的​​反馈​​​并删除二进制​​字面​​?

在为C实现它之后,我发现可​​简单​​​地打开​​现有实现​​​来添加位域到​​D​​​.​​代码​​​已经存在,已支持并调试.
更喜欢​​​模板​​​方法,它没有​​C方法​​​所具有的简单语法,而​​位域​​​可证明更简单的​​内置语法​​​是合理的.
在为D打开它时,它暴露了1个​​​严重​​​错误,我为C端编写的​​大量测试​​错过了该错误.

把它​​包装​​​在串字面中,并编写简单​​解析器​​​来翻译它为二进制数据.
这样很容易向​​​反汇编​​​程序添加​​测试用例​​​.非常值得为此付出​​额外​​​的努力来制作​​小型解析器​​​.
编写简单解析器,并用​​​CTFE​​​生成表中二进制数据.当然,这样,解析器可​​反复​​​用于​​其他​​项目.

enum Flag  = {
CARRY = 1,
SIGN = 2,
OVERFLOW = 4,
PARITY = 8,
ZERO = 0x10,
...
}

我一直使用上面​​二进制标志​​.要了解:

​序号​

学习

​1​

​2进制​​补码算法

​2​

​浮点数​​是如何工作的

​3​

指针

比​​等效​​​的​​十六进制​​​更容易理解
我更喜欢内置的​​​位域​​系统.

{
assert(beststraight(0b10000000011110) == Rank.Five);
assert(beststraight(0b10101111111110) == Rank.Ten);
}

以八进制表示的​​8080/8085/Z80​​​操作码更容易处理.​​仿真器​​​是个小众领域,但许多​​CPU​​​和外围寄存器通常具有​​八进制​​​字段.当然,​​十六​​​进制通常足以处理它们.
我从未见过以​​​八进制​​​表示的​​8080/Z80​​​操作码.我知道​​x86​​​的​​modregrm​​​字节是​​2,3,3​​​,但我通过使用​​内联函数​​​来处理它.我从来没有想过使用​​八进制​​.有趣的.

ubyte modregrm (uint m, uint r, uint rm){
return cast(ubyte)((m << 6) | (r << 3) | rm);
}

当然,位域可能会更好,:-)
我开始实施​​​ImportC​​​时,我​​重新​​​发现了所有我​​不喜欢​​​的东西,但它们已经在​​D中​​修复了.

writeln(format("%b", 0xcc));

解析工具:

ulong parse(const char[] data){
ulong result = 0;
foreach(ch; data){
switch(ch){
case '.':
result <<= 1;
break;
case 'x': case 'X':
result <<= 1;
result |= 1;
break;
case ' ': case '\t': case '\n': case '\r':
case '_':
continue;
default:
throw new Exception("oops");
}
}
return result;
}

static assert("...".parse == 0b000);
static assert("..x".parse == 0b001);
static assert(".x.".parse == 0b010);
static assert(".xx".parse == 0b011);
static assert("x..".parse == 0b100);
static assert("x.x".parse == 0b101);
static assert("xx.".parse == 0b110);
static assert("xxx".parse == 0b111);
static assert("
xxx
x.x
xxx
".parse == 0b111_101_111);
static assert("x.x.__x__.x.x".parse == 0b1010__1__0101);
private bool does_throw(const char[] data){
bool caught = false;
try { const _ = data.parse; }
catch (Exception e){ caught = true; }
return caught;
}
static assert(does_throw("x0x"));
static assert(does_throw("1010"));
static assert(does_throw("1010"));