【问题标题】:x64 compatible C sourcex64 兼容的 C 源代码
【发布时间】:2009-12-17 12:02:33
【问题描述】:

我想我知道我需要使用什么 #ifdefs 才能在 msvc 和 gcc 上兼容 x86-32 和 x86-64,见下文。这些平台是否完整?

#if defined(_MSC_VER)
#  if defined(_M_IA64) || defined(_M_X64)
#    define SIZEOF_SIZE_T 8
#    define SIZEOF_VOIDP  8
#  elif defined(_M_IX86)
#    define SIZEOF_SIZE_T 4
#    define SIZEOF_VOIDP  4
#  else
#    error "Unsupported MSVC platform"
#  endif
#elif defined(__GNUG__)
#  if defined(__x86_64__) || defined(__ia64__)
#    define SIZEOF_SIZE_T 8
#    define SIZEOF_VOIDP  8
#  elif defined(__i386__)
#    define SIZEOF_SIZE_T 4
#    define SIZEOF_VOIDP  4
#  else
#    error "Unsupported GCC platform"
#  endif
#endif

从 C 程序员的角度来看,IA64 和 x86 64 是否相同?

我还希望能够在 Mac 上编译。我要添加什么?

编辑:我不能使用 sizeof(),因为我正在处理使用像 #if SIZEOF_VOIDP == SIZEOF_LONG 这样的东西的不可触碰的遗留代码。我也只对架构感兴趣,而不是实际内容。注意预编译器不允许#if sizeof(size_t) == sizeof(void*)

【问题讨论】:

  • sizeof (void*) 也是编译时间常数时,为什么要#defining 常量?
  • 需要预编译时间常数。
  • 完整,因为我涵盖了这两种架构。还想添加 Mac 架构,无论是哪一种。
  • 我不明白你为什么不能做#define SIZEOF_LONG sizeof(long)
  • 预编译器不允许#if sizeof(whatever) == sizeof(other)。

标签: c 64-bit portability itanium


【解决方案1】:

如何使用您的构建系统将这些生成为常量

#include <stdio.h>

int main()
{
   printf(
      "#if !defined ARCH_MODEL_CONSTANTS_H\n"
      "#define ARCH_MODEL_CONSTANTS_H\n"
      "\n"
      "#    define SIZEOF_LONG  %u\n"
      "#    define SIZEOF_VOIDP %u\n"
      "\n"
      "#endif\n",
      (unsigned)sizeof(long),
      (unsigned)sizeof(void *) ) ;

   return 0 ;
}

如果你的构建系统是一致的,所有的东西都是用相同的选项构建的,这就建立了隐式的可移植性,并且你处理了 ifdefs 中的问题,你在 64 位上遇到了 sizeof(long) 错误ia64 和 x64 窗口(即使使用您认为是非窗口的 gcc 编译器)。

用另一个答案中提到的静态断言来支持这一点会给你两全其美。

【讨论】:

  • 好主意 - 我什至可以保留我的简约自制构建系统!
【解决方案2】:

如果您正在进行大量跨平台/跨编译器工作,那么可能值得为这些常量添加静态断言,这样您至少可以捕获未在 ifdef 中设置的平台/编译器组合。

在带有 boost 的 C++ 中:

#include <boost/static_assert.hpp>
BOOST_STATIC_ASSERT(sizeof(void*) == SIZEOF_VOIDP)
BOOST_STATIC_ASSERT(sizeof(long)  == SIZEOF_LONG)

如果您使用 C 语言工作,这里有几个关于在 C 语言中实现静态断言的问题。

Mac 使用定制版本的 GCC,因此您用于 GCC 的许多常量也应该适用于 Mac。我通常使用

检测 OSX 构建
#ifdef __APPLE__
#endif

但我不确定这是否是最好的方法。在我的(32 位)10.4 OSX 上安装 long 和 void* 占用 4 个字节。

【讨论】:

    【解决方案3】:

    所有这些定义对我来说都是多余的。只需使用sizeof(void*) 和朋友。

    如果您需要定义常量,请像这样定义它们

    #define SIZEOF_VOIDP sizeof(void*)
    

    【讨论】:

      【解决方案4】:

      为什么不使用 sizeof 运算符?

      sizeof(long);
      sizeof(int);
      sizeof(void*);
      

      【讨论】:

      • 我需要遵守类似于 #ifdef SIZEOF_LONG == SIZEOF_VOIDP...的遗留代码...
      • 你可以定义像#define SIZEOF_LONG (sizeof(long)) 这样的宏,它们总是正确的。
      • 预编译器(至少是 msvc 的)不允许它们出现在 #if 语句中。
      【解决方案5】:

      小心!在 Windows 上,无论您是i386(即x86_32)还是x86_64,您都将拥有sizeof(long) == 4! (或#define SIZEOF_LONG 4)。而sizeof(void *) == 8!

      sizeof(long) != sizeof(void *)

      【讨论】:

      • 这也适用于 IA64 吗?从 C 程序员的角度来看,您知道 IA64 和 x64 是否存在差异?
      • @Jonas:我不知道。我从来没有编程过,可以访问 IA64 系统。
      • 更多关于 ILP64、LP64 和 LLP64 的信息:unix.org/version2/whatsnew/lp64_wp.html
      【解决方案6】:

      关于#define SIZEOF_LONG 8#define SIZEOF_VOIDP 8 需要考虑的一点。

      在 HP-UX IA64 上这个程序:

      #include <iostream>
      
      int main()
      {
      #if defined(__ia64__) && defined(__GNUG__)
          std::cout << sizeof(long) << std::endl;
          std::cout << sizeof(void*) << std::endl;
      #endif
          return 0;
      }
      

      如果这样编译:

      g++ -mlp64 main.cpp
      

      给出: 8 8

      但如果这样编译:

      g++ -milp32 main.cpp
      

      给予 4 4

      【讨论】:

      • 哼,你有没有得到某种类型的#define 来识别你编译的模式?
      • 据我所知__LP64___LP64是在-mlp64模式下定义的。
      【解决方案7】:

      不,不完整。

      只有sizeof (char) 在所有平台、编译器选项、...
      上都是相同的 不保证所有其他类型都一样,用不同的选项编译后保持不变,...

      你需要

      sizeof (short)
      sizeof (int)
      sizeof (long)
      sizeof (long long) // C99
      sizeof (float)
      sizeof (double)
      sizeof (long double) // C99
      sizeof (void *)
      sizeof (char *)
      sizeof (long double *) // C99
      
      ...
      

      【讨论】:

      • 只对架构感兴趣,不需要实际内容。
      【解决方案8】:

      //这可能有助于理解

      //使用 MSC 或 BORLAND 可以做到这一点

      #if(sizeof(int) == 4)
          typedef int32  int;
      #endif
      
      #if(sizeof(int) == 8)
          typedef int64  int;
      #endif
      

      GNU 编译器无法解决此问题#if(sizeof(int) == 4) 他退出了这个并显示错误消息!

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-11-04
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多