开发者

x64 compatible C source

开发者 https://www.devze.com 2022-12-14 11:35 出处:网络
I think I know what #ifdefs I need to use to be x86-32 and x86-64 compatible on both msvc and gcc, see below. Is this complete for those platforms?

I think I know what #ifdefs I need to use to be x86-32 and x86-64 compatible on both msvc and gcc, see below. Is this complete for those platforms?

#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

Are IA64 and x86 64 the same from a C programmer's perspective?

I'd also like to be able to compile on Macs. What do开发者_StackOverflow中文版 I add?

Edit: I can't use sizeof(), as I'm dealing with untouchable legacy code that use stuff like #if SIZEOF_VOIDP == SIZEOF_LONG. I am also only interested in the architectures, not the actual contents. Note that the precompiler does not allow #if sizeof(size_t) == sizeof(void*).


How about using your build system to generate these as constants

#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 ;
}

Provided your build system is consistent, where everything is built with the same options, this builds in implicit portability, and you deal with the problems in your ifdefs where you've got sizeof(long) wrong on 64-bit ia64 and x64 windows (even with the gcc compiler which you've assumed to mean non-windows).

Backing this up with the static asserts mentioned in a different answer would then give you the best of both worlds.


If you're doing a lot of cross-platform/cross-compiler work then it may be worth adding static asserts for those constants so you can at least catch platform/compiler combinations that are not set in your ifdefs.

In C++ with boost:

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

If you're working in C there are a couple of questions on here about implementing static assertions in C.

Macs use a customised version of GCC, so many of the constants you use for GCC should also work on the Mac. I typically detect OSX builds with

#ifdef __APPLE__
#endif

but I'm not sure if this is the best way. On my (32-bit) 10.4 OSX install both a long and void* occupy 4 bytes.


All those defines look pretty reduntant to me. Just use sizeof(void*) and friends.

If you need to have your constants defined, define them like

#define SIZEOF_VOIDP sizeof(void*)


Why don't you use sizeof operator?

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


Beware! On Windows, whether you are i386 (i.e. x86_32) or x86_64, you will have sizeof(long) == 4 ! (Or #define SIZEOF_LONG 4). Whereas sizeof(void *) == 8 !

sizeof(long) != sizeof(void *)


One point to consider about #define SIZEOF_LONG 8 and #define SIZEOF_VOIDP 8.

On HP-UX IA64 this program:

#include <iostream>

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

if compiled like this:

g++ -mlp64 main.cpp

gives: 8 8

but if compiled like this:

g++ -milp32 main.cpp

gives 4 4


No, it is not complete.

Only sizeof (char) is the same on all platforms, compiler options, ...
All other types are not guaranteed to be the same, to stay the same after compiling with different options, ...

You need

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

...


//may be this helps to understand

//with MSC or BORLAND it was possible to do this

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

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

the GNU Compiler don't resolve this #if(sizeof(int) == 4) he quit this with error message!

0

精彩评论

暂无评论...
验证码 换一张
取 消