输出中C结构组件中的前导0xff
一些最奇怪的事情正在发生。遵循代码:输出中C结构组件中的前导0xff,c,struct,C,Struct,一些最奇怪的事情正在发生。遵循代码: #include <stdlib.h> #include <assert.h> #include <stdio.h> struct s { char a; char b; char c; unsigned int d; unsigned int e; }__attribute__((packed)); int main(void) { struct s *m = (void *)malloc(
#include <stdlib.h>
#include <assert.h>
#include <stdio.h>
struct s
{
char a;
char b;
char c;
unsigned int d;
unsigned int e;
}__attribute__((packed));
int main(void)
{
struct s *m = (void *)malloc(sizeof (struct s));
assert(m);
m->a=0x33;
m->b=0x33;
m->c=0x33;
m->d=0xabcdefab;
m->e=0x12345678;
*(char *)(m + 1) = 0;
while (*((char*)m))
{
printf("%p -> %x\n", m, *((char *)m));
m = (struct s *)((char*) m + 1);
}
}
到现在为止,您可能已经发现了输出中的奇异性。实际上,在地址0x85a013到0x85a016的内存中没有“0xff”,每个字节也没有4个字节?!?!(我的意思是,这是合乎逻辑的吗?)。在我看来,这似乎是一个显示问题,但我无法找出原因或方式。编辑
将(字符*)
强制转换为(无符号字符*)
。为了防止未定义的行为,不要尝试发布哨兵,而是使用struct size。我的版本:
#include <stdlib.h>
#include <assert.h>
#include <stdio.h>
#pragma pack(push, 1)
struct s
{
char a;
char b;
char c;
unsigned int d;
unsigned int e;
};
#pragma pack(pop)
int main(void)
{
int i;
unsigned char *cptr;
struct s *m = malloc(sizeof (struct s));
assert(m);
m->a=0x33;
m->b=0x33;
m->c=0x33;
m->d=0xabcdefab;
m->e=0x12345678;
cptr = (unsigned char*)m;
for (i=0; i<sizeof(struct s); i++)
printf("%p -> %02x\n", (void*)(cptr+i), cptr[i]);
}
编辑
将(字符*)
强制转换为(无符号字符*)
。为了防止未定义的行为,不要尝试发布哨兵,而是使用struct size。我的版本:
#include <stdlib.h>
#include <assert.h>
#include <stdio.h>
#pragma pack(push, 1)
struct s
{
char a;
char b;
char c;
unsigned int d;
unsigned int e;
};
#pragma pack(pop)
int main(void)
{
int i;
unsigned char *cptr;
struct s *m = malloc(sizeof (struct s));
assert(m);
m->a=0x33;
m->b=0x33;
m->c=0x33;
m->d=0xabcdefab;
m->e=0x12345678;
cptr = (unsigned char*)m;
for (i=0; i<sizeof(struct s); i++)
printf("%p -> %02x\n", (void*)(cptr+i), cptr[i]);
}
编辑
将(字符*)
强制转换为(无符号字符*)
。为了防止未定义的行为,不要尝试发布哨兵,而是使用struct size。我的版本:
#include <stdlib.h>
#include <assert.h>
#include <stdio.h>
#pragma pack(push, 1)
struct s
{
char a;
char b;
char c;
unsigned int d;
unsigned int e;
};
#pragma pack(pop)
int main(void)
{
int i;
unsigned char *cptr;
struct s *m = malloc(sizeof (struct s));
assert(m);
m->a=0x33;
m->b=0x33;
m->c=0x33;
m->d=0xabcdefab;
m->e=0x12345678;
cptr = (unsigned char*)m;
for (i=0; i<sizeof(struct s); i++)
printf("%p -> %02x\n", (void*)(cptr+i), cptr[i]);
}
编辑
将(字符*)
强制转换为(无符号字符*)
。为了防止未定义的行为,不要尝试发布哨兵,而是使用struct size。我的版本:
#include <stdlib.h>
#include <assert.h>
#include <stdio.h>
#pragma pack(push, 1)
struct s
{
char a;
char b;
char c;
unsigned int d;
unsigned int e;
};
#pragma pack(pop)
int main(void)
{
int i;
unsigned char *cptr;
struct s *m = malloc(sizeof (struct s));
assert(m);
m->a=0x33;
m->b=0x33;
m->c=0x33;
m->d=0xabcdefab;
m->e=0x12345678;
cptr = (unsigned char*)m;
for (i=0; i<sizeof(struct s); i++)
printf("%p -> %02x\n", (void*)(cptr+i), cptr[i]);
}
这是由有符号整数提升引起的。%x的
printf
说明符至少需要一个完整的int
值
为了避免值大小的各种问题,变量参数函数,如printf
将值至少转换为int
和double
大小
这意味着像0xab这样的
signed char
值被符号扩展为32位0xffffffab
这是由有符号整数提升引起的。%x的printf
说明符至少需要一个完整的int
值
为了避免值大小的各种问题,变量参数函数,如printf
将值至少转换为int
和double
大小
这意味着像0xab这样的
signed char
值被符号扩展为32位0xffffffab
这是由有符号整数提升引起的。%x的printf
说明符至少需要一个完整的int
值
为了避免值大小的各种问题,变量参数函数,如printf
将值至少转换为int
和double
大小
这意味着像0xab这样的
signed char
值被符号扩展为32位0xffffffab
这是由有符号整数提升引起的。%x的printf
说明符至少需要一个完整的int
值
为了避免值大小的各种问题,变量参数函数,如printf
将值至少转换为int
和double
大小
这意味着像0xab这样的
signed char
值被符号扩展为32位0xffffffab
格式说明符%x
需要printf
中的unsigned int
参数。仅当int
值为非负值时,才允许在其位置使用int
参数。如果该值为负值,则行为未定义
您正在为%x
格式说明符传递一个char
参数。变量char
参数自动转换为int
,并作为int
传递。如果原始的char
(以及由此产生的int
)恰好具有负值,则该行为未定义。这显然就是你的情况。您的ff
输出是使用%x
格式说明符打印负int
值的无效尝试的结果
您可以用几种不同的方法修复损坏的代码。例如,您可以将printf
参数显式转换为unsigned int
类型
printf("%p -> %x\n", (void *) m, (unsigned) *((char *)m));
这将消除未定义的行为,但很可能保持输出不变。现在,ff
将显示为负值到unsigned int
类型的模转换的[完美定义]结果
这个
这也是一种形式上有问题的做法。该语言不保证
结构
指针可以保留字符*
指针的精确值。格式说明符%x
需要printf
中的无符号int
参数。仅当int
值为非负值时,才允许在其位置使用int
参数。如果该值为负值,则行为未定义
您正在为%x
格式说明符传递一个char
参数。变量char
参数自动转换为int
,并作为int
传递。如果原始的char
(以及由此产生的int
)恰好具有负值,则该行为未定义。这显然就是你的情况。您的ff
输出是使用%x
格式说明符打印负int
值的无效尝试的结果
您可以用几种不同的方法修复损坏的代码。例如,您可以将printf
参数显式转换为unsigned int
类型
printf("%p -> %x\n", (void *) m, (unsigned) *((char *)m));
这将消除未定义的行为,但很可能保持输出不变。现在,ff
将显示为负值到unsigned int
类型的模转换的[完美定义]结果
这个
这也是一种形式上有问题的做法。该语言不能保证
struct
指针可以保留char*
指针的精确值。格式说明符%x