Могу ли я сделать арифметику на указатели void * в C?

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

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

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

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

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

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

Резюме:

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

  • gcc (4) разрешает это и обрабатывает как char *
  • G ++ отказывается от этого
  • об этом предупреждает gcc -pedantic
  • vs2010 и c и C++ отказываются

6 ответов

Решение

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

РЕДАКТИРОВАТЬ: это только для арифметики пустого указателя. Не имеет смысла использовать в этом случае шаги sizeof(int) или 0. Общие ожидания того, кто его использует, будут наименьшим возможным шагом.

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

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

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

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

РЕДАКТИРОВАТЬ

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

-Wall -ansi -pedantic

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

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

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

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

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

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

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

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

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

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

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

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

Другие вопросы по тегам