2016-04-22 3 views
1

Люди имеет коданнулируются * Тип обугливаться * Тип leadng

#include <conio.h> 
#include <stdio.h> 

void dbleInt(void *a) { 
    *((int*) a) *= 2; 
} 

void deleteEvenInt(void* a) { 
    int tmp = *((int*) a); 
    if (tmp % 2 == 0) { 
     *((int*) a) = 0; 
    } 
} 

void dbleDouble(void *a) { 
    *((double*) a) *= 2.0; 
} 

void deleteEvenDouble(void* a) { 
    int tmp = *((double*) a); 
    if (tmp % 2 == 0) { 
     *((double*) a) = 0; 
    } 
} 

// Function takes an array, its size, the size of one element and a function //pointer, 
// Which is then applied to all the elements of an array 
void map(void *arr, unsigned num, size_t size, void (*fun)(void *)) { 
    unsigned i; 
    char *ptr = (char*) arr; 
    for (i = 0; i < num; i++) { 
     fun((void*) (ptr + i*size)); 
    } 
} 

Почему он ведет аннулируется * типа обугливаться * типа? Я вижу, что это ошибка, когда я меняю этот код и не веду его, но почему?

+0

Атрибут указателя на тип 'void *' определяется его недопустимым стандартом (поскольку размер типа 'void' (например,' sizeof (void) ') не определен). Это расширение, позволяющее ему НКА. (Расширение установлено на 1 размер 'void') – BLUEPIXY

+0

« У человека есть код »- извините, но никто не может помочь –

ответ

2

Вам не разрешено выполнять арифметические действия недействительных указателей в C. Таким образом, следующий код неверен:

void *foo = whatever; 
foo + 1; 

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

+0

Чтобы НЕ нарушать строгий псевдоним, вызывающий пользователь должен был убедиться, что правильный тип передан каждая функция ,,, Например, 'double x = 3.0; dbleInt (&x); 'было бы нарушением строгой псевдонимы, верно? – yano

0

Мои комментарии о том, почему void *ptr, нельзя выполнить адресную арифметику. Предупреждение, длинные бессвязные :).

В общем когда вы сделать PTR арифметическая как

ptr = ptr + N ; 

Интерпретация с помощью C является выполнение следующих эквивалентных целочисленной арифметики (Infact компилятор будет производить сборку кода, эквивалентный ниже целочисленной арифметики)

ptr = ptr + N * sizeof (typeof (* N));

Следовательно, для получения кода компилятор должен знать тип (* N). typeof (* N) здесь означает, что тип переменной «ptr» указывает на. (typeof не является стандартной конструкцией c, она покупается здесь для простого объяснения).

Возьмите, например,

int x ; // Assume x is at addesss 1000 
int *ptr = &x ; // ptr has a value of 1000 

Тогда PTR = PTR + 1;
бы PTR в 1004 во время выполнения (предполагается, что размер Int составляет 4 байта)

Пояснение-1: Приведенные выше утверждение означает, что PTR должен содержать адрес следующей переменной целочисленного после PTR. Поскольку ptr указывает на x, который находится по адресу 1000, следующая целочисленная переменная после 1000 будет равна 1004. Таким образом, ptr будет равен 1004.

Пояснение-2 Это также синхронизируется с интерпретацией ptr = ptr + N эквивалентно целому числу arithmeitc

ptr = ptr + N* sizeof (typeof(*N)) ; // typeof (*N)->int 
      // => 1000 + 1 *sizeof (typeof (int)) 
           // => 1004 

Резюмируя для операции PTR Arith

ptr = ptr + N ; 

компилятор выдает эквивалентный код сборки как

р тр = PTR + N * SizeOf (TypeOf (* N)) // компилятор должен TYPEOF (* N)

Поэтому компилятор должен знать, что это тип данных, который PTR указывает на.

Теперь рассмотрим

void foo (int type, void *ptr) { 

    ptr = ptr + 2 ; 
} 
f2() { 
int x ; 
char c ; 
f1(&x) ; 
f1(&c); 
} 

Пустота * PTR является родовым PTR, указывающий на addresss.Когда вызывается с f1 (x), ptr указывает на адрес целого числа, при вызове с f1 (& c) он указывает на адрес символа. Поэтому во время компиляции компилятор не может определить, что такое typeof (* ptr). (в одном случае это целое число, а другое - символ). Следовательно, компилятор не может сгенерировать код для ptr = ptr + n;

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

Надеюсь, это поможет.

Смежные вопросы