пустота * арифметика - PullRequest
       2

пустота * арифметика

23 голосов
/ 13 октября 2010
#include<stdio.h>
int main(int argc,char *argv[])
{
   int i=10;
   void *k;
   k=&i;

   k++;
   printf("%p\n%p\n",&i,k);
   return 0;
}

Является ли ++ допустимой операцией для void *? Некоторые книги говорят, что это не но K & R ничего не говорит об арифметике void * (стр. 93,103,120,199 из K & R 2 / e)

Пожалуйста, уточните.

PS: GCC не жалуется, по крайней мере, на k ++.

Ответы [ 5 ]

34 голосов
/ 13 октября 2010

Это расширение GCC .

В GNU C операции сложения и вычитания поддерживаются для указателей на аннулирование и для указателей на функции. Это делается путем обработки размера void или функции как 1.

Если вы добавите флаг -pedantic, он выдаст предупреждение:

warning: wrong type argument to increment

Если вы хотите соблюдать стандарт, наведите указатель на char*:

k = 1 + (char*)k;

Стандарт определяет, что нельзя выполнять сложение (k+1) на void*, потому что:

  1. Арифметика указателя выполняется путем обработки k как указателя на первый элемент (# 0) массива void (C99 §6.5.6 / 7), и k+1 вернет элемент # 1 в этом "массиве" (§6.5.6 / 8).

  2. Чтобы это имело смысл, нам нужно рассмотреть массив void. Соответствующая информация для void: (§6.2.5 / 19)

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

  3. Однако определение массива требует, чтобы тип элемента не был неполным (§6.2.5 / 20, сноска 36)

    Поскольку типы объектов не включают в себя неполные типы, массив неполного типа не может быть создан.

Следовательно, k+1 не может быть допустимым выражением.

5 голосов
/ 13 октября 2010

Нет, арифметика на void* не охватывается стандартом. Для этого используйте char*.

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

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

0 голосов
/ 13 октября 2010

Арифметика по пустоте * является расширением GCC.Когда я компилирую ваш код с помощью clang -Wpointer-arith, вывод будет:

test.c:9:4: warning: use of GNU void* extension [-Wpointer-arith]
k++;
~^

Обычное поведение приращения указателя состоит в добавлении размера типа pointee к значению указателя.Например:

<code>
int *p;
char *p2;
p++; /* adds sizeof(int) to p */
p2 += 2; /* adds 2 * sizeof(char) to p2 */

Поскольку void не имеет размера, вы не сможете выполнять арифметику указателей на void* указателях, но GNU C позволяет это.

0 голосов
/ 13 октября 2010

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

...