Сравнивая с пустыми указателями, чей фактический тип известен - PullRequest
1 голос
/ 28 февраля 2012

Я немного растерялся, как сделать следующее:

void myMethod(void *ary, void *b, MPI_Datatype type) {

   if(ary[0] != b) { 
        /* do something */
   }

}

b имеет тип type, ary - это массив type. (Указатели void используются, чтобы позволить вызывающей стороне передавать элементы любого типа MPI_Datatype). Как сравнить элемент ary с b?

Я попытался посмотреть вещи, но застрял со следующей ошибкой (используя `mpicc -ansi -std = c99 -Wall -g -c):

warning: dereferencing `void *` pointer [enabled by default]
error: void value not ignored as it ought to be

РЕДАКТИРОВАТЬ: я исправил опечатку в функциональной главе: tpye -> type. Я надеюсь, что это не вызвало большого замешательства

Ответы [ 5 ]

3 голосов
/ 28 февраля 2012

Разыменование void* не допускается через * в смещении [].Вам нужно преобразовать их в соответствующий тип с помощью приведения, прежде чем вы сможете разыменовать.

void myMethod(void *ary, void *b, MPI_Datatype tpye) {

  type* aryType = ary;
  type* bType = b;
  if (aryType[0] != *bType) {
    // Do something
  }
}
2 голосов
/ 28 февраля 2012

Вы не можете разыменовывать указатели void.

Если целью функции является сравнение a и b без типа, известного как тип в C (который не является значением MPI_Datatype), вы можете использовать memcmp ():


void myMethod(void *ary, void *b, MPI_Datatype type)
{
    int sz;
    MPI_Type_size(type, &sz);
    if (memcmp(ary, b, sz) {
        // do something
    }
}

2 голосов
/ 28 февраля 2012

Вы не можете разыменовать указатели на void, сначала приведите их к соответствующему типу:

((type *) ary)[0] != (type) b

Например, если ваш type является указателем на char *, вы должны сделать:

((char **) ary)[0] != (char *) b
1 голос
/ 28 февраля 2012

Вы не можете передать тип в качестве параметра функции в C.

MPI использует значения типа MPI_Datatype, чтобы указать, какой тип передается, но что касается кода C, все, что выwrite для того, чтобы что-то действительно делать с объектом, должно обрабатывать этот объект как фактический тип, известный во время компиляции.

Итак, MPI, вероятно, предоставляет вам некоторые функции, которые немного помогают (janneb указывает MPI_Type_sizeи я не знаю, какие есть другие).Но для такого рода вещей в C вам часто приходится кропотливо писать код для каждого типа:

switch(type) {
    MPI_LONG_DOUBLE:
        /* having said this, equality checks on floating-point types
           are often a mistake anyway due to rounding errors making
           values come out non-equal when "really" they're equal for
           your purposes. But that's a whole subject of its own.
        */
        if (*(long double*)ary != *(long double*)b) /* do something */;
        break;
    MPI_DOUBLE:
        if (*(double*)ary != *(double*)b) /* do something */;
        break;
    MPI_FLOAT:
        if (*(float*)ary != *(float*)b) /* do something */;
        break;
    MPI_INT:
        if (*(int*)ary != *(int*)b) /* do something */;
        break;
    /* etc ... */
    MPI_UNSIGNED_CHAR:
        if (*(unsigned char*)ary != *(unsigned char*)b) /* do something */;
        break;
    default:
        /* janneb's code */
        int sz;
        MPI_Type_size(type, &sz);
        if (memcmp(ary, b, sz) {
            // do something
        }
        /* or it might be better to indicate an error, so that any types
           you haven't dealt with explicitly can be added to the code
           when encountered.
        */
}

На самом деле, код janneb будет работать для всех целочисленных типов практически во всех реализациях C, которые вас интересуютимя, но если вы заботитесь о «правильной» переносимости, вам, вероятно, следует все равно обращаться с ними особо.

Очевидно, что вы действительно не захотите дублировать /* do something */ в своем коде, поэтому вы, вероятно, определите функциюequals, и назовите это из теста if в myMethod.

1 голос
/ 28 февраля 2012

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

((myArrayType*)ary)[0] != b

или (char*)ary + (size_element_in_bytes * index ) != (char*)b

...