Могу ли я сделать арифметику на указателях void * в C?
- это действительный
void *p = &X; /* some thing */
p += 12;
и если да, то на что указывает p?
У меня есть (сторонний) код, который делает это (и компилируется чисто), и я предполагаю, что void * рассматривался как char *. Мой надежный K & R не работает (ish) по теме
EDIT: мое маленькое тестовое приложение отлично работает на gcc 4.1.1 и обрабатывает void * как char *. Но g++ barfs
Я знаю, как это сделать правильно. Мне нужно знать, нужно ли мне очищать эту базу кода, чтобы найти все места, которые она сделала.
BTW gcc -pedantic выдает предупреждение
Резюме:
Спецификация C неоднозначна. В нем говорится, что в терминах представления и использования в качестве параметров функции void * = char *. Но он молчал относительно арифметики указателя.
- gcc (4) разрешает это и рассматривает его как
char *
- g++ отказывается от него
- gcc -pedantic предупреждает об этом
- vs2010 и c и С++
отказывается от него.
Ответы
Ответ 1
Это зависит от компилятора. Те, которые позволяют ему рассматривать sizeof (* (void *)) как 1.
EDIT: это только для арифметики указателей пустот. Было бы бесполезно использовать в этом случае шаги sizeof (int) или 0. Общим ожиданиям того, кто его использует, был бы наименьший возможный шаг.
Ответ 2
Нет, это не законно. A void*
не может быть произвольно увеличен. Сначала его нужно перенести на определенный тип.
Если вы хотите увеличить его на определенное количество байтов, то это решение, которое я использую.
p = ((char*)p) + 12;
Тип char
удобен, поскольку он имеет размер 1 байт.
EDIT
Интересно, что он работает на gcc с предупреждением. Я тестировал Visual Studio 2010 и проверял, что он не компилируется. Мое ограниченное понимание стандарта скажет, что gcc в ошибке здесь. Можете ли вы добавить следующие флаговые компиляции
-Wall -ansi -pedantic
Ответ 3
Процитировать по спецификации:
§6.5.6/2. Для добавления оба операнда должны иметь арифметический тип, или один операнд должен быть указателем на тип объекта, а другой должен иметь целочисленный тип. (Инкремент эквивалентен добавлению 1.)
Указатель на void не является указателем на тип объекта, в соответствии с этими выдержками:
§6.2.5/1: [...] Типы разделены на типы объектов (типы, которые полностью описывают объекты), типы функций (типы описывающие функции) и неполные типы (типы, описывающие объекты, но не имеющие информация, необходимая для определения их размеров).
§6.2.5/19: тип void содержит пустой набор значений; это неполный тип, который не может быть завершено.
Следовательно, арифметика указателя не определена для указателя на типы void.
Ответ 4
Ваша догадка правильная.
В стандарте ISO C99, раздел 6.2.5, пункт 26, он заявляет, что указатели void и указатели на символы будут иметь те же требования к представлению и выравниванию (перефразирование).
Ответ 5
Вы можете захотеть взглянуть на главный голосовой ответ на этот вопрос
Арифметика указателя для указателя void в C
Ответ 6
Я не думаю, что вы можете, потому что он не знает своего типа, поэтому не может найти правильное количество байтов.
Сначала переведите его в тип, т.е. (int)
.