我使用以下C结构体来报告2D游戏中的跟踪结果。
typedef struct TraceResult
{
bool collided;
bool beganColliding;
bool endedColliding; // If the trace ended while still inside a collider
float fraction;
Vector2 endPosition;
Vector2 contactNormal;
struct Entity* collisionEnt;
ComponentType collisionComponentType;
} TraceResult;
结构被初始化如下:
TraceResult workingResult = TraceRectangleMovementAgainstTerrain(
hull,
delta,
Entity_GetTerrainComponent(ent),
collisionMask
);
调用完成后,将结构体传回给前一个函数的调用者。我在return语句前面放了一个printf
,它报告了接触正常值是预期的:
printf("Contact normal before returning: (%.2f, %.2f)n", workingResult.contactNormal.x, workingResult.contactNormal.y);
return workingResult;
Contact normal before returning: (0.00, -1.00)
然而,在返回结构体的函数调用之后,我有另一个printf
语句。这报告了接触法向是不同的-它似乎已经采取了endPosition
成员之前的值:
printf("Contact normal after returning: (%.2f, %.2f)n", result.contactNormal.x, result.contactNormal.y);
Contact normal after returning: (995.00, 150.00)
当我在Ubuntu上运行应用程序时,这个问题不会发生,只有在Windows上才会发生。有时通过复制返回TraceResult
是可以的,但其他时候这些值似乎会像这样损坏。是我疯了,还是编译器不配合?
我最终解决了这个问题:问题是我忽略了在定义结构体的头文件中添加#include <stdbool.h>
。一旦我添加了这个,一切都开始像预期的那样工作。
我最初感到困惑,为什么这是这种情况-当然,如果没有bool
的定义,编译器应该抛出一个错误?然而,经过一番搜索,我在我的第三方库头之一中找到了这个:
#if defined(__STDC__) && __STDC_VERSION__ >= 199901L
#include <stdbool.h>
#elif !defined(__cplusplus) && !defined(bool)
typedef enum bool { false, true } bool;
#define RL_BOOL_TYPE
#endif
根据快速谷歌,MSVC只有在使用/Za编译选项时才定义__STDC__
。因为我没有打开这个开关,所以库头使用了自己的bool
类型,因为这是一个enum,所以它是4字节而不是1字节。这引起了关于结构体成员偏移量的混淆,这取决于编译单元在遇到结构体定义时是否可以看到stdbool.h
。
我要做一些事情来解决这个问题:
- 我要在我的CMake项目中设置一个适当的C标准(我的错)。
- 我有一个包装这个库头文件的头文件,因为我为它定义了一些额外的东西。我要添加
stdbool.h
到这个标题只是以防万一。 我要向图书馆提交一份PR,加强
#ifdef
检查。显然,MSVC从VS2013开始支持C99,因此如果定义了_MSC_VER
并且至少是1800
,则检查可以升级为包括stdbool.h
。