有人可以帮我解释一下代码吗?
为什么32位UINT
?
为什么0xff
?
这里有4个正确的转变吗?
int writeUINT32little(FILE *f, UINT32 i)
{
int rc;
rc = fputc((i & 0xff), f);
if (rc == EOF) return rc;
rc = fputc(((i >> 8) & 0xff), f);
if (rc == EOF) return rc;
rc = fputc(((i >> 16) & 0xff), f);
if (rc == EOF) return rc;
return fputc(((i >> 24) & 0xff), f);
}
答案 0 :(得分:8)
这需要一个32位无符号整数,并将其输出到一个文件,逐字节,最低有效字节(即little-endian)。
0xff
是以十进制编写255
或以二进制编写11111111
的十六进制方式。 &
是按位and
函数。放在一起,(i & 0xff)
掩盖整数的最低有效字节。
然后,移位将整个事物移位到8位,并重复该过程以打印下一个字节。
答案 1 :(得分:1)
这个函数应该做的是将一个32位无符号整数写入little-endian的文件流中。
它真正做的是,它不是做一个简单的小任务并且做得对,而是尝试一起做两件事并且两者都错了。
在我说明为什么这是错的之前,我会快速回答这个问题:
UINT32
?不知道。这是非标准的,最好用uint32_t
替换。0xff
?用作掩码,将较低的8位保存在较大的变量(32位)<小时/> 现在,有了这个......
为什么这是错的?
char
保证为at least 8 bits wide,但可能更大。这意味着fputc
每次调用可能会写入8位,但可能写得更多。这意味着在一个char(例如)16位的某个架构上,该函数每次调用将写入64位,并且它根本不会是小端。此外,该函数非常仔细地检查错误,但不会将相关的失败信息暴露给调用者(写入了多少字节?)。
什么是更好的设计?
首先,一如既往,做一件小事,做得对:
uint32_t toLittleEndian(uint32_t v)
{
uint32_t result = v >> 24;
result |= v << 24;
result |= (v >> 8) & 0xf0;
result |= (v << 8) & 0xf00;
return result;
}
注意:此实现是故意冗长的。使用位旋转操作有一个优化机会,但C没有本机支持,需要汇编代码
此函数仅将big-endian 32位值转换为其等效的little-endian表示(实际上它在两者之间交替,可以命名为switchEndian
)。
接下来,我们需要将值写入文件:
int write(uint32_t v, FILE *f)
{
return fwrite(&v, sizeof(v), 1, f);
}
这将写入完全 32位宽的整数,并返回实际写入的字节数。此外,它可以重复使用。
接下来,如果我们想要,我们可以创建一个便利的复合函数:
int writeLittleEndian(uint32_t v, FILE *f)
{
return write(toLittleEndian(v), f);
}