【发布时间】:2015-09-27 09:58:57
【问题描述】:
我只需要一位来表示我的数据 - 1 或 0。在 C 中这样做的最佳方式是什么? “正常”数据类型太大。
【问题讨论】:
-
内存是否如此稀缺以至于您需要将值存储为单个位?你用它做什么?也许有更好的方法。
我只需要一位来表示我的数据 - 1 或 0。在 C 中这样做的最佳方式是什么? “正常”数据类型太大。
【问题讨论】:
可移植的方式是定义一个变量,将各个位用作标志。
#define FLAG_FOO 0
#define FLAG_BAR 1
// in case platform does not support uint8_t
typedef unsigned char uint8_t;
uint8_t flags;
void flag_foo_set()
{
flags |= (1 << FLAG_FOO);
}
void flag_foo_clr()
{
flags &= ~(1 << FLAG_FOO);
}
uint8_t flag_foo_get()
{
return flags & (1 << FLAG_FOO);
}
虽然与 C 位字段相比,这似乎是多余的。它基本上可以移植到每个 ANSI C 编译器。
【讨论】:
uint8_t 有 每个 ANSI C 编译器都支持吗?我不完全确定。 unsigned char 可能是更好的选择。
unsigned char
typedef unsigned char uint8_t; 对我来说似乎有潜在危险。
如果您不需要 数百万 个这些标志或内存限制极其有限,那么最好的方法无疑是 int。
这是因为int 通常对应于您平台的自然字长,并且可以在正确对齐的情况下快速访问。无论如何,机器一次读取一个单词,并且使用单个位需要屏蔽和移位,这会花费时间。在具有千兆字节 RAM 的典型 PC 上,这简直是愚蠢的。
如果内存消耗真的是个问题,则存在位域结构。
【讨论】:
通常,C 中最小的可寻址数据块是一个字节。你不能有一个指向位的指针,所以你不能声明一个 1 位大小的变量。但正如 Sourav Ghosh 已经指出的那样,您可以声明位域,其中一位可以直接访问。
【讨论】:
你可以创造
typedef struct foo
{
unsigned x:1;
} foo;
您曾告诉编译器您将只使用x 的一位。
但是由于结构打包安排(C 标准有意灵活,以便编译器可以根据机器架构进行优化),很可能它仍然占用与常规unsigned 一样多的内存空间和foos 的数组不必按位连续。
【讨论】:
#pragma pack(1) 和#pragma pack(0) 避免您解释的包装安排吗?
如果你真的想要,你可以创建一个带有成员变量的结构体,bit-fielded 为 1 位。
记住,成员变量的数据类型必须是unsigned,因为你需要存储0和1。
【讨论】: