AndreyS 0 27 сентября, 2010 Опубликовано 27 сентября, 2010 (изменено) · Жалоба Добрый день. Дано: 8 битный микроконтроллер Keil Си Структура для хранения переменных во внешней I2C EPROM Размер EPROM константа 256 байт Структура постепенно растет и изменяется Хотел включить макрос проверки размера структура за предел размер памяти EPROM на стадии компиляции и в случае превышеняи размера выводить ошибку. Что-то типа того: typdef struct { ... }структура; #define размер EPROM 256 #if (sizeof(структура)>размер EPROM) #error "ОШИБКА" #endif Но sizeof в данном случае использовать нельзя. Подскажите пожалуйста, как мне решить мою задачу? (считать вручную уже надоело) Изменено 27 сентября, 2010 пользователем AndreyS Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
neiver 0 27 сентября, 2010 Опубликовано 27 сентября, 2010 · Жалоба Можно вот такой хак применить, воспользовавшись, тем фактом, что массив не может иметь отрицательный размер: 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 в частности. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
sergeeff 1 27 сентября, 2010 Опубликовано 27 сентября, 2010 · Жалоба Макросы обрабатываются препроцессором, то есть до компиляции. sizeof определяется на этапе компиляции. Посему ответ: в лоб на С - никак. http://msdn.microsoft.com/en-us/library/ew...28VS.80%29.aspx Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
vmp 0 27 сентября, 2010 Опубликовано 27 сентября, 2010 · Жалоба sizeof в препроцессоре понимали какие-то ранние версии компиляторов IAR. А для проверки можно тупо написать if в теле программы. Все равно компилятор при оптимизации его выкинет, если условие не выполняется. Можно даже вызывать какую-нибуь левую подпрограииу, чтобы обругался линкер: void linker_error(void); void main(void) { if (sizeof(структура)>размер EPROM) { linker_error(); for (;;); } } В этом случае сначала компилятор даст warning на недостижимый код из-за for (;;);, а потом линкер не найдет подпрограмму linker_error. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
neiver 0 27 сентября, 2010 Опубликовано 27 сентября, 2010 · Жалоба Можно довольно много языковых конструкций использовать для этих целей. Особенно тех, правильность которых зависит от значений целочисленных выражений. switch, например, можно использовать с дублирующимися метками. Да много чего ещё. А вот в С++ есть такая штука как STATIC_ASSERT, реализацию которого можно найти, например, в boost (А как утвердят новый стандарт -это будет часть языка). И можно писать в любом месте программы так: BOOST_STATIC_ASSERT(sizeof(A) < 256) Если условие итненно - всё нормально, ложно - ошибка компиляции. Я лично именно BOOST_STATIC_ASSERT использую в таких случаях (и пишу на С++ соответственно). Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
sergeeff 1 27 сентября, 2010 Опубликовано 27 сентября, 2010 · Жалоба Я лично именно BOOST_STATIC_ASSERT использую в таких случаях (и пишу на С++ соответственно). STATIC_ASSERT уже является частью Visual Studio 2010 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
neiver 0 27 сентября, 2010 Опубликовано 27 сентября, 2010 · Жалоба STATIC_ASSERT уже является частью Visual Studio 2010 Он является частью нового стандарта С++. И в GCC он уже тоже есть. Но стандарт ещё не принят. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AndreyS 0 30 сентября, 2010 Опубликовано 30 сентября, 2010 · Жалоба Всем большое спасибо. Сделал костыль предложенный neiver (хоть и пришлось пожертвовать одним байтом ОЗУ. 0 длины массив не создал. Вернее не выкинул его, а ругнулся при требуемом типе оптимизации.) Жалко конструкция vmp на Keil не сработала. Он упорно пытался найти все что под if (хотя после компиляции его выкинул) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Diz 0 30 сентября, 2010 Опубликовано 30 сентября, 2010 · Жалоба Если волнует, что компилятор выделит память переменной (при ненулевом уровне оптимизации должен выбросить), можно добавить extern: #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 ] Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
DogPawlowa 0 1 октября, 2010 Опубликовано 1 октября, 2010 · Жалоба Есть такой макрос определения смещения поля в структуре, в ИАРе он встроенный, его использовать. #define OFFSET(type,field) ((uchar *)&(((type *)0)->field) - (uchar *)0) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
_Pasha 0 1 октября, 2010 Опубликовано 1 октября, 2010 · Жалоба #define OFFSET... Вообще-то он должен offsetof называться.... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
DogPawlowa 0 2 октября, 2010 Опубликовано 2 октября, 2010 · Жалоба offsetof Может быть, я то свой определил. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
esaulenka 7 4 октября, 2010 Опубликовано 4 октября, 2010 · Жалоба Есть такой макрос определения смещения поля в структуре, в ИАРе он встроенный, его использовать. #define OFFSET(type,field) ((uchar *)&(((type *)0)->field) - (uchar *)0) Плюс адин к мнению _Pasha, лучше делать #include <stddef.h> и использовать стандартный offsetof(). Вот только топикстартера интересовал другой вопрос :) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться