为什么我不能将位域声明为自动变量?

发布于 2024-09-14 10:42:32 字数 430 浏览 5 评论 0原文

我想声明一个使用冒号指定大小的位域(我不记得语法叫什么)。我想这样写:

void myFunction() 
{   
  unsigned int thing : 12;
  ...
}

但是 GCC 说这是一个语法错误(它认为我正在尝试编写一个嵌套函数)。不过,我这样做没有问题:

struct thingStruct
{
  unsigned int thing : 4;
};

然后将一个这样的结构放在堆栈上

void myFunction() 
{   
  struct thingStruct thing;
  ...
}

这让我相信它是由语法而不是语义问题阻止的。

那么为什么第一个例子不起作用呢?我缺少什么?

I want to declare a bitfield with the size specified using the a colon (I can't remember what the syntax is called). I want to write this:

void myFunction() 
{   
  unsigned int thing : 12;
  ...
}

But GCC says it's a syntax error (it thinks I'm trying to write a nested function). I have no problem doing this though:

struct thingStruct
{
  unsigned int thing : 4;
};

and then putting one such struct on the stack

void myFunction() 
{   
  struct thingStruct thing;
  ...
}

This leads me to believe that it's being prevented by syntax, not semantic issues.

So why won't the first example work? What am I missing?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

街道布景 2024-09-21 10:42:32

第一个示例不起作用,因为您只能在结构内部声明位域。正如您所说,这是语法,而不是语义,但事实就是如此。如果您想要位域,请使用结构体。

The first example won't work because you can only declare bitfields inside structs. This is syntax, not semantics, as you said, but there it is. If you want a bitfield, use a struct.

灰色世界里的红玫瑰 2024-09-21 10:42:32

你为什么要做这样的事?在所有常见架构上,12 位字段将被填充到至少 16 或 32 位。

如果要确保整数变量的宽度,请使用inttypes.h中的类型,例如int16_tint32_t

Why would you want to do such a thing? A bit field of 12 would on all common architectures be padded to at least 16 or 32 bits.

If you want to ensure the width of an integer variable use the types in inttypes.h, e.g int16_t or int32_t.

貪欢 2024-09-21 10:42:32

正如其他人所说,位域必须在 struct (或 union,但这并不是真正有用)中声明。为什么?这里有两个原因。

  • 主要是为了让编译器编写者的工作更轻松。位域往往需要更多的机器指令来从字节中提取位。只有字段可以是位字段,而不能是变量或其他对象,因此如果不涉及 .-> 运算符,编译器编写者不必担心它们.

  • 但是,你说,有时语言设计者会让编译器编写者的工作变得更困难,以便让程序员的生活更轻松。嗯,程序员对结构体之外的位域的需求并不多。原因是程序员几乎只在将几个小整数塞进单个数据结构中时才关心位域。否则,他们会使用普通的整型。

其他语言有整数范围类型,例如,您可以指定变量范围为 17 到 42。C 中对此没有太多要求,因为 C 从不要求实现检查溢出。因此,C 程序员只需选择一种能够表示所需范围的类型即可;无论如何,检查边界是他们的工作。

C89(即几乎随处可见的 C 语言版本)提供了有限的类型选择,至少有 n 位。有 8 位的 unsigned char、16 位的 unsigned Short 和 32 位的 unsigned long(加上有符号变体)。 C99 提供了更广泛的类型选择,称为 uint_least8_tuint_least16_tuint_least32_tuint_least64_t。这些类型保证是具有至少那么多值位的最小类型。实现可以提供其他位数的类型,例如 uint_least12_t,但大多数不提供。这些类型在 中定义,尽管标准并不要求,但它在许多 C89 实现中可用。

As others have said, bitfields must be declared inside a struct (or union, but that's not really useful). Why? Here are two reasons.

  • Mainly, it's to make the compiler writer's job easier. Bitfields tend to require more machine instructions to extract the bits from the bytes. Only fields can be bitfields, and not variables or other objects, so the compiler writer doesn't have to worry about them if there is no . or -> operator involved.

  • But, you say, sometimes the language designers make the compiler writer's job harder in order to make the programmer's life easier. Well, there is not a lot of demand from programmers for bitfields outside structs. The reason is that programmers pretty much only bother with bitfields when they're going to cram several small integers inside a single data structure. Otherwise, they'd use a plain integral type.

Other languages have integer range types, e.g., you can specify that a variable ranges from 17 to 42. There isn't much call for this in C because C never requires that an implementation check for overflow. So C programmers just choose a type that's capable of representing the desired range; it's their job to check bounds anyway.

C89 (i.e., the version of the C language that you can find just about everywhere) offers a limited selection of types that have at least n bits. There's unsigned char for 8 bits, unsigned short for 16 bits and unsigned long for 32 bits (plus signed variants). C99 offers a wider selection of types called uint_least8_t, uint_least16_t, uint_least32_t and uint_least64_t. These types are guaranteed to be the smallest types with at least that many value bits. An implementation can provide types for other number of bits, such as uint_least12_t, but most don't. These types are defined in <stdint.h>, which is available on many C89 implementations even though it's not required by the standard.

成熟的代价 2024-09-21 10:42:32

位域提供一致的语法来访问某些依赖于实现的功能。该功能最常见的目的是以某种方式将某些数据项相对于彼此放入位中。如果两个项目(位字段或非位字段)在结构中被声明为连续项目,则保证它们连续存储。无论存储类别或范围如何,单个变量都不存在这样的保证。如果一个结构包含:

struct foo {
  unsigned bar: 1;
  unsigned boz: 1;
};

则保证 bar 和 boz 将连续存储(最有可能在同一存储位置,尽管我认为这实际上不能保证)。相比之下,“bar”和“boz”是单位自动变量,不知道它们将存储在哪里,因此将它们作为位字段没有什么好处。如果它们确实与其他变量共享空间,则很难确保在同一字节中读取和写入不同位的不同函数不会相互干扰。

请注意,某些嵌入式系统编译器确实公开了真正的“位”类型,这些类型被打包为八个字节。此类编译器通常具有一个内存区域,该区域被分配用于仅存储位变量,并且它们为其生成代码的处理器具有用于测试、设置和清除各个位的原子指令。由于只能使用此类指令访问保存这些位的内存位置,因此不存在冲突的危险。

Bitfields provide a consistent syntax to access certain implementation-dependent functionality. The most common purpose of that functionality is to place certain data items into bits in a certain way, relative to each other. If two items (bit-fields or not) are declared as consecutive items in a struct, they are guaranteed to be stored consecutively. No such guarantee exists with individual variables, regardless of storage class or scope. If a struct contains:

struct foo {
  unsigned bar: 1;
  unsigned boz: 1;
};

it is guaranteed that bar and boz will be stored consecutively (most likely in the same storage location, though I don't think that's actually guaranteed). By contrast, 'bar' and 'boz' were single-bit automatic variables, there's no telling where they would be stored, so there'd be little benefit to having them as bitfields. If they did share space with some other variable, it would be hard to make sure that different functions reading and writing different bits in the same byte didn't interfere with each other.

Note that some embedded-systems compilers do expose a genuine 'bit' type, which are packed eight to a byte. Such compilers generally have an area of memory which is allocated for storing nothing but bit variables, and the processors for which they generate code have atomic instructions to test, set, and clear individual bits. Since the memory locations holding the bits are only accessed using such instructions, there's no danger of conflicts.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文