为什么C不具有二进制文字?

时间:2022-03-15 21:00:34

I am frequently wishing I could do something like this in c:

我经常希望我能在c中做这样的事情:

val1 &= 0b00001111; //clear high nibble
val2 |= 0b01000000; //set bit 7
val3 &= ~0b00010000; //clear bit 5

Having this syntax seems like an incredibly useful addition to C with no downsides that I can think of, and it seems like a natural thing for a low level language where bit-twiddling is fairly common.

拥有这种语法似乎是C的一个非常有用的补充,没有我能想到的缺点,对于低级语言而言,这似乎是很自然的事情。

Edit: I'm seeing some other great alternatives but they all fall apart when there is a more complex mask. For example, if reg is a register that controls I/O pins on a microcontroller, and I want to set pins 2, 3, and 7 high at the same time I could write reg = 0x46; but I had to spend 10 seconds thinking about it (and I'll likely have to spend 10 seconds again every time I read those code after a not looking at it for a day or two) or I could write reg = (1 << 1) | (1 << 2) | (1 << 6); but personally I think that is way less clear than just writing `reg = 0b01000110;' I can agree that it doesn't scale well beyond 8 bit or maybe 16 bit architectures though. Not that I've ever needed to make a 32 bit mask.

编辑:我看到了其他一些很好的选择,但是当有更复杂的面具时,它们都会崩溃。例如,如果reg是控制微控制器上I / O引脚的寄存器,并且我想将引脚2,3和7设置为高电平,同时我可以写入reg = 0x46;但是我不得不花10秒时间思考它(而且每次我在没有看一两天之后阅读这些代码时我可能不得不再花10秒钟)或者我可以写reg =(1 << 1)| (1 << 2)| (1 << 6);但我个人认为这不仅仅是写'reg = 0b01000110;'。我同意它不会超出8位或16位架构。不是说我曾经需要制作32位掩码。

6 个解决方案

#1


22  

According to Rationale for International Standard - Programming Languages C §6.4.4.1 Integer constants

根据国际标准的基本原理 - 编程语言C§6.4.4.1整数常数

A proposal to add binary constants was rejected due to lack of precedent and insufficient utility.

添加二进制常量的提议由于缺乏先例和实用程序不足而被拒绝。

It's not in standard C, but GCC supports it as an extension, prefixed by 0b or 0B:

它不是标准的C,但是GCC支持它作为扩展,以0b或0B为前缀:

 i = 0b101010;

See here for detail.

详情请见此处。

#2


12  

This is what pushed hexadecimal to be... hexadecimal. The "... primary use of hexadecimal notation is a human-friendly representation of binary-coded values in computing and digital electronics ...". It would be as follows:

这就是将十六进制推送到十六进制的内容。 “...十六进制表示法的主要用途是计算和数字电子设备中二进制编码值的人性友好表示......”。它将如下:

val1 |= 0xF;
val2 &= 0x40;
val3 |= ~0x10;

Hexadecimal:

十六进制:

  1. One hex digit can represent a nibble (4 bits or half an octal).
  2. 一个十六进制数字可以表示半字节(4位或半个八进制)。
  3. Two hex digits can represent a byte (8 bits).
  4. 两个十六进制数字可以表示一个字节(8位)。
  5. Hex is much more compact when scaling to larger masks.
  6. 当缩放到更大的掩模时,Hex更紧凑。

With some practice, converting between hexadecimal and binary will become much more natural. Try writing out your conversions by hand and not using an online bin/hex notation converter -- then in a couple days it will become natural (and quicker as a result).

通过一些练习,十六进制和二进制之间的转换将变得更加自然。尝试手动写出你的转换,而不是使用在线bin / hex符号转换器 - 然后在几天内它将变得自然(并且因此更快)。

Aside: Even though binary literals are not a C standard, if you compile with GCC it is possible to use binary literals, they should be prefixed with '0b' or '0B'. See the official documentation here for further information. Example:

旁白:尽管二进制文字不是C标准,但如果使用GCC进行编译,则可以使用二进制文字,它们应该以“0b”或“0B”作为前缀。有关详细信息,请参阅此处的官方文档。例:

int b1 = 0b1001; // => 9
int b2 = 0B1001; // => 9

#3


8  

All of your examples can be written even more clearly:

您可以更清楚地编写所有示例:

val1 &= (1 << 4) - 1; //clear high nibble
val2 |= (1 << 6); //set bit 6
val3 &=~(1 << 3); //clear bit 3

(I have taken the liberty of fixing the comments to count from zero, like Nature intended.)

(我已经冒昧地将评论从零开始计算,就像大自然一样。)

Your compiler will fold these constants, so there is no performance penalty to writing them this way. And these are easier to read than the 0b... versions.

您的编译器将折叠这些常量,因此以这种方式编写它们不会有性能损失。这些比0b版本更容易阅读。

#4


6  

I think readability is a primary concern. Although low-level, it's human beings who read and maintain your code, not machine.

我认为可读性是一个主要问题。虽然是低级别的,但是人类会阅读和维护您的代码,而不是机器。

Is it easy for you to figure out that you mistakenly typed 0b1000000000000000000000000000000(0x40000000), where you really mean 0b10000000000000000000000000000000(0x80000000) ?

您是否容易弄清楚您错误地键入了0b1000000000000000000000000000000(0x40000000),其中您的意思是0b10000000000000000000000000000000(0x80000000)?

#5


2  

"For example, if reg is a register that controls I/O pins on a microcontroller"

“例如,如果reg是一个控制微控制器上I / O引脚的寄存器”

I can't help thinking this is a bad example. Bits in control registers have specific functions (as will any devices connected to individual IO bits).

我不禁想到这是一个糟糕的例子。控制寄存器中的位具有特定功能(连接到各个IO位的任何器件也是如此)。

It would be far more sensible to provide symbolic constants for bit patterns in a header file, rather than working out the binary within the code. Converting binary to hexadecimal or octal is trivial, remembering what happens when you write 01000110 to an IO register is not, particularly if you don't have the datasheet or circuit diagram handy.

为头文件中的位模式提供符号常量更为明智,而不是在代码中计算二进制文件。将二进制转换为十六进制或八进制是微不足道的,记住将01000110写入IO寄存器时会发生什么,特别是如果您没有方便的数据表或电路图。

You will then not only save those 10 seconds trying to work out the binary code, but maybe the somewhat longer time trying to work out what it does!

然后,您不仅可以节省10秒钟来计算二进制代码,还可能需要更长的时间来计算它的功能!

#6


0  

If you don't need an actual literal, you can do something like this:

如果您不需要实际的文字,您可以这样做:

#define B_(x) strtoull(#x, 0, 2)

unsigned char low_nibble = B_(00001111);
unsigned char bit_7 = B_(01000000);
unsigned char bit_5 = B_(00010000);

val1 |= low_nibble;
val2 &= bit_7;
val3 |= ~bit_5;

#1


22  

According to Rationale for International Standard - Programming Languages C §6.4.4.1 Integer constants

根据国际标准的基本原理 - 编程语言C§6.4.4.1整数常数

A proposal to add binary constants was rejected due to lack of precedent and insufficient utility.

添加二进制常量的提议由于缺乏先例和实用程序不足而被拒绝。

It's not in standard C, but GCC supports it as an extension, prefixed by 0b or 0B:

它不是标准的C,但是GCC支持它作为扩展,以0b或0B为前缀:

 i = 0b101010;

See here for detail.

详情请见此处。

#2


12  

This is what pushed hexadecimal to be... hexadecimal. The "... primary use of hexadecimal notation is a human-friendly representation of binary-coded values in computing and digital electronics ...". It would be as follows:

这就是将十六进制推送到十六进制的内容。 “...十六进制表示法的主要用途是计算和数字电子设备中二进制编码值的人性友好表示......”。它将如下:

val1 |= 0xF;
val2 &= 0x40;
val3 |= ~0x10;

Hexadecimal:

十六进制:

  1. One hex digit can represent a nibble (4 bits or half an octal).
  2. 一个十六进制数字可以表示半字节(4位或半个八进制)。
  3. Two hex digits can represent a byte (8 bits).
  4. 两个十六进制数字可以表示一个字节(8位)。
  5. Hex is much more compact when scaling to larger masks.
  6. 当缩放到更大的掩模时,Hex更紧凑。

With some practice, converting between hexadecimal and binary will become much more natural. Try writing out your conversions by hand and not using an online bin/hex notation converter -- then in a couple days it will become natural (and quicker as a result).

通过一些练习,十六进制和二进制之间的转换将变得更加自然。尝试手动写出你的转换,而不是使用在线bin / hex符号转换器 - 然后在几天内它将变得自然(并且因此更快)。

Aside: Even though binary literals are not a C standard, if you compile with GCC it is possible to use binary literals, they should be prefixed with '0b' or '0B'. See the official documentation here for further information. Example:

旁白:尽管二进制文字不是C标准,但如果使用GCC进行编译,则可以使用二进制文字,它们应该以“0b”或“0B”作为前缀。有关详细信息,请参阅此处的官方文档。例:

int b1 = 0b1001; // => 9
int b2 = 0B1001; // => 9

#3


8  

All of your examples can be written even more clearly:

您可以更清楚地编写所有示例:

val1 &= (1 << 4) - 1; //clear high nibble
val2 |= (1 << 6); //set bit 6
val3 &=~(1 << 3); //clear bit 3

(I have taken the liberty of fixing the comments to count from zero, like Nature intended.)

(我已经冒昧地将评论从零开始计算,就像大自然一样。)

Your compiler will fold these constants, so there is no performance penalty to writing them this way. And these are easier to read than the 0b... versions.

您的编译器将折叠这些常量,因此以这种方式编写它们不会有性能损失。这些比0b版本更容易阅读。

#4


6  

I think readability is a primary concern. Although low-level, it's human beings who read and maintain your code, not machine.

我认为可读性是一个主要问题。虽然是低级别的,但是人类会阅读和维护您的代码,而不是机器。

Is it easy for you to figure out that you mistakenly typed 0b1000000000000000000000000000000(0x40000000), where you really mean 0b10000000000000000000000000000000(0x80000000) ?

您是否容易弄清楚您错误地键入了0b1000000000000000000000000000000(0x40000000),其中您的意思是0b10000000000000000000000000000000(0x80000000)?

#5


2  

"For example, if reg is a register that controls I/O pins on a microcontroller"

“例如,如果reg是一个控制微控制器上I / O引脚的寄存器”

I can't help thinking this is a bad example. Bits in control registers have specific functions (as will any devices connected to individual IO bits).

我不禁想到这是一个糟糕的例子。控制寄存器中的位具有特定功能(连接到各个IO位的任何器件也是如此)。

It would be far more sensible to provide symbolic constants for bit patterns in a header file, rather than working out the binary within the code. Converting binary to hexadecimal or octal is trivial, remembering what happens when you write 01000110 to an IO register is not, particularly if you don't have the datasheet or circuit diagram handy.

为头文件中的位模式提供符号常量更为明智,而不是在代码中计算二进制文件。将二进制转换为十六进制或八进制是微不足道的,记住将01000110写入IO寄存器时会发生什么,特别是如果您没有方便的数据表或电路图。

You will then not only save those 10 seconds trying to work out the binary code, but maybe the somewhat longer time trying to work out what it does!

然后,您不仅可以节省10秒钟来计算二进制代码,还可能需要更长的时间来计算它的功能!

#6


0  

If you don't need an actual literal, you can do something like this:

如果您不需要实际的文字,您可以这样做:

#define B_(x) strtoull(#x, 0, 2)

unsigned char low_nibble = B_(00001111);
unsigned char bit_7 = B_(01000000);
unsigned char bit_5 = B_(00010000);

val1 |= low_nibble;
val2 &= bit_7;
val3 |= ~bit_5;