Я бы не советовал вообще делать это с макросами, но если вы действительно заинтересованы в том, что происходит с кодом, - больше, чем в том, как это следует решать, вот объяснение.
В коде есть простая проблема, и более непонятная.Очень просто, чтобы объявить массив, вы используете не круглые скобки, а фигурные скобки:
#define sup (const char**){"str1", "str2"} // still wrong!!
Менее простая проблема состоит в том, что массивы не являются указателями .Инициализатор фигурных скобок можно использовать для инициализации массива из двух const char*
, но это не то же самое, что const char**
.Если вы измените код на:
#define sup (const char*[2]){"str1", "str2" }
Он должен работать.
Что происходит под капотом с предыдущей версией?Что ж, компилятор видит объявление указателя (ну, приведение к указателю) и инициализатор.Предполагается, что вы хотите инициализировать указатель с первым элементом (несовместимый указатель, но приведение является явным ... вы должны знать, чего хотите, если вы принудительно произвели приведение ), а затем проигнорировать остаток,По сути, компилятор переводит ваш код в [*]:
#define sup (const char**)"str1"
И это вызовет хаос во время выполнения.Интересно отметить, что если бы вы использовали правильную переменную, а затем инициализировали указатель с ней, это сработало бы, потому что, хотя массивы не являются указателями (я настаиваю, имейте это в виду), массивы разрушаютсяв указатели:
const char* tmp[] = { "hi", "there" };
const char** sup = tmp; // fine, tmp decays into &tmp[0]
[*] Там есть небольшая ручная работа ... компилятор переводит код, один раз вставленный в месте использования макроса препроцессором, но перевод эквивалентенчто я написал, если бы вы редактировали макрос вручную.