Определить массив строк - PullRequest
       3

Определить массив строк

3 голосов
/ 21 февраля 2011

Я хотел бы определить массив строк следующим образом:

#define sup (const char**) ("string1", "string2")

, но он не работает, когда я пытаюсь напечатать первую строку:

printf("The string: %s\n",sup[0]); 

как это сделать вправильный путь?

Ответы [ 3 ]

5 голосов
/ 21 февраля 2011

Я бы не советовал вообще делать это с макросами, но если вы действительно заинтересованы в том, что происходит с кодом, - больше, чем в том, как это следует решать, вот объяснение.

В коде есть простая проблема, и более непонятная.Очень просто, чтобы объявить массив, вы используете не круглые скобки, а фигурные скобки:

#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]

[*] Там есть небольшая ручная работа ... компилятор переводит код, один раз вставленный в месте использования макроса препроцессором, но перевод эквивалентенчто я написал, если бы вы редактировали макрос вручную.

2 голосов
/ 21 февраля 2011

Я думаю, что делать подобные уловки препроцессора, особенно с массивами, не очень хорошая идея. Вместо этого у вас должна быть настоящая глобальная таблица строк, например:

const char const * sup[]={"String 1", "String 2", "String 3"};

в одном из .c файлов и поместите объявление extern в заголовок, который будет включен везде, где необходимы такие строки:

extern const char const * sup[];

(первый const должен избегать модификаций каждого строкового литерала - который является UB), второй, чтобы избежать замены указателей, хранящихся в sup; если вы хотите разрешить это последнее действие, удалите второе const)

Альтернативным подходом было бы определение sup непосредственно в заголовке в качестве глобальной переменной static (т.е. с внутренней связью); Я видел, как это делалось ранее с целочисленными константами, чтобы убедиться, что они немедленно известны компилятору в каждом модуле перевода (чтобы он мог поместить их в качестве непосредственных значений в сгенерированной сборке), но я не думаю, что с помощью строковых указателей это может дать любой значительный прирост производительности.

0 голосов
/ 20 августа 2015

У меня есть заголовок, общий для всех моих проектов.

#define MAX_STUDENTS 3
char STUDENT[] = { "Manny", "Joe", "Jack" };

Код выглядит так:

for( int i=0; i<MAX_STUDENTS; i++ )
{ Do Something with STUDENT[i]; }

Клод

...