Передача массивов символов в функции, которые принимают указатели на символы - PullRequest
0 голосов
/ 27 апреля 2018

Почему в C я могу передавать символьные массивы функциям, которые принимают char * в качестве аргумента, но я не могу передать адрес массива функциям, которые принимают char **?

ОБНОВЛЕНИЕ: Интересно, что изменение типа аргумента на char* qux[12] вообще не меняет предупреждение компилятора

Например:

#include <stdio.h>

void foo(char* qux) { puts(qux); }
void bar(char** qux) { puts(*qux); }
void baz(char* qux[12]) { puts(*qux); }

int main() {
    char str[12] = "Hello there";

    foo(str);
    bar(&str); // Compiler warning
    baz(&str); // Same compiler warning

    return 0;
}

Во втором случае я получаю предупреждение компилятора:

warning: incompatible pointer types passing 'char (*)[12]' to
         parameter of type 'char **' [-Wincompatible-pointer-types]

Что здесь происходит?

Ответы [ 2 ]

0 голосов
/ 27 апреля 2018

В C char * представляет указатель на непрерывную последовательность символов. Непрерывная последовательность символов с нулевым окончанием - это то, что мы называем строкой в ​​C.

char ** является указателем на непрерывную последовательность строк, и, поскольку каждая строка является непрерывной последовательностью символов, оканчивающихся нулевым ('\ 0') символом, char ** представляет непрерывную последовательность для непрерывной последовательности символы, оканчивающиеся нулем.

Ваша декларация:

 char str[12] = "Hello there";

Объявляет str массивом символов длиной 12 и инициализируется 12 символами {'H','e','l','l','o',' ','t','h','e','r','e','\0'}. Это совместимо с параметром в foo (), но не с bar и baz, которые ожидают непрерывную последовательность указателей на строки. Вот почему эти двое выдают вам предупреждение компилятора, потому что параметр несовместим с аргументами, передаваемыми в.

0 голосов
/ 27 апреля 2018

Массивы естественным образом распадаются на указатели на их первый элемент. Так что в вызове foo(str) это действительно то же самое, что и foo(&str[0]). Это типа char *, так что все в порядке.

Теперь второй вызов, bar, - это другое дело. Когда вы используете &str, вы не получаете указатель на первый элемент массива, вы получаете указатель на сам массив . И, как отметил компилятор, это тип char (*)[12], который очень отличается от (и несовместим с) char **.

Наконец, когда вы объявляете baz, вы говорите, что аргумент имеет тип char *[12], то есть у вас есть массив или 12 указателей на символ, а не то, что у вас есть указатель на массив 12 char. Кроме того, из-за спада массива на указатель, char *[12] на самом деле совпадает с с char **.

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