【问题标题】:C pointers and bit setting questionC指针和位设置问题
【发布时间】:2011-02-05 18:30:36
【问题描述】:

作为这个问题的背景,这是我编写的一个测试程序,用于调查我们在我工作的消息传递程序中看到的一些奇怪行为。我们有各种使用位标志来保存消息状态的结构,一些标志使用 char,一些使用 short。我们必须将消息转储到平面文件的实用程序是在这些标志值上使用 char* 来提取设置,因此我故意在 flag2 上使用了不同的指针。

当这个程序在 AIX UNIX 6.1 上运行时为什么会输出:

2套
4套
8套
16套
64套

值 1 和 32 发生了什么变化?

#include <stdio.h>

#define SET(x,y) y |= (x)
#define UNSET(x,y) y &= (~x)

int main ( int argc, char *argv[] )
{
    unsigned char *g;
    unsigned short *h;
    unsigned long *i;

    char flag1; 
    short flag2; 
    long flag3;

    g = (char*) &flag2;

    SET(1, flag2);
    if ( 1 & *g )
        printf("1 set\n");
    UNSET(1, flag2);

    SET(2, flag2);
    if ( 2 & *g )
        printf("2 set\n");
    UNSET(2, flag2);

    SET(4, flag2);
    if ( 4 & *g )
        printf("4 set\n");
    UNSET(4, flag2);

    SET(8, flag2);
    if ( 8 & *g )
        printf("8 set\n");
    UNSET(8, flag2);

    SET(16, flag2);
    if ( 16 & *g )
        printf("16 set\n");
    UNSET(16, flag2);

    SET(32, flag2);
    if ( 32 & *g )
        printf("32 set\n");
    UNSET(32, flag2);

    SET(64, flag2);
    if ( 64 & *g )
        printf("64 set\n");
    UNSET(64, flag2);

    return 0;
}

【问题讨论】:

  • 您可能希望将 flag2 显式初始化为 0。
  • flag2 很短,但您将指向它的指针转换为 char*,请改用 short*(g 也应该是 short 类型)。
  • 我在 HP UX 上运行程序,它根本不打印任何东西,但是当我在 Fedora 上运行相同的程序时,它可以工作。
  • 为什么要在 short 上使用 char 指针?

标签: c bit-manipulation


【解决方案1】:

AIX 是大端架构,这意味着g 指向flag 的最高有效字节。这意味着对最低有效字节的任何更改对g 都是不可见的。

flag2 也从未初始化,因此它将包含一些任意值。所以事实证明,当只是一开始的任意值时,您认为某些位设置有效。

如果您在像 x86 这样的小端机器上运行,事情应该会按预期运行。

【讨论】:

  • 不仅因为它是大端,而且因为short和char恰好是不同的大小。
【解决方案2】:

我发现有几件事可能是问题所在。

  1. 你没有初始化flag2

  2. 您可能需要转换为 g= (short * ) &flag2,因为如果您转换为 char 你不一定是 获得最少的参考 有效 8 位。

【讨论】:

  • 但他在之前检查其状态
  • 他可能正在检查不同的内存位置,*g 可能指的是最高有效 8 位,而不是他所期望的最低有效位。
  • @BlackBear: SET(1, flag2) 可能在与1 &amp; *g 测试的字符不同的字符中设置了位。
  • @bobbogo,@eric:是的,我错过了那个细节。 :)
  • 是的,这就是我所期待的,这就是为什么忽略初始化没有被隐藏起来。
【解决方案3】:

来自维基百科的pointers

C 标准的 2005 年草案 需要转换一个指针 从一种类型派生到其中之一 另一种类型应保持 两种类型的对齐正确性 (6.3.2.3 指针,第 7 段):[3]

char *external_buffer = "abcdef";
int *internal_data;

internal_data = (int *)external_buffer;  // UNDEFINED BEHAVIOUR if "the resulting pointer
                                         // is not correctly aligned"

底线:使用正确的指针类型

该行为可能会按预期工作,但不能保证。

C++03 标准 $5.3.3/1 说,

sizeof(char), sizeof(signed char) and sizeof(unsigned char) are 1; the

sizeof 的结果应用于任何其他 基本类型(3.9.1)是 实现定义。 [注:在 特别是 sizeof(bool) 和 sizeof(wchar_t) 是 实现定义.69)

看这个:C++ Size of primitives

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-05-16
    • 2023-04-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-15
    • 2011-08-02
    • 2011-04-15
    相关资源
    最近更新 更多