Подтвердить что ты не робот

Указатель на массив со спецификатором const в C & С++

Рассмотрим следующую программу:

int main()
{
    int array[9];
    const int (*p2)[9] = &array;
}

Он компилируется в С++ (см. live demo здесь), но не удается выполнить компиляцию в C. По умолчанию GCC дает следующие предупреждения. (См. Живое демо здесь).

prog.c: In function 'main':
prog.c:4:26: warning: initialization from incompatible pointer type [enabled by default]
     const int (*p2)[9] = &array;

Но если я использую опцию -pedantic-errors:

gcc -Os -s -Wall -std=c11 -pedantic-errors -o constptr constptr.c

он дает мне следующую ошибку компилятора

constptr.c:4:26: error: pointers to arrays with different qualifiers are incompatible in ISO C [-Wpedantic]

Почему это не удается в компиляции в C, но не в С++? Что говорит об этом в стандарте C и С++?

Если я использую const квалификатор в заявлении объявления массива, он также компилируется в C. Итак, что здесь происходит в вышеуказанной программе?

4b9b3361

Ответ 1

GCC-gnu

В GNU C указатели на массивы с квалификаторами работают аналогично указателям на другие квалифицированные типы. Например, значение типа int (*)[5] может использоваться для инициализации переменной типа const int (*)[5]. Эти типы несовместимы в ISO C, потому что квалификатор const формально привязан к типу элемента массива, а не самому массиву.

Стандарт C говорит, что (раздел: §6.7.3/9):

Если спецификация типа массива включает в себя квалификаторы любого типа, тип элемента имеет соответствующую квалификацию, не тип массива. [...]

Теперь посмотрим на стандарт С++ (раздел § 3.9.3/5):

[...] Cv-квалификаторы, применяемые к типу массива, присоединяются к типу базового элемента, поэтому обозначение "cv T", где T является типом массива, относится к массиву, элементы которого являются так называемыми " квалифицированный. Тип массива, чьи элементы имеют квалификацию cv, также считается имеющим те же CV-квалификацию, что и его элементы. [Пример:

 typedef char CA[5];
 typedef const char CC;
 CC arr1[5] = { 0 };
 const CA arr2 = { 0 };

Тип arr1 и arr2 - это "массив из 5 const char", а тип массива считается const-qual. -endexample]

Следовательно, инициализация

const int (*p2)[9] = &array;  

является присвоением указателю типа массиву [9] of int указателю на массив [9] для const int. Это не похоже на назначение int * a const int *, где const применяется непосредственно к типу объекта , указатель указывает на. Это не относится к const int(*)[9], где в C, const применяется к элементам объекта массива вместо объекта, на который указывает указатель. Это делает вышеуказанную инициализацию несовместимой.

Это правило изменяется на С++. Поскольку const применяется к самому объекту массива, назначение находится между теми же типами указателя на const array [9] of int вместо указателя типа на массив [9] of int и указателя на массив [9] of const int.