【问题标题】:check void pointer size in macro c检查宏 c 中的 void 指针大小
【发布时间】:2013-12-08 13:44:23
【问题描述】:

我需要检查 void 指针是否适合 8 个字节,所以我检查它的长度是 4 还是 8。我知道这些值只是,我可以使用 _W64,只是一个好奇的检查。

#include <windows.h>
#if (sizeof(void *) == 4)
#define IS64 0
#elif (sizeof(void *) == 8)
#define IS64 1
#else
#error "Pointer size 4 nor 8, make changes in app"
#endif
int APIENTRY WinMain(HINSTANCE hInstance,
        HINSTANCE hPrevInstance, 
        LPTSTR    lpCmdLine, 
        int       cmdShow)
{
    if (IS64) MessageBoxA(NULL, "is 64", "info", MB_OK);
    else MessageBoxA(NULL, "is 32", "info", MB_OK);
    return(0);
}

此代码不起作用,我收到错误app.c(2) : fatal error C1017: invalid integer constant expression

我把宏改成:

#if (sizeof(void *) == sizeof(int32_t))
#define IS64 0
#elif (sizeof(void *) == sizeof(int64_t))
#define IS64 1
#else
#error "Pointer size 4 nor 8, make changes in app"
#endif

同样的错误。这里有什么解决方法吗?

【问题讨论】:

  • #define IS64 (sizeof(void*)==8)
  • @WhozCraig 这是一个很好的宏和一个很好的解决方法。我怀疑他想要一个预处理器条件表达式,这是不允许的,因为预处理器无法明显理解 sizeof。
  • @Jekyll 当然,因此它是评论而不是答案。我不明白他为什么不只是使用 MS 预定义,但我确信这是有原因的。哦等等,他说他是,只是好奇为什么这不起作用。纳米=P
  • @WhozCraig 所以我的评论实际上就是答案?我也不确定他想达到什么目的
  • 我决定使用#define IS64 (if(sizeof(void*)==4) ? 0 : (if(sizeof(void*)==8) ? 1 : exit(1) /*Or some message box*/))

标签: c pointers visual-studio-2008 macros windows-xp


【解决方案1】:

GCC 自带一堆预处理器定义;

为了解决这个特定问题,它提供了__SIZEOF_POINTER__,其值是 8 或 4,具体取决于架构。

我不是 MS 编译器的专家,但我猜他们提供了等效的定义;

对参数的快速搜索(来源:https://docs.microsoft.com/it-it/cpp/preprocessor/predefined-macros?view=vs-2019显示以下内容:

_M_AMD64 定义为针对 x64 处理器的编译的整数文字值 100。否则,未定义。

_M_ARM 为针对 ARM 处理器的编译定义为整数文字值 7。否则,未定义。

_M_ARM_ARMV7VE 当为针对 ARM 处理器的编译设置 /arch:ARMv7VE 编译器选项时,定义为 1。否则, 未定义。

_M_ARM_FP 定义为整数文字值,指示为 ARM 处理器目标设置的 /arch 编译器选项。否则, 未定义。

_M_ARM64 为针对 64 位 ARM 处理器的编译定义为 1。否则,未定义。

使用这些信息,您可以为您的定义分配一个值。

【讨论】:

    【解决方案2】:

    sizeof 运算符的使用在宏中无效,因为它不是 cpp 的一部分,而是 C 语言的一部分。但是您仍然可以在编译时进行此检查而无需额外费用,因为好的编译器会删除这样的死代码。事实上,它是一些编码标准推荐的。

    编辑:要将此测试留给编译,您需要这样:

    int IS64;
    if (sizeof(void *) == 4)
     IS64  = 0;
    else if (sizeof(void *) == 8)
     IS64 = 1;
    else
    printf ("Pointer size 4 nor 8, make changes in app\n");
    

    然后:

       if (IS64) MessageBoxA(NULL, "is 64", "info", MB_OK);
        else MessageBoxA(NULL, "is 32", "info", MB_OK);
    

    一个好的编译器会删除死代码,即返回值sizeof()(如果未在 VLA 中使用)始终是一个常量值,如果它是 48 和你正在做的编译器 @ 987654328@ 或 8 == 88 == 4 它将执行 DCE 并且您的程序中将只有 MessageBoxA() 没有 if (IS64) 检查。

    【讨论】:

    • 这只是部分正确。预处理器提供类型通用宏,它们某种语言感知的。
    • 你说的是C11的_Generic()吗?我以前不知道。
    • 如果我告诉编译器将其编译为 c 代码,我的代码也不起作用。
    • 再想一想,我认为你是完全正确的,预处理器与 C 语言无关——类型通用代码是 C 语言的一部分(由 _Generic 关键字提供) ,而预处理器看不到任何内容。
    猜你喜欢
    • 2021-12-16
    • 1970-01-01
    • 1970-01-01
    • 2015-05-03
    • 2011-04-01
    • 2010-09-29
    • 2023-04-11
    相关资源
    最近更新 更多