Разъяснение того, почему этот код C работает - PullRequest
7 голосов
/ 04 июля 2011

Я изучаю C сегодня. Я уже давно пишу на управляемых языках (Java, C #, Python и т. Д.). Я думал, что понимаю детали указателей, но затем я написал следующий код, который работал как ожидалось, но сгенерировал предупреждение «несовместимый тип указателя».

void setText(char* output) {
    //code to set output to whatever, no problems here.
}

int main(int argc, const char* argv[]) {
    char output[10];

    setText(&output);

    //[EDITED] ...other test code which printf's and further manipulates output.

    return 0;
}

Так что я погуглил и закончил тем, что изменил строку

setText(&output);

до

setText(output);

, который избавился от предупреждения. Но теперь я не знаю, почему первый работал вообще. Насколько я могу судить, я отправлял адрес адреса (потому что char * x; по сути то же самое, что char x [];). Что я неправильно понимаю, и почему оба они работают?

1 Ответ

17 голосов
/ 04 июля 2011

Тип из output равен char [10], который уменьшается до char * в контексте вызова функции (именно поэтому работает второй вариант).

Тип &output равен char (*)[10], то есть указатель на массив.Это не одно и то же, отсюда и предупреждение компилятора.Однако значение из &output (адрес) эквивалентно значению output (после того, как оно уменьшилось до char *), поэтому конечный результат будет «как и ожидалось».

Это может звучать как педантизм, но есть довольно важное различие.Попробуйте следующее:

void foo(const char *p)
{
    printf("%s\n", p);
}

int main(void)
{
    char output[][6] = { "Hello", "world" };

    foo(output[0] + 1);
    foo(&output[0] + 1);
}

Рекомендуется прочитать Часто задаваемые вопросы по C для массивов и указателей , в частности вопросы 6.3 и 6.12.

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