#c
#c
Вопрос:
На C (НЕ C ) я пытаюсь создать две таблицы строк, которые содержат одинаковые значения, но имеют значения, отсортированные двумя разными способами. И я не хочу, чтобы строки дублировались в памяти.
В принципе, я хочу сделать следующее. За исключением того, что согласно gcc, происходит сбой, потому что «элемент инициализатора не является постоянным» при второй инициализации массива. Есть ли какой-то способ обойти эту проблему? Желательно без слов «о, ну, компилятор должен оптимизировать его, чтобы делать то, что вы хотите»?
static const char * monthNames[] = {
"Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
};
/********
* Month table sorted for O(log N) string lookup
*/
static const char * monthSortedKeys[]= {
monthNames[3], /* Apr */
monthNames[7], /* Aug */
monthNames[11], /* Dec */
monthNames[1], /* Feb */
monthNames[0], /* Jan */
monthNames[6], /* Jul */
monthNames[5], /* Jun */
monthNames[2], /* Mar */
monthNames[4], /* May */
monthNames[10], /* Nov */
monthNames[9], /* Oct */
monthNames[8] /* Sep */
};
Разъяснение:Я знаю, как это сделать с помощью цикла. Я пытаюсь выяснить, как это сделать во время компиляции.
Еще одно обновление: я только что скомпилировал это как C (g ), и это работает. Но опять же, я ищу ответ на C.
Комментарии:
1. О, ну, компилятор должен оптимизировать его, чтобы делать то, что вы хотите
2. @K-ballo 1 за юмор. И я только что проверил эту теорию, и она работает. И я думал, что так и будет. Но я надеялся найти способ сделать это явно. В системе с объемом ПЗУ всего 256 КБ (и меньшим объемом оперативной памяти) приятно сразу понять, что ваш код не тратит впустую ПЗУ.
Ответ №1:
Пример фрагмента кода:
static const char
JAN[] = "Jan",
FEB[] = "Feb",
// ...
DEC[] = "Dec";
static const char *const monthNames[] = {
JAN, FEB, /* ... */ DEC
};
static const char *const monthSortedKeys[]= {
/* APR, ... */ DEC, /* ... */ FEB, JAN /* ... SEP */
};
Комментарии:
1. Мне нужно что-то подобное, но я передаю массив строк как
argv
вmain
(раньше былmain
, теперь переименован) функцию.const
Определитель предотвратит совпадение в прототипе функции.
Ответ №2:
Кажется, это работает для меня:
static const char monthNames[][4] = ...
Я бы подумал, что объявление указателей как констант помогло бы, но, как указывали другие, это не так.
Комментарии:
1. хороший вариант — об этом не подумал; хотя мое решение все еще может быть более читабельным…
2. Закрыть…. за исключением того, что она ломается
sizeof()
. Это одно тонкое различие междуstatic const char * array[]
иstatic const char array[][]
. Первая приведет к тому, что sizeof() вернет количество указателей в массиве. Вторая приведет к тому, что sizeof() вернет размер 2D-массива.3. что касается того, почему это работает, а не исходный код: в коде Брайана
monthNames[3]
необходимо фактически вычислять*(monthNames 3)
, т. Е. считывать значение из памяти, тогда как в вашем коде это эквивалентно(char *)(monthNames 3)
— доступ к памяти не требуется, просто некоторая арифметика указателя4. @Brian: на самом деле это не должно иметь значения — следующее все равно будет выполнено:
sizeof monthNames / sizeof *monthNames == sizeof monthSortedKeys / sizeof *monthSortedKeys
5. @Christoph Я полагаю, что это хороший момент, поскольку я использую
sizeof()
для получения количества строк в таблице. Однако я думаю, что ваш ответ, вероятно, в целом предпочтительнее, поскольку он может быть расширен для работы с различными длинами строк. Единственным недостатком является то, что это немного более подробно, чем должно быть.