Могу ли я сделать арифметику на указатели void * в C? - PullRequest
13 голосов
/ 26 октября 2010

это действительно

void *p = &X; /* some thing */
p += 12;

и если да, то на что сейчас указывает p? У меня есть (сторонний) код, который делает это (и компилируется чисто), и я предполагаю, что void * был обработан как char *. Мой верный K & R молчит (ish) на тему

РЕДАКТИРОВАТЬ: мое маленькое тестовое приложение работает нормально на gcc 4.1.1 и обрабатывает void * как char *. Но g ++ barfs

Я знаю, как это сделать правильно. Мне нужно знать, нужно ли мне чистить эту базу кода, чтобы найти все места, где это сделано.

Кстати, gcc -pedantic выдает предупреждение

Резюме:

Спецификация C неоднозначна. Это говорит о том, что с точки зрения представления и использования в качестве параметров функции void * = char *. Но он ничего не говорит об арифметике указателей.

  • gcc (4) разрешает это и рассматривает это как символ *
  • g ++ отказывается
  • gcc -pedantic предупреждает об этом
  • vs2010 как c, так и c ++ отказывается

Ответы [ 6 ]

15 голосов
/ 26 октября 2010

Нет, это не законно.void* не может быть произвольно увеличено.Это должно быть приведено к определенному типу сначала.

Если вы хотите увеличить его на определенное количество байтов, то это решение, которое я использую.

p = ((char*)p) + 12;

Тип char удобен, поскольку имеет определенный размер 1 байт.

EDIT

Интересно, что он работаетна gcc с предупреждением.Я протестировал на Visual Studio 2010 и убедился, что он не компилируется.Мое ограниченное понимание стандарта скажет, что gcc в ошибке здесь.Можете ли вы добавить следующие флаги компиляции

-Wall -ansi -pedantic
12 голосов
/ 26 октября 2010

Цитировать из спецификации:

§6.5.6 / 2 : Кроме того, либо оба операнда должны иметь арифметический тип, либо один операнд должен быть указателем натип объекта, а другой должен иметь целочисленный тип.(Увеличение эквивалентно добавлению 1.)

Указатель на void не является указателем на тип объекта, согласно этим выдержкам:

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

§6.5.5 / 19 : тип void содержит пустой набор значений;это неполный тип, который не может быть завершен.

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

4 голосов
/ 26 октября 2010

Это зависит от компилятора.Те, которые позволяют это, рассматривают sizeof (* (void *)) как 1.

EDIT: это только для арифметики пустого указателя.Не имеет смысла использовать в этом случае шаги sizeof (int) или 0. Общие ожидания того, кто его использует, будут наименьшим возможным шагом.

2 голосов
/ 17 февраля 2014

Возможно, вы захотите взглянуть на лучший ответ на этот вопрос

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

2 голосов
/ 26 октября 2010

Ваше предположение верно.

В стандарте ISO C99, раздел 6.2.5, параграф 26, объявляется, что пустые указатели и указатели символов будут иметь одинаковые требования к представлению и выравниванию (перефразируя).

1 голос
/ 26 октября 2010

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

Сначала приведите его к типу, то есть (int).

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