Арифметика указателя для пустого указателя в C

Когда указатель на определенный тип (скажем, int , char , float , ..) увеличивается, его значение увеличивается на размер этого типа данных. Если указатель void , который указывает на данные размером x , увеличивается, как он добирается до точки x байтов вперед? Как компилятор узнает, как добавить x к значению указателя?

162
задан PJTraill 5 May 2015 в 22:08
поделиться

5 ответов

Окончательный вывод: арифметика на void * является незаконной как в C, так и в C ++.

GCC разрешает это как расширение, см. Арифметика на void - и указатели на функции (обратите внимание, что этот раздел является частью главы «Расширения C» в руководстве). Clang и ICC, вероятно, допускают арифметику void * в целях совместимости с GCC.Другие компиляторы (например, MSVC) запрещают арифметические операции с void * , а GCC запрещает их, если указан флаг -pedantic-errors или если -Werror-pointer- Указан флаг arith (этот флаг полезен, если ваша кодовая база также должна компилироваться с MSVC).

Говорит стандарт C

Цитаты взяты из черновика n1256.

Стандартное описание операции сложения гласит:

6.5.6-2: Для сложения либо оба операнды должны иметь арифметический тип, или один операнд должен быть указателем на тип объекта, а другой должен имеют целочисленный тип.

Итак, вопрос здесь в том, является ли void * указателем на «тип объекта» или, что эквивалентно, является ли void «типом объекта». Определение «типа объекта»:

6.2.5.1: Типы подразделяются на типы объектов (типы, которые полностью описывают объекты), типы функций (типы, описывающие функции) и неполные типы (типы, которые описывают объекты, но не имеют информации, необходимой для определения их размеров).

Стандарт определяет void как:

6.2.5-19: Тип void включает пустой набор значений; это неполный тип, который не может будет завершена.

Поскольку void является неполным типом, это не тип объекта. Следовательно, это недопустимый операнд для операции сложения.

Следовательно, вы не можете выполнять арифметические действия с указателем на указатель void .

Примечания

Первоначально считалось, что арифметика void * была разрешена из-за этих разделов стандарта C:

6.2.5-27: Указатель на void должен иметь то же представление и выравнивание требования как указатель на тип персонажа.

Однако

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

Это означает, что printf ("% s", x) имеет то же значение, имеет ли x тип char * или void * , но это не означает, что вы можете выполнять арифметические операции с void * .

Примечание редактора: Этот ответ был отредактирован, чтобы отразить окончательный вывод.

267
ответ дан 23 November 2019 в 21:21
поделиться

Вы не можете выполнять арифметику указателей на типы void *, именно по этой причине!

14
ответ дан 23 November 2019 в 21:21
поделиться

преобразовать его в указатель char и увеличить указатель вперед на x байтов.

16
ответ дан 23 November 2019 в 21:21
поделиться

Вы должны привести его к другому типу указателя, прежде чем выполнять арифметические действия с указателем.

8
ответ дан 23 November 2019 в 21:21
поделиться

Арифметика указателей не разрешена для указателей void * .

57
ответ дан 23 November 2019 в 21:21
поделиться
Другие вопросы по тегам:

Похожие вопросы: