【问题标题】:How do I use a binary prefix in accordance with C11?如何根据 C11 使用二进制前缀?
【发布时间】:2026-02-02 03:55:01
【问题描述】:

我目前开始使用C30(基于GCCC 编译器,来自微芯片的PIC24 设备)对微控制器进行编程,出于好奇,我启用了Strict ANSI warnings。首先,我不知道在 C11 中像 // 这样的注释标记是“错误的”,而我应该使用 /* blah blah */,但真正让我吃惊的是对一行代码的警告。

“警告:使用非标准二进制前缀”

代码行是:

OSCCONbits.COSC = 0b000;

我在网上查看了 C11 (ISO/IEC 9899:2011) 的草案之一,但找不到任何关于 C 中二进制前缀的信息。http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf

根据 C11,C 的正确二进制表示法是什么?

【问题讨论】:

  • 将其转换为十六进制数。至于将某些内容设置为(二进制)0000,为什么不使用普通的十进制0 或十六进制0x00
  • 谁告诉你 // cmets 是“错误的”?
  • 我想我的问题可能措辞错误,所以这里有一些更正。我知道我可以只使用十六进制或十进制而不是二进制,我只是想知道使用二进制文字的“正确”方式是什么。关于我说 // cmets 是“错误的”,我是从编译器警告中得到的,除了编译器之外没有人告诉我。无论如何,感谢所有帮助的家伙!我得到了一些很棒的答案,我希望我可以将它们全部标记为答案,但遗憾的是我只能对一个这样做。
  • @hak8or:那么它不是 c99 或 c11 编译器。
  • @JoachimPileborg:完全迂腐,0 是一个 八进制 常量,而不是十进制(!)

标签: c compiler-construction standards standards-compliance c11


【解决方案1】:

C 没有二进制常量。 (即使在 C11 中也不支持它们。)

它们被提议作为 C99 的补充,但该提议被拒绝了。

来自 C99 基本原理文档:

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

您说您正在使用基于 gccgcc 的编译器支持二进制常量:它们是 C 语言的 GNU 扩展。

整数常量可以写成二进制常量,由01的数字序列组成,前缀为0b0B。这对于在位级别进行大量操作的环境(例如微控制器)特别有用。

有关二进制常量的更多信息,请参见gcc 页面:

http://gcc.gnu.org/onlinedocs/gcc/Binary-constants.html

【讨论】:

  • 他们觉得它没有足够的实用性。我一直在代码中使用0b 来进行高速整数运算(与微控制器无关)。例如,0b10101010 对我来说比 0xAA 更具可读性。他们觉得没有先例也令人遗憾。 Java 拥有0b 已有一段时间了。
【解决方案2】:

关于标准:

  • ANSI C /“严格 ANSI”通常是指 C 的第一个标准版本,仅在 1989 年在美国标准化。有时也称为“C89”。
  • ANSI C/89 于 1990 年过时,当时 C 成为国际 C 标准 ISO/IEC 9899:1990,简称为“C90”。在技​​术细节方面,C89 和 C90 是等效的。
  • C90 在 1999 年过时,当时 ISO C 被更新。新标准称为“C99”。
  • C99 于 2011 年过时。新标准称为“C11”。

关于你的编译器问题:

  • C89/C90 不允许 // cmets。它们是在 C99 中引入的。它们尚未在 C11 中删除。
  • 二进制符号从未成为任何 C 标准的一部分。

结论:

  • 您很可能在 C90 编译器上编译代码,并提供了一些非标准扩展。

【讨论】:

  • 感谢您的回答。 :)
【解决方案3】:

C11 没有二进制字面量;它只有十进制、八进制和十六进制,如标准第 6.4.4.1 节所述。这与 C99 相同。

6.6 第 10 段说:

一个实现可以接受其他形式的常量表达式。

如果我理解正确的话,它允许你的编译器提供的那种扩展;这也与 C99 相同。

通常的解决方法是使用十六进制文字;每个十六进制数字对应四个二进制数字。 (当然0b000 可以写成0。)

【讨论】:

  • 感谢您的回答。 :)
  • 这不是对 C11§6.6p10 的正确解释。 §6.6 旨在划分出一个保证评估为常量的有效表达式的子集。它不扩展解析器或词法分析器(需要支持二进制文字)。
  • @SamElliott 我倾向于同意。我得再考虑一下。如果你是对的,这意味着可以支持二进制文字作为 C11 4p6 下的扩展,但符合标准的编译器仍必须对 0b000 发出诊断,因为它违反了语法规则。
【解决方案4】:

二进制前缀不是标准的。将它们转换为八进制 (0) 或十六进制 (0x),它们只是标准中定义的前缀。

另外,// cmets 是在 C99 标准中引入的,它们在 C89 ANSI 标准中不存在。这就是为什么你的编译器会给你一个警告。

【讨论】:

  • 感谢您的回答。 :)