Почему временный аргумент char ** незаконен? - PullRequest
0 голосов
/ 31 октября 2018

У меня есть функция, f(char **p), и я хотел вызвать ее как можно проще.

Я пытался

char ** p = {"a", "b"};
f(p);

и получил:

скалярному объекту требуется один элемент в инициализаторе

поэтому я изменил его на

char * p[2] = {"a", "b"};
f(p);

и все прошло хорошо [ было бы также хорошо, если бы просто char * p[]].

Почему я не могу создать массив указателей на лету, как показано ниже?

f({"a", "b"});

Ответы [ 3 ]

0 голосов
/ 31 октября 2018

Это объявление char ** p = {"a", "b"}; вызывает предупреждение, потому что C не знает, как интерпретировать содержимое { } фигурных скобок:

  • Тип объявления char** предполагает, что это один указатель на указатель на символ
  • Содержимое { } определяет два элемента.

Вы должны указать C, что вы инициализируете указатель на указатель указателем на начальный элемент анонимного массива, указывая тип перед фигурными скобками:

char ** p = (char*[]){"a", "b"}

Эта конструкция называется «составной литерал». Он может использоваться в объявлении, но также работает как выражение.

Примечание: если вы планируете передать подобный массив функции, вам необходимо указать способ определения размера массива. Один из подходов состоит в том, чтобы передать NULL для «завершения» массива, например:

void f(char **p) {
    int i = 0;
    while (*p) {
        printf("%d:%s\n", i++, *p++);
    }
}
int main(void) {
    f((char*[]){"a", "b", NULL});
    return 0;
}

Демо-версия.

0 голосов
/ 31 октября 2018

C99 и позже добавлены составные литералы для точной цели: создание массива и структур на лету
Пример:

struct foo {int a; char b[2];} structure;
structure = ((struct foo) {1, 'a', 0});
int *y = (int []) {1, 2, 3};
int *z = (int []) {1}; 

Помимо стандартного C99 и более поздних, GCC также предоставляет эту функцию в качестве расширения.
В вашем случае это будет работать

f((char *[]){"a","b"});

(char *[]){"a","b"} является составным литералом, который создает массив из 2 указателей на char на лету.

0 голосов
/ 31 октября 2018

Это дает предупреждение:

char ** p = {"a", "b"};

потому что p не является массивом.

Это также не разрешено законом:

f({"a", "b"});

поскольку фигурные скобки сами по себе не допускаются в выражении (но могут использоваться в качестве инициализатора).

Можно создать массив на лету, используя составной литерал :

f((char *[]){"a", "b"});

Вы также можете использовать составной литерал для инициализации временного:

char ** p = (char *[]){"a", "b"};

В отличие от первого оператора, это допустимо, поскольку литерал является массивом типа char *[2] и будет иметь значение char **, которое можно использовать для инициализации переменной этого типа.

См. Раздел 6.5.2.5 C стандарта для получения дополнительной информации о составных литералах.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...