dimka76 62 15 октября, 2023 Опубликовано 15 октября, 2023 · Жалоба On 10/15/2023 at 5:56 PM, jcxz said: Вроде как там всего одна строка. Так как символ '\' - указывает, что это единая строка. После макроподстановки получится одна строка кода. Понятно. Спасибо ! Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Arlleex 180 15 октября, 2023 Опубликовано 15 октября, 2023 · Жалоба 2 часа назад, repstosw сказал: Мне кажется, мой вариант с объявлениями переменных в начале тела функции - требует меньше всего телодвижений со стороны портирующего чужой код. Это да... Но я имел в виду вот так func() { c->luma_buffer = ve_malloc(c->input_buffer_size); if(c->luma_buffer == NULL) goto nomem; else { c->bytestream_buffer_size = 3 /*1*/ * 1024 * 1024; c->bytestream_buffer = ve_malloc(c->bytestream_buffer_size); if(c->bytestream_buffer == NULL) goto nomem; else { unsigned int luma_size = ALIGN(c->mb_width * 16, 32) * ALIGN(c->mb_height * 16, 32); unsigned int chroma_size = ALIGN(c->mb_width * 16, 32) * ALIGN(c->mb_height * 8, 32); //... } } nomem: printf("no mem. bye-bye...\n"); return; } 1 час назад, dimka76 сказал: Чего нет? Того и нет, что макрос __LINE__ развернется на этапе подстановки в строке вызова, по правилам разворачивания макросов. Вы предполагаете, что TTT() сначала развернется в то, что написано в TTT, а __LINE__ заполнится "по мере парсинга", но это не так. Препроцессор Си таким образом защищается от рекурсивных вызовов внутри макроса того же макроса (если не понятно, пишите). 45 минут назад, jcxz сказал: Вроде как там всего одна строка. Так как символ '\' - указывает, что это единая строка. После макроподстановки получится одна строка кода. Ды не, это тут даже не важно. На момент разворачивания TTT() __LINE__ не используется в макрос-операции # или ##, поэтому __LINE__ развернется ровно 1 раз. 1 час назад, jcxz сказал: Почему? Вроде всё ок. Разве что __packed должен быть перед struct (хотя не уверен что это важно). В структуре все элементы u32 имеют естественное выравнивание в 4 байта, поэтому дописывать упаковку нет смысла, да и весьма чревато: помимо потенциально "опасных" невыровненных (а потому - неатомарных) чтений volatile, в структуре могли оказаться, например, 8 или 16-битные регистры, выровненные по границе 4 байт. И с __packed получилась бы неправильная каша: // должно было быть: // 0x0 - 8-разрядный регистр a // 0x4 - 16-разрядный регистр b // 0x8 - 32-разрядный регистр c // с __packed будет так __packed struct NoValidMMIO { __IO u8 a; // реальное смещение 0x0 __IO u16 b; // реальное смещение 0x1 <<-- ERROR __IO u32 c; // реальное смещение 0x3 <<-- ERROR }; // без __packed будет правильно struct ValidMMIO { __IO u8 a; // реальное смещение 0x0 __IO u16 b; // реальное смещение 0x4 <<-- OK __IO u32 c; // реальное смещение 0x8 <<-- OK }; Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 236 15 октября, 2023 Опубликовано 15 октября, 2023 · Жалоба 39 минут назад, Arlleex сказал: Ды не, это тут даже не важно. На момент разворачивания TTT() __LINE__ не используется в макрос-операции # или ##, поэтому __LINE__ развернется ровно 1 раз. Почему думаете что "не используется"? Логично предположить, что внутри concat2() как раз есть склейка ##. 39 минут назад, Arlleex сказал: В структуре все элементы u32 имеют естественное выравнивание в 4 байта, поэтому дописывать упаковку нет смысла Почему Вы всё время упираете на "упаковку"? Причём тут какая-то "упаковка" если в той структуре нет никаких padding? Упаковка там вовсе не причём, а __packed - совсем для иного: Для того, чтобы указать компилятору, что структура может лежать по невыровненному адресу (по адресу, не выровненному на величину выравнивания структуры). Я уже выше писал, что __packed используется не только для упаковки структур. Вы видимо не обратили внимание: 4 часа назад, jcxz сказал: __packed uint x1; __packed struct T1 { char y1; uint y2; char y3; }; Здесь представлены 2 предназначения __packed. И __packed здесь запрещает на Cortex-M для доступа к x1 использовать инструкции CPU, не поддерживающие невыровненный доступ. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Arlleex 180 15 октября, 2023 Опубликовано 15 октября, 2023 · Жалоба 57 минут назад, jcxz сказал: Почему думаете что "не используется"? Логично предположить, что внутри concat2() как раз есть склейка ##. Макрос раскрывается сразу, если он не участвует напрямую в операциях # или ##. В concat2() не напрямую склеиваются токены, а вызывается _concat2(a, b), который уже и разворачивается в a##b. Это - не одно и то же: Цитата 6.10.3.1 Argument substitution After the arguments for the invocation of a function-like macro have been identified, argument substitution takes place. A parameter in the replacement list, unless preceded by a # or ## preprocessing token or followed by a ## preprocessing token (see below), is replaced by the corresponding argument after all macros contained therein have been expanded. Before being substituted, each argument’s preprocessing tokens are completely macro replaced as if they formed the rest of the preprocessing file; no other preprocessing tokens are available. Единственное, не совсем понятно, касается ли это не function-like макросов. Цитата Для того, чтобы указать компилятору, что структура может лежать по невыровненному адресу (по адресу, не выровненному на величину выравнивания структуры). Крайне необычно и противоестественно видеть структуру MMIO-регистров периферии невыровненной. Цитата Почему Вы всё время упираете на "упаковку"? Причём тут какая-то "упаковка" если в той структуре нет никаких padding? Потому что "упаковка" намекает как раз на то, что данные внутри структуры могут не иметь естественных выравниваний. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Edit2007 3 16 октября, 2023 Опубликовано 16 октября, 2023 · Жалоба 19 часов назад, repstosw сказал: Не нравится объявление переменных после условия. Пока сделал объявление переменных в начале. Объявлять переменные в начале функции(блока) - это требование классического С. Только плюсы позволяют объявлять переменные где вздумается по мере необходимости. А то, что GCC проглатывает - так это, наверняка, от ключей зависит. Указать строгую проверку на соответствие С-98, и получите тот же набор предупреждений. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 136 16 октября, 2023 Опубликовано 16 октября, 2023 · Жалоба 1 час назад, Edit2007 сказал: Объявлять переменные в начале функции(блока) - это требование классического С. Только плюсы позволяют объявлять переменные где вздумается по мере необходимости. В стандарте языка C от 89 года нету требования объявлять переменные в начале блока. Такое требование было в K&R C, еще до введения стандарта. Так что не только лишь плюсы... 1 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Arlleex 180 16 октября, 2023 Опубликовано 16 октября, 2023 · Жалоба 1 час назад, Edit2007 сказал: Объявлять переменные в начале функции(блока) - это требование классического С. Не было такого требования. А зачастую когда в длинной функции все переменные свалены наверху - получается малопонятная каша. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Xenia 44 16 октября, 2023 Опубликовано 16 октября, 2023 · Жалоба 5 часов назад, Сергей Борщ сказал: В стандарте языка C от 89 года нету требования объявлять переменные в начале блока. Такое требование было в K&R C, еще до введения стандарта. Так что не только лишь плюсы... В классическом C все переменные объявляли в начале блока для того, чтобы внутри блока goto пользоваться :). Потому что как только goto перескочит через объявление переменной - быть ошибке. Но если посмотреть на ассемблерный листинг компилятора, то там всё равно место для всех локальных переменных выделятся на стеке в начале блока. А если что и хорошо, то это декларация переменной цикла внутри оператора for. Сильно это мне нравится, особенно когда в качестве такой переменной компилятор использует регистр. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Arlleex 180 16 октября, 2023 Опубликовано 16 октября, 2023 · Жалоба 1 час назад, Xenia сказал: Потому что как только goto перескочит через объявление переменной - быть ошибке. Объявление тут как раз не шибко важно - важно определение с инициализацией. Вот если проскочит инициализацию - тогда будет ошибка/предупреждение. Вроде, так🙂 Цитата Но если посмотреть на ассемблерный листинг компилятора, то там всё равно место для всех локальных переменных выделятся на стеке в начале блока. А Вы чей листинг смотрели? Какого CPU? Потому как именно выделение места на стеке (команды изменения SP) - зачастую в начале функции, не важно, сколько в ней будет блоков (составных операторов) со своими локальными переменными... Однако все это весьма сильно зависит от принятого соглашения по ABI. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться