|
|
  |
Как определить размер структуры в макросе?, в макросе sizeof() не работает |
|
|
|
Sep 27 2010, 13:16
|

Местный
  
Группа: Участник
Сообщений: 235
Регистрация: 28-01-05
Из: Санкт-Петербург
Пользователь №: 2 276

|
Добрый день. Дано: 8 битный микроконтроллер Keil Си Структура для хранения переменных во внешней I2C EPROM Размер EPROM константа 256 байт Структура постепенно растет и изменяется Хотел включить макрос проверки размера структура за предел размер памяти EPROM на стадии компиляции и в случае превышеняи размера выводить ошибку. Что-то типа того: Код typdef struct { ... }структура;
#define размер EPROM 256
#if (sizeof(структура)>размер EPROM) #error "ОШИБКА" #endif Но sizeof в данном случае использовать нельзя. Подскажите пожалуйста, как мне решить мою задачу? (считать вручную уже надоело)
Сообщение отредактировал AndreyS - Sep 27 2010, 13:20
--------------------
Удачи.
|
|
|
|
|
Sep 27 2010, 13:56
|
Местный
  
Группа: Участник
Сообщений: 214
Регистрация: 22-03-10
Из: Саратов
Пользователь №: 56 123

|
Можно вот такой хак применить, воспользовавшись, тем фактом, что массив не может иметь отрицательный размер: Код struct A { int a, b, c, d; char e[300]; };
enum{EPROM_SIZE = 256};
static int error_struct_a_is_too_big[sizeof(A) > EPROM_SIZE ? -1: 0]; Если sizeof(A) будет больше EPROM_SIZE, то будет ошибка. Если нет - массив нулевого размера, который оптимизатор выкинет. Собственно, сообщение нужно закодировать в имени этого массива. Пример сообщения об ошибке, которое выдаёт GCC: ../main.cpp:19: error: size of array 'error_struct_a_is_too_big' is negative А в макросах это никак не сделать, макросы работают на уровне текстовых строк, им побоку любые языковые конструкции и sizeof в частности.
|
|
|
|
|
Sep 27 2010, 14:13
|

Местный
  
Группа: Свой
Сообщений: 426
Регистрация: 20-01-05
Из: Зеленоград
Пользователь №: 2 070

|
sizeof в препроцессоре понимали какие-то ранние версии компиляторов IAR. А для проверки можно тупо написать if в теле программы. Все равно компилятор при оптимизации его выкинет, если условие не выполняется. Можно даже вызывать какую-нибуь левую подпрограииу, чтобы обругался линкер: Код void linker_error(void);
void main(void) { if (sizeof(структура)>размер EPROM) { linker_error(); for (;;); } } В этом случае сначала компилятор даст warning на недостижимый код из-за for (;;);, а потом линкер не найдет подпрограмму linker_error.
|
|
|
|
|
Sep 27 2010, 15:02
|
Местный
  
Группа: Участник
Сообщений: 214
Регистрация: 22-03-10
Из: Саратов
Пользователь №: 56 123

|
Можно довольно много языковых конструкций использовать для этих целей. Особенно тех, правильность которых зависит от значений целочисленных выражений. switch, например, можно использовать с дублирующимися метками. Да много чего ещё. А вот в С++ есть такая штука как STATIC_ASSERT, реализацию которого можно найти, например, в boost (А как утвердят новый стандарт -это будет часть языка). И можно писать в любом месте программы так: Код BOOST_STATIC_ASSERT(sizeof(A) < 256) Если условие итненно - всё нормально, ложно - ошибка компиляции. Я лично именно BOOST_STATIC_ASSERT использую в таких случаях (и пишу на С++ соответственно).
|
|
|
|
|
Sep 27 2010, 17:02
|
Местный
  
Группа: Участник
Сообщений: 214
Регистрация: 22-03-10
Из: Саратов
Пользователь №: 56 123

|
Цитата(sergeeff @ Sep 27 2010, 20:36)  STATIC_ASSERT уже является частью Visual Studio 2010 Он является частью нового стандарта С++. И в GCC он уже тоже есть. Но стандарт ещё не принят.
|
|
|
|
|
Sep 30 2010, 18:42
|
Частый гость
 
Группа: Участник
Сообщений: 84
Регистрация: 1-08-06
Пользователь №: 19 250

|
Если волнует, что компилятор выделит память переменной (при ненулевом уровне оптимизации должен выбросить), можно добавить extern: CODE #define CAT(a, b) a##b #define CAT_WRAP(prefix, line) CAT(prefix, line) #define PANIC_IF(arg) extern char CAT_WRAP(AssertAtLine, __LINE__) [ (arg) ? -1 : 1 ]
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|