我们知道,由于对齐原因,结构可以具有内部填充字节。
如何用特定值填充非紧凑结构的所有填充字节?换句话说,请考虑以下代码段:
struct Foo;
// Is that possible to implement pad_Foo() function? If Yes, How?
void pad_Foo(struct Foo *pFoo_x, char pad_byte);
void bar(struct Foo *pFoo_x, int fd, char pad_byte)
{
// reading in *pFoo_x from a file.
// It may get some garbage padding bytes.
read(fd, pFoo_x, sizeof(struct Foo));
pad_Foo(&x, pad_byte);
}
是否可以实现pad_Foo()函数,如果答案是肯定的,怎么办?
答案 0 :(得分:1)
是否可以实现pad_Foo()函数
作为符合标准的代码,答案为否
根据C11草案n1570,6.2.6类型表示:
6当值存储在结构或联合类型的对象中(包括成员对象中)时,与任何填充字节对应的对象表示形式的字节采用未指定的值。 51)
和
51)因此,例如,结构分配不需要复制任何填充位。
因此标准明确指出:填充的值无法控制。
在特定系统(平台,操作系统,编译器)上,这是可能的。以我的系统为例:
# include <stdio.h>
# include <string.h>
struct s
{
char c;
int n;
};
void dump_struct(struct s * p)
{
unsigned char * u = (unsigned char *)p;
for (size_t i=0; i < sizeof *p; ++i) printf("%02x ", u[i]);
printf("\n");
}
int main(){
printf("sizeof(struct s)=%zu sizeof(char)=%zu sizeof(int)=%zu padding=%zu\n",
sizeof(struct s),
sizeof(char),
sizeof(int),
sizeof(struct s) - sizeof(char) - sizeof(int));
struct s sa;
memset(&sa, 'A', sizeof sa);
sa.c = '8';
sa.n = 42;
dump_struct(&sa);
struct s sb;
memset(&sb, 'B', sizeof sa);
sb.c = '8';
sb.n = 42;
dump_struct(&sb);
}
输出:
sizeof(struct s)=8 sizeof(char)=1 sizeof(int)=4 padding=3
38 41 41 41 2a 00 00 00
38 42 42 42 2a 00 00 00
^^^^^^^^
notice
因此,在我的系统上,memset
确实写入了填充字节,但是在其他系统上,您可能会看到不同的行为。
将这样的代码添加到main
:
unsigned char * u = (unsigned char *)&sb.c;
u += sizeof sb.c;
while(u < (unsigned char *)&sb.n)
{
*u = 'C';
++u;
}
dump_struct(&sb);
将打印多余的行:
38 43 43 43 2a 00 00 00
再次-在我的特定系统上-填充已更改。