Указатель на const в вызове функции - PullRequest
0 голосов
/ 22 февраля 2019

У меня есть целочисленный массив int foo[3], и я хочу передать его другой функции.Я хотел бы выполнить две вещи:

  • Передать его по ссылке
  • Установить его как постоянное, так как его не следует изменять.

Функция Iопределено:

void print_foo(const int(*const foo)[3]) {

    // Print the second integer
    printf("%d\n", (*foo)[1]);
}

И я называю это:

int foo[3] = {1, 2, 3};

print_foo(&foo);

Когда я компилирую его с помощью gcc MinGW, я получаю предупреждение:

warning: passing arg 1 of `print_foo` from incompatible pointer type

Я хотел бы понять, что я делаю неправильно.

Примечание: Я могу скрыть предупреждение, объявляющее функцию без первого const как:

void print_foo(int(*const foo)[3])

Но это похоже на обходной путь, так как я хочу, чтобы не только адрес указателя был постоянным, но и содержимое памяти (вот причина двух const).

Ответы [ 2 ]

0 голосов
/ 22 февраля 2019

Интересно, что я мог бы скомпилировать следующий код с версиями CLang 3.4.1 и 6.0.0 без предупреждений:

#include <stdio.h>

void print_foo(const int (* const foo)[3]) {
    printf("%d - size: %lu\n", (*foo)[1], sizeof(*foo));
}
int main() {
    int foo[3] = {1,2,3};
    print_foo(&foo);
    return 0;
}

В моей 32-битной системе вывод 2 - 12, что доказывает, что sizeof(*foo) имеет ожидаемое значение.

Но я бы сказал, что gcc здесь верный, и что Clang допускает его как расширение.

Стандарт (черновик n1570 для C11) гласит 6.2.7 Совместимый тип и составной тип §1:

Два типа имеют совместимый тип, если их типы совпадают.Дополнительные правила определения совместимости двух типов описаны в 6.7.2 для спецификаторов типов, в 6.7.3 для классификаторов типов и в 6.7.6 для деклараторов и в 6.7.3 классификаторах типов § 10

Длядва квалифицированных типа должны быть совместимы, оба должны иметь идентично квалифицированную версию совместимого типа

Таким образом, типы должны иметь одинаковую константность для совместимости.

Но передача параметров ввызов функции имеет ту же семантику, что и присваивание, и 6.5.16.1 простое присваивание говорит в своих ограничениях:

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

Итак, разрешено присваивать int (*)[3] int (const *)[3], даже если они несовместимы.

Ноint [3] и const int[3] - это разные типы, поэтому вы не можете присвоить int (*)[3] для const int (*)[3] или const int (const *)[3].

То, что вы хотите, имеет смысл, но я не могу представить себе подходящий способобъявить это.

0 голосов
/ 22 февраля 2019

просто сделайте это:

#include <stdio.h>

// note can also use "const int foo[3]" but in that
// case 3 is nothing more than a comment for a reader
void print_foo(const int foo[])
{
  // Print the second integer
  printf("%d\n", foo[1]);
}

int main()
{
  int foo[3] = {1, 2, 3};

  print_foo(foo);
}

массив уже указан по адресу

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