Как я могу гарантировать, что два типа имеют одинаковый размер? - PullRequest
6 голосов
/ 05 октября 2011

В своем коде я хочу убедиться, что sizeof(a) == sizeof(b).

Первый подход состоял в том, чтобы позволить препроцессору выполнить проверку:

#if (sizeof(a) != sizeof(b))
#  error sizes don't match
#endif

, которая не компилируется из-за fatal error C1017: invalid integer constant expression.Хорошо.Поймите.

Следующая попытка:

if(sizeof(a) != sizeof(b)){
  printf("sizes don't match\n");
  return -1;
}

В результате выдается предупреждение: warning C4127: conditional expression is constant.

Теперь я застрял.Существует ли безошибочный способ убедиться, что две структуры a и b имеют одинаковый размер?


Редактировать: Компилятор визуальныйStudio 2005, уровень предупреждения установлен на 4.

Ответы [ 4 ]

6 голосов
/ 05 октября 2011

Неверный размер массива

// make sure sizeof(a) == sizeof(b):
int size_must_match[sizeof(a) == sizeof(b)];
// will fail if sizeof(a) == sizeof(b) evaluates to 0
// might produce warning: 'size_must_match' is not used 

// to suppress "'size_must_match' is not used", try:
size_must_match[0]; // might produce warning: "statement has no effect"

или

typedef int size_must_match[sizeof(a) == sizeof(b)];

Плохая арифметика времени компиляции

В C ++ гарантируется, что эти константные выражения оцениваются компилятором ввремя компиляции, и я считаю, что то же самое верно в C:

// make sure sizeof(a) == sizeof(b):
1 / (sizeof(a) == sizeof(b));
// might produce warning: "statement has no effect"

int size_must_match = 1 / (sizeof(a) == sizeof(b));
// might produce warning: 'size_must_match' is unused

assert (1 / (sizeof(a) == sizeof(b)));
// very silly way to use assert!

Switch (просто для удовольствия)

switch (0) { // compiler might complain that the 
             // controlling expression is constant
case 0:       
case sizeof(a) == sizeof(b):
    ; // nothing to do
}

Вы поняли идею.Просто поиграйте с этим, пока компилятор не будет доволен на 100%.

2 голосов
/ 05 октября 2011

Первый случай явно запрещен согласно #if документации:

В выражении нельзя использовать sizeof или оператор приведения типа.

Что касается предупреждения, вы можете либо проигнорировать его (потому что вы знаете, что ваш код в порядке), либо отключить его с помощью #pragma, либо просто взять условие из if:

bool sizeMatch = (sizeof(a) == sizeof(b));
if (!sizeMatch){
    printf("sizes don't match\n");
    return -1;
}

Редактировать: так как отключение ошибки, похоже, привлекло некоторое внимание, вот несколько способов добиться этого с помощью #pragma warning:

#pragma warning (push) 
#pragma warning (disable: 4127)
    if(sizeof(a) != sizeof(b)){
#pragma warning (pop) 
          // ...

Очевидно, что всплывающее окно можно сделать дальше по коду. Другой вариант может быть:

#pragma warning (disable: 4127)
    if(sizeof(a) != sizeof(b)){
#pragma warning (default: 4127) 

Что снова включит предупреждение, не нажимая и не щелкая.

В любом случае, этот код выглядит ужасно. IMO, просто использование bool для получения результата сравнения sizeof (как показывает мой первый фрагмент) будет самым чистым решением.

0 голосов
/ 05 октября 2011

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

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

http://msdn.microsoft.com/en-us/library/2c8f766e(v=vs.80).aspx

0 голосов
/ 05 октября 2011
#include <stdio.h>

struct tag {
int a;
};
main() {
    struct tag a,b;
        if(sizeof(a) != sizeof(b))
        printf("not");
    else
        printf("same");

}

эта программа работает без предупреждения ... !!!

...