问题描述
我想检查一个 GUID 结构是否为空/所有字段都是 0.这是我写的代码:
I want to check if a GUID structure is empty/all fields are 0. This is the code I wrote:
#include <windows.h>
static BOOL IsEmptyGuid(const GUID * const pGuid)
{
return \
(pGuid->Data1 == 0) &&
(pGuid->Data2 == 0) &&
(pGuid->Data3 == 0) &&
#ifdef _WIN64
(*(DWORD64 *)pGuid->Data4 == 0);
#else
(*(DWORD *)pGuid->Data4 == 0) && (*(DWORD *)(pGuid->Data4 + 4) == 0);
#endif
}
/* GUID definition from MSDN
typedef struct _GUID {
DWORD Data1;
WORD Data2;
WORD Data3;
BYTE Data4[8];
} GUID;
*/
int main() {
GUID guid1;
guid1.Data1 = 0;
guid1.Data2 = 0;
guid1.Data3 = 0;
memset(guid1.Data4, 0x0, 8);
printf("Result: %u\n", IsEmptyGuid(&guid1));
}
检查字段 Data4
是否等于 0 的更安全方法是遍历每个字节并检查其值.但是,我发现上面的代码更具表现力.
A safer way to check if field Data4
equals 0 is to iterate over every byte and check for it's value. But, I find the code from above more expressive.
我想知道,对吗?安全吗?
I would like to know, is it correct? Is it safe?
谢谢!
推荐答案
代码不正确.它违反了严格的别名规则(N1570 §6.5 p7),导致未定义的行为.
Code is incorrect. It breaks strict aliasing rule (N1570 §6.5 p7), causing undefined behaviour.
一个对象只能通过左值表达式访问其存储的值,该表达式具有以下之一以下类型:
- 与对象的有效类型兼容的类型,
- 与对象的有效类型兼容的类型的限定版本,
- 一个类型,它是对应于有效类型的有符号或无符号类型对象,
- 一种类型,它是对应于限定版本的有符号或无符号类型对象的有效类型,
- 一个聚合或联合类型,其中包括上述类型之一成员(包括递归地,子聚合或包含联合的成员),或
- 一种字符类型.
确切地说,UB 在您使用非匹配类型取消引用指针时发生:
To be exact, UB happens when you dereference pointer using non-matching type:
DWORD64 * temp = (DWORD64 *)pGuid->Data4; // Allowed, but implementation defined
DWORD64 temp2 = *temp; // Undefined behaviour
使用循环单独检查每个元素,或与 memcmp
比较到相同大小的零填充数组.
Use loop to check each element individually, or compare with memcmp
to zero filled array of the same size.
如评论中所述,某些编译器允许禁用严格别名,但应避免这样做,因为它会降低代码的可移植性,并且您仍然存在潜在的对齐问题.
As noted in the comments, some compilers allow disabling strict aliasing, but that should be avoided as it makes code less portable, and you still have potential alignment issues.
这篇关于检查 GUID 是否为空(在 C 中)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!