dimka76 85 October 15, 2023 Posted October 15, 2023 · Report post On 10/15/2023 at 5:56 PM, jcxz said: Вроде как там всего одна строка. Так как символ '\' - указывает, что это единая строка. После макроподстановки получится одна строка кода. Понятно. Спасибо ! Quote Share this post Link to post Share on other sites More sharing options...
Arlleex 311 October 15, 2023 Posted October 15, 2023 · Report post 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 }; Quote Share this post Link to post Share on other sites More sharing options...
jcxz 342 October 15, 2023 Posted October 15, 2023 · Report post 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, не поддерживающие невыровненный доступ. Quote Share this post Link to post Share on other sites More sharing options...
Arlleex 311 October 15, 2023 Posted October 15, 2023 · Report post 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? Потому что "упаковка" намекает как раз на то, что данные внутри структуры могут не иметь естественных выравниваний. Quote Share this post Link to post Share on other sites More sharing options...
Edit2007 3 October 16, 2023 Posted October 16, 2023 · Report post 19 часов назад, repstosw сказал: Не нравится объявление переменных после условия. Пока сделал объявление переменных в начале. Объявлять переменные в начале функции(блока) - это требование классического С. Только плюсы позволяют объявлять переменные где вздумается по мере необходимости. А то, что GCC проглатывает - так это, наверняка, от ключей зависит. Указать строгую проверку на соответствие С-98, и получите тот же набор предупреждений. Quote Share this post Link to post Share on other sites More sharing options...
Сергей Борщ 177 October 16, 2023 Posted October 16, 2023 · Report post 1 час назад, Edit2007 сказал: Объявлять переменные в начале функции(блока) - это требование классического С. Только плюсы позволяют объявлять переменные где вздумается по мере необходимости. В стандарте языка C от 89 года нету требования объявлять переменные в начале блока. Такое требование было в K&R C, еще до введения стандарта. Так что не только лишь плюсы... 1 Quote Share this post Link to post Share on other sites More sharing options...
Arlleex 311 October 16, 2023 Posted October 16, 2023 · Report post 1 час назад, Edit2007 сказал: Объявлять переменные в начале функции(блока) - это требование классического С. Не было такого требования. А зачастую когда в длинной функции все переменные свалены наверху - получается малопонятная каша. Quote Share this post Link to post Share on other sites More sharing options...
Xenia 48 October 16, 2023 Posted October 16, 2023 · Report post 5 часов назад, Сергей Борщ сказал: В стандарте языка C от 89 года нету требования объявлять переменные в начале блока. Такое требование было в K&R C, еще до введения стандарта. Так что не только лишь плюсы... В классическом C все переменные объявляли в начале блока для того, чтобы внутри блока goto пользоваться :). Потому что как только goto перескочит через объявление переменной - быть ошибке. Но если посмотреть на ассемблерный листинг компилятора, то там всё равно место для всех локальных переменных выделятся на стеке в начале блока. А если что и хорошо, то это декларация переменной цикла внутри оператора for. Сильно это мне нравится, особенно когда в качестве такой переменной компилятор использует регистр. Quote Share this post Link to post Share on other sites More sharing options...
Arlleex 311 October 16, 2023 Posted October 16, 2023 · Report post 1 час назад, Xenia сказал: Потому что как только goto перескочит через объявление переменной - быть ошибке. Объявление тут как раз не шибко важно - важно определение с инициализацией. Вот если проскочит инициализацию - тогда будет ошибка/предупреждение. Вроде, так🙂 Цитата Но если посмотреть на ассемблерный листинг компилятора, то там всё равно место для всех локальных переменных выделятся на стеке в начале блока. А Вы чей листинг смотрели? Какого CPU? Потому как именно выделение места на стеке (команды изменения SP) - зачастую в начале функции, не важно, сколько в ней будет блоков (составных операторов) со своими локальными переменными... Однако все это весьма сильно зависит от принятого соглашения по ABI. Quote Share this post Link to post Share on other sites More sharing options...