x64 совместимый источник C - PullRequest
0 голосов
/ 17 декабря 2009

Я думаю, что знаю, какие #ifdefs мне нужно использовать, чтобы быть совместимыми с x86-32 и x86-64 на msvc и gcc, см. Ниже. Это завершено для этих платформ?

#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

Являются ли IA64 и x86 64 одинаковыми с точки зрения программиста на C?

Я также хотел бы иметь возможность компилировать на Mac. Что мне добавить?

Редактировать: Я не могу использовать sizeof (), так как я имею дело с неприкасаемым устаревшим кодом, который использует такие вещи, как #if SIZEOF_VOIDP == SIZEOF_LONG. Я также интересуюсь только архитектурой, а не фактическим содержанием. Обратите внимание, что прекомпилятор не позволяет #if sizeof(size_t) == sizeof(void*).

Ответы [ 8 ]

6 голосов
/ 17 декабря 2009

Как насчет использования вашей системы сборки для генерации этих констант

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

При условии, что ваша система сборки совместима, где все построено с одинаковыми параметрами, это подразумевает неявную переносимость, и вы решаете проблемы в ваших ifdef с ошибками sizeof(long) в 64-битных системах. окна ia64 и x64 (даже с компилятором gcc, который, как вы предполагали, означают не-окна).

Если подкрепить это статическими утверждениями, упомянутыми в другом ответе, то вы получите лучшее из обоих миров.

2 голосов
/ 17 декабря 2009

Если вы выполняете большую работу по кроссплатформенности / кросс-компиляции, возможно, стоит добавить статические утверждения для этих констант, чтобы вы могли по крайней мере перехватывать комбинации платформы / компилятора, которые не заданы в ваших ifdefs. *

В 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 байта.

2 голосов
/ 17 декабря 2009

Все эти определения выглядят довольно избыточно для меня. Просто используйте sizeof(void*) и друзей.

Если вам нужно определить свои константы, определите их как

#define SIZEOF_VOIDP sizeof(void*)
1 голос
/ 17 декабря 2009

Один пункт, чтобы рассмотреть около #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

1 голос
/ 17 декабря 2009

Осторожно! В Windows, будь вы i386 (т.е. x86_32) или x86_64, у вас будет sizeof(long) == 4! (Или #define SIZEOF_LONG 4). Тогда как sizeof(void *) == 8!

sizeof(long) != sizeof(void *)

1 голос
/ 17 декабря 2009

Почему вы не используете оператор sizeof?

sizeof(long);
sizeof(int);
sizeof(void*);
0 голосов
/ 03 мая 2013

// может быть, это помогает понять

// с MSC или BORLAND это можно было сделать

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

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

Компилятор GNU не разрешает это #if(sizeof(int) == 4) он вышел с сообщением об ошибке!

0 голосов
/ 17 декабря 2009

Нет, оно не завершено.

Только 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

...
...