Ошибка в инициализаторе массива строк: элемент инициализатора не является константой - PullRequest
0 голосов
/ 10 января 2019

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

//.h file
const char *serviceStateKindNormal = "Normal";
const char *serviceStateKindUnmanned = "Unmanned";
const char *serviceStateKindScheduledMaintenanceDown = "ScheduledMaintenance (down)";
const char *serviceStateKindScheduledMaintenanceAvailable = "ScheduledMaintenance (available)";
const char *serviceStateKindMajorIncidentInProgress = "MajorIncidentInProgress";
const char *serviceStateKindPartialService = "PartialService";
const char *serviceStateKindOverloaded = "Overloaded";
const char *serviceStateKindGoingDown = "GoingDown";
const char *serviceStateKindDown = "Down";

const char *serviceStateKind[9] = {
    serviceStateKindNormal,
    serviceStateKindUnmanned,
    serviceStateKindScheduledMaintenanceDown,
    serviceStateKindScheduledMaintenanceAvailable,
    serviceStateKindMajorIncidentInProgress,
    serviceStateKindPartialService,
    serviceStateKindOverloaded,
    serviceStateKindGoingDown,
    serviceStateKindDown
};

но компилятор показывает

error: initializer element is not constant
     serviceStateKindNormal

в чем именно заключается проблема, и какие у меня есть варианты для определения моих переменных?

Ответы [ 2 ]

0 голосов
/ 10 января 2019

Все, что вы вводите в инициализированную переменную, объявленную в области видимости файла, должно быть константным выражением или строковым литералом , из инициализация . Есть список того, что является константным выражением, и значение переменной среди них отсутствует. Итак:

 // there is an array of char[2]{'a',\0'} somewhere in the memory
 // we store the pointer value to that array inside the variable a
 static const char *a = "a";
 // now we want to statically initialize variable b with the same value
 static const char *b = a;

не будет работать, потому что b инициализируется указателем a value , который не является константным выражением. Вам нужно постоянное выражение при инициализации переменной со статической продолжительностью хранения.

Что вы можете сделать? Следующее:

  1. Хороший способ: почему вы храните указатели на строковые литералы "Normal"? Почему бы не хранить сами данные внутри массива? К счастью, адрес переменной является константным выражением, поэтому мы можем использовать его при инициализации! Обратите внимание, что (почти) все варианты использования и семантика остаются неизменными, за исключением некоторого углового использования, такого как sizeof(serviceStateKindNormal) результаты оператора.

    const char serviceStateKindNormal[] = "Normal";
    const char serviceStateKindUnmanned[] = "Unmanned";
    
    const char *serviceStateKind[] = {
        serviceStateKindNormal,
        serviceStateKindUnmanned,
    };
    
  2. Странный способ: хранить указатели на указатели на строки внутри массива. Поскольку переменные адреса являются константными выражениями, это будет работать. Обратите внимание, что serviceStateKind является трехзвездочной переменной. Вам необходимо дважды разыменовать массив при использовании. serviceStateKind - это массив указателей на строки. Обратите внимание, что использование такого массива очень запутанно, поэтому я предлагаю вам использовать структуру.

    const char *serviceStateKindNormal = "Normal";
    const char *serviceStateKindUnmanned = "Unmanned";
    
    const char **serviceStateKind[] = {
        &serviceStateKindNormal,
        &serviceStateKindUnmanned,
    };
    
    int main() {
        // question which one is correct?
        printf("%s\n", *serviceStateKind[1]);
        printf("%s\n", (*serviceStateKind)[1]);
        printf("%s\n", serviceStateKind[0][1]);
    }
    

но так как я не считаю себя трехзвездным программистом, я бы попытался сделать это как минимум до двух звезд:

    const char *serviceStateKindNormal = "Normal";
    const char *serviceStateKindUnmanned = "Unmanned";

    struct {
        // points to a string
        const char **pnt;
    // an array of pointers to string
    } serviceStateKind[] = {
        &serviceStateKindNormal,
        &serviceStateKindUnmanned,
    };

    int main() {
        // more verbose
        printf("%s\n", *serviceStateKind[0].pnt);
    }
  1. По старинке - макросы. Не делай этого. И что в этом плохого, вы можете использовать препроцессорную конкатенацию строковых литералов, чтобы объединить их вместе.

    #define serviceStateKindNormal  "Normal"
    #define serviceStateKindUnmanned  "Unmanned"
    
    const char *serviceStateKind[] = {
        serviceStateKindNormal,
        serviceStateKindUnmanned,
    };
    
    int main() { 
       # magic
       printf(serviceStateKindNormal " " serviceStateKindUnmanned "\n");
    }
    

Я думал определить их в заголовочном файле следующим образом:

Если вы определяете переменные в заголовочном файле, вы хотите пометить их как static, чтобы вы не получили повторяющихся ошибок символов при связывании с различными .c файлами, которые используют этот .h файл. Также приятно пометить переменную как const как подсказку другим программистам, что они не могут быть изменены.

0 голосов
/ 10 января 2019

В языке C константа относится к буквальным константам, таким как (3.14, 2.718 и т. Д.). Квалифицированные по константам объекты (любого типа) не являются константами в терминологии языка C.

Для создания констант в терминологии языка C используйте директиву #define, например:

#define ServiceStateKindNormal "Normal"

и т.д.

...