<分区>
当我们对十六进制数使用 0x
前缀,对八进制数使用 0
时,对于二进制数有什么可以做的吗?
我尝试了 b
后缀,但是 GCC不允许。
Error: invalid suffix "b" on integer constant
这可能吗?
标签 c
<分区>
当我们对十六进制数使用 0x
前缀,对八进制数使用 0
时,对于二进制数有什么可以做的吗?
我尝试了 b
后缀,但是 GCC不允许。
Error: invalid suffix "b" on integer constant
这可能吗?
最佳答案
标准 C 没有定义二进制常量。虽然有一个 GNU C 扩展(在流行的编译器中,clang 也对其进行了调整):0b
或 0B
前缀:
int foo = 0b1010;
如果你想坚持使用标准 C,那么有一个选择:你可以结合一个宏和一个函数来创建一个几乎可读的“二进制常量”特性:
#define B(x) S_to_binary_(#x)
static inline unsigned long long S_to_binary_(const char *s)
{
unsigned long long i = 0;
while (*s) {
i <<= 1;
i += *s++ - '0';
}
return i;
}
然后你可以像这样使用它:
int foo = B(1010);
如果您启用大量编译器优化,编译器很可能会完全消除函数调用(常量折叠)或至少将其内联,因此这甚至不会成为性能问题。
证明:
以下代码:
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <string.h>
#define B(x) S_to_binary_(#x)
static inline unsigned long long S_to_binary_(const char *s)
{
unsigned long long i = 0;
while (*s) {
i <<= 1;
i += *s++ - '0';
}
return i;
}
int main()
{
int foo = B(001100101);
printf("%d\n", foo);
return 0;
}
已使用 clang -o baz.S baz.c -Wall -O3 -S
编译,并生成以下程序集:
.section __TEXT,__text,regular,pure_instructions
.globl _main
.align 4, 0x90
_main: ## @main
.cfi_startproc
## BB#0:
pushq %rbp
Ltmp2:
.cfi_def_cfa_offset 16
Ltmp3:
.cfi_offset %rbp, -16
movq %rsp, %rbp
Ltmp4:
.cfi_def_cfa_register %rbp
leaq L_.str1(%rip), %rdi
movl $101, %esi ## <= This line!
xorb %al, %al
callq _printf
xorl %eax, %eax
popq %rbp
ret
.cfi_endproc
.section __TEXT,__cstring,cstring_literals
L_.str1: ## @.str1
.asciz "%d\n"
.subsections_via_symbols
所以clang
完全消除了对该函数的调用,并将其返回值替换为101
。整洁吧?
关于c - 用C代码编写二进制数字系统,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15114140/