作为这个问题的背景,这是我编写的一个测试程序,用于调查我在我工作的消息传递程序中看到的一些奇怪的行为。我们有各种结构使用位标志来保存有关消息的状态,一些标志使用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;
}
答案 0 :(得分:4)
AIX是一个大端架构,这意味着g
指向flag
的最重要字节。这意味着对最低有效字节的任何更改对g
都是不可见的。
flag2
也从未初始化,因此它将包含一些arbirary值。所以事实证明,当它只是开头的那些生活价值时,你会认为有点设置有效。
如果你在像x86这样的小端机器上运行,事情应该按照预期运行。
答案 1 :(得分:0)
我看到了一些可能成为问题的事情。
您尚未初始化flag2
你可能想要施放g= (short *
) &flag2
,因为如果你施展
char你不一定会
获得最少的参考
重要的8位。
答案 2 :(得分:0)
来自维基百科的pointers:
2005年C标准草案 需要投射指针 从一种类型派生到一种类型 另一种类型应该保持 两种类型的对齐正确性 (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)是 实施-defined.69)