Указатель в C++ используется как массив без инициализации или выделения. Тем не менее, это работает и считается действенC++

Программы на C++. Форум разработчиков
Anonymous
 Указатель в C++ используется как массив без инициализации или выделения. Тем не менее, это работает и считается действен

Сообщение Anonymous »

Сегодня я наткнулся на этот код:

Код: Выделить всё

ushort *LibRaw::ljpeg_row(int jrow, struct jhead *jh)
{
ushort mark = 0, *row[3];
// Irrelevant code here...
FORC3 row[c] = jh->row + jh->wide * jh->clrs * ((jrow + c) & 1);
// Irrelevant code here...
return row[2];
}

void LibRaw::canon_sraw_load_raw()
{
short *rp = 0, (*ip)[4];
// Irrelevant code here...
rp = (short *)ljpeg_row(jrow++, &jh);
// Few lines of code with no assignment to any variable...
FORC(jh.clrs - 2)
{
ip[col + (c >> 1) * width + (c & 1)][0] = rp[jcol + c];
ip[col + (c >> 1) * width + (c & 1)][1] =
ip[col + (c >> 1) * width + (c & 1)][2] = 8192;
}
// Irrelevant code here...
}
Давайте обратимся к функции ljpeg_row как к вызывающей стороне и к canon_sraw_load_raw как к вызывающей стороне. Насколько я понимаю, переменная row представляет собой массив указателей ushort длиной 3. Это правильно используется внутри вызываемого объекта. Но после того, как один элемент массива возвращается по значению, вызывающая сторона выполняет итерацию по этому указателю (), так как это массив! ФОРК/

Код: Выделить всё

FORC3Макросы 
расширяются до цикла for, увеличивая c. В моем примере FORC(jh.clrs - 2) c увеличивается как минимум один раз.
Теперь мои вопросы:
  • Разве это не должно быть выделено с помощью alloc/malloc внутри вызываемого объекта или объявлено/инициализировано как массив в вызывающей функции, чтобы это не вызывало ошибок сегментации? Нет никакой гарантии (кроме того, что между этими строками нет другого присваивания), что в rp[jcol + c] не будет мусора.
  • Насколько я понимаю у программиста буквально нет возможности контролировать, где расположен массив строк, не только для того, чтобы попытаться прикоснуться к нему, но и для того, чтобы попытаться прочитать оттуда полезные данные?! Итак,
  • Как это правильный стиль программирования? Это какой-то быстрый хак, который просто работает?
Это известная библиотека с открытым исходным кодом, в которой много участников, поэтому я сомневаюсь, что она будет ошибка (и, следовательно, открыть новую проблему на GitHub и спросить). Кроме того, это компилируется и работает нормально, без ошибок сегментации. Более того, я проверил репозиторий git и обнаружил, что приведенный выше код присутствует с самого первого коммита, сделанного 6 лет назад. И все же мы здесь. Чего мне здесь не хватает?
Я скомпилировал и запустил код. Работает без проблем.
Я выполнил отладку с помощью резиновой утки, но ничего не могу понять!
Я искал похожие вопросы, например:
https:// stackoverflow.com/questions/12416459/can-i-use-a-void-pointer-in-c-as-an-array
https://stackoverflow.com/questions/ 59184633/c-declaring-a-pointer-and-then-use-it-as-an-array-memory-allocation
https://stackoverflow.com/questions/43724654/ как-эта-переменная-используется-как-целое-и-как-массив-в-cpp
только для дальнейшего подтверждения моих вопросов.
Это ссылка на исходный файл (если вы хотите проверить код, который я удалил):
https://github.com/LibRaw/LibRaw/blob/m ... /decoders/ decoders_dcraw.cpp

Подробнее здесь: https://stackoverflow.com/questions/790 ... ion-yet-it

Вернуться в «C++»