Используемый случай указателя на массив с неопределенными границами в C ++ (не в C)

Рассмотрим следующий код:

int main() {
int (*p)[]; // pointer to array with unspecified bounds

int a[] = {1};
int b[] = {1,2};

p = &a; // works in C but not in C++
p = &b; // works in C but not in C++

return 0;
}

В чистом C вы можете назначить указатель на этот тип адреса массива любого измерения. Но в C ++ вы не можете. Я нашел один случай, когда компилятор позволяет присваивать значение такому указателю:

struct C
{
static int v[];
};

int main()
{
int (*p)[] = &C::v; // works in C++ if 'v' isn't defined (only declared)
return 0;
}

Но не смог найти ни одного полезного случая этого кода.

Может ли кто-нибудь привести полезный пример (в C ++) указателя на массив с неопределенными границами?
Или это только остаток от C?

32

Решение

Такой указатель не может участвовать в арифметике указателей, потенциально полезные вещи, которые еще можно сделать, это получить его тип с decltype или же reinterpret_cast это к другому типу указателя или intptr_t, Это потому, что в разделе 3.9p6 говорится:

Тип класса (например, «class X«) может быть неполным в одном месте в единице перевода и завершаться позже; тип»class X«является одним и тем же типом в обеих точках. Объявленный тип объекта массива может быть массивом неполного типа класса и, следовательно, неполным; если тип класса будет завершен позднее в модуле перевода, тип массива станет полным; тип массива в этих двух точках — один и тот же тип. Объявленный тип объекта массива может быть массивом неизвестного размера и поэтому может быть неполным в одной точке в единице перевода и завершаться позже; типы массива в этих двух точках («массив неизвестная граница T«и» массив N T«) это разные типы. Тип указателя на массив неизвестного размера или тип, определенный объявлением typedef как массив неизвестного размера, не может быть завершен.

5.3.1 говорит:

Примечание: косвенное обращение через указатель на неполный тип (кроме cv void) является действительным. Полученное таким образом l-значение может использоваться ограниченным образом (например, для инициализации ссылки); это значение не должно быть преобразовано в предварительное значение, см. 4.1.

Поскольку затухание массива в указатель может быть выполнено для значений l массива без предварительного преобразования в значение rvalue, код dyp, оставленный в комментарии, является правильным:

(*p)[i]

Соответствующее правило из 4.2:

именующий или значение типа ‘массив N T» или же «массив неизвестных границ T« может быть преобразовано в значение типа «указатель на TMsgstr «Результатом является указатель на первый элемент массива.

12

Другие решения

Я думаю, что компилятор должен принять это (независимо от параметра -O), потому что определение статического может быть предоставлено другим модулем компиляции. (Возможно, это прагматическое отклонение от стандарта — я не эксперт по С ++.) Размещенный фрагмент кода можно скомпилировать, но он неполон и не может быть приведен в исполнение без определения статического члена.

Файл c.h:

struct C {
static int v[];
};

Файл x.cpp

#include "c.h"#include <iostream>
int main(){
int (*p)[] = &C::v; // works in C++ if 'v' isn't defined (only declared)
std::cout << *((int*)p) << std::endl;
return 0;
}

Файл y.cpp

#include "c.h"int C::v[3] = {1,2,3};

Скомпилировано и скомпоновано с использованием (dont-tell-me-it-old) g ++ 4.3.3. Отпечатки 1.

И: да, я знаю, что это актерский состав.

2

По вопросам рекламы [email protected]