Что происходит с указателями в этом фрагменте? - PullRequest
7 голосов
/ 18 апреля 2010

Мне интересно, почему это ошибка и что означает сообщение об ошибке. Вот некоторый код:

int *x[] = {"foo", "bar", "baz"};
int *y[] = {"foo", "bar", "baz"};

x = y;

Я пытаюсь скомпилировать и получаю это:

error: incompatible types when assigning to type ‘char *[3]’ from type ‘char **’

Вопрос № 1, почему это ошибка? и вопрос №2, почему разные типы?

Ответы [ 5 ]

5 голосов
/ 18 апреля 2010

Как написано, проблем довольно много. Во-первых, литералы массива имеют тип char*[], а x и y имеют тип int*[]. Во-вторых, вы не можете назначать массивы напрямую, так как они фактически являются указателями на константы.

3 голосов
/ 18 апреля 2010

Ошибка несовместимых типов, поскольку вы присваиваете массивы строк (тип char * в C) для массивов указателей на целые (например, int *x[]). Сообщение об ошибке, выдаваемое компилятором, немного сбивает с толку, потому что C много делает за кулисами, пытаясь преобразовать переменные из одного типа в другой.

Поскольку символы представляются внутренне в виде чисел (буквы соответствуют их значениям ASCII), C способен преобразовывать символы в целые, поэтому он пытается обрабатывать переменные x и y как массивы указателей на символы вместо целых, поэтому char *[3]. Он видит {"foo", "bar", "baz"} как тип char **, потому что строки имеют тип char *, а массивы по существу хранятся как указатели в C, поэтому это указатель на char * или char ** .

Хотя это не в полной мере относится к вашему вопросу, мне также интересно, что вы пытаетесь сделать с x = y; Как написано, это заставит x указывать на тот же массив, что и y, оставляя массив с x раньше указывал на недоступное. Чтобы проверить, равны ли две переменные в C, вы должны использовать оператор ==. Тестирование равенства не так просто для массивов или строк, но это полностью выходит за рамки этого вопроса.

2 голосов
/ 18 апреля 2010

Это ошибка, потому что массив является неизменяемым lvalue - то есть вы не можете назначить ему напрямую. Вы можете изменять только элементы массива индивидуально.

Типы разные, потому что, если массив используется в контексте, где lvalue не требуется, он оценивается как указатель на его первый элемент (somearray становится эффективным &somearray[0]).

Поскольку массив y используется в таком контексте, он оценивается как адрес его первого элемента, который имеет тип int **. Поскольку массив x равен в контексте lvalue, он оценивается как массив (int *[3]). (Ваше сообщение об ошибке на самом деле не соответствует вашему коду - я подозреваю, что ваши массивы на самом деле являются массивами char *).

(«lvalue context» означает, в значительной степени, одно из: левая часть оператора присваивания (отсюда и название), субъект оператора sizeof или субъект & оператор).

0 голосов
/ 18 апреля 2010

по какой-то причине я не могу использовать ту же учетную запись, с которой опубликовал вопрос.

"int" - это опечатка с моей стороны, я действительно хотел сказать, что это "char". Извините, за путаницу.

Однако я думаю, что Каф ответил на мой вопрос.

"Это ошибка, потому что массив является неизменяемым lvalue - это означает, что вы не можете назначить ему напрямую. Вы можете изменять только элементы массива индивидуально."

Я просто пытаюсь понять, как работают указатели в c, поэтому я пробую эти случайные вещи, которые вы, вероятно, обычно не делаете. Я подумал, что это может сработать, так как я думал, что массивы = указатели, поэтому я мог просто указать x на y. Наверное, нет?

Спасибо за ваш ответ, ребята.

0 голосов
/ 18 апреля 2010

Я бы порекомендовал начать с хорошего урока по указателям и массивам. Похоже, вы пришли из интерпретируемого языка, такого как JavaScript или PHP. В C все совсем по-другому, и вам нужно разобраться с понятиями стековой памяти, динамической памяти, указателей и т. Д. После того, как вы это сделаете, все будет иметь смысл, и вы полюбите C.

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