2013-11-07 5 views
0

Мой фактический вопрос: действительно ли можно сравнить значения, содержащиеся в двух указателях пустот, если вы действительно знаете, что эти значения одного типа? Например, int.Значения указателя Void, сравнивающие C++

void compVoids(void *firstVal, void *secondVal){ 
    if (firstVal < secondVal){ 
      cout << "This will not make any sense as this will compare addresses, not values" << endl; 
    } 
} 

На самом деле мне нужно сравнить два недействительные значения указателей, в то время как за пределами функции известно, что тип внутр. Я не хочу использовать сравнение int внутри функции. Так что это не сработает для меня: if (*(int*)firstVal > *(int*)secondVal) Любые предложения? Большое вам спасибо за помощь!

+3

Это звучит как проблема XY. Почему вы пытаетесь сравнить void вместо фактических типов? Что вы пытаетесь сделать? –

+0

Я ответил на этот вопрос ниже. – user2962977

+3

Ваш вопрос не имеет никакого смысла. Вы говорите в начале своего вопроса, что сравнение адресов, а не значений, не имеет смысла (news-flash. Значение указателя *** - это адрес ***). Очень * следующее предложение * вы говорите: «Мне нужно сравнить два значения указателя void». Поэтому выберите один. Это адреса или значения * на * те адреса, которые вы хотите сравнить? – WhozCraig

ответ

0

Вы должны разыменовать их и гипс, с

if (*(int*) firstVal < *(int*) secondVal) 

Почему вы не хотите использовать int сравнения внутри функции, если вы знаете, что эти два значения будут int и что вы хотите сравнить значения int, на которые они указывают?


Вы упомянули функцию сравнения для сравнения данных о вставках; для функции сравнения, я рекомендую это:

int 
compareIntValues (void *first, void *second) 
{ 
    return (*(int*) first - *(int*) second); 
} 

Это следует условность отрицательным, если первый меньше, 0, если они равны, положительное значение, если первый больше. Просто вызовите эту функцию, если вы хотите сравнить данные int.

+0

Это потому, что я создаю двоичное дерево, и вне этой функции пользователь решает, какой тип данных он хочет вставить. Таким образом, данные внутри дерева будут всегда одного и того же типа, но содержатся в данных void *, которые выделяются в структуре. Чтобы переместиться внутри дерева и решить, где разместить значение, мне нужно сравнить их. – user2962977

+0

Обновлено, я рекомендую абстрагировать это на другую функцию. – Leigh

0

Это определенно возможно, но поскольку они являются указателями void, вы должны указать, сколько данных нужно сравнивать и как.

memcmp function может быть тем, что вы ищете. Он принимает два указателя void и аргумент для количества байтов, которые нужно сравнить, и возвращает сравнение. Однако некоторые сопоставления не зависят от всех равных данных. Например: сравнение направления двух векторов, игнорирующих их длину.

Этот вопрос не имеет определенного ответа, если вы не укажете, как вы хотите сравнить данные.

+0

Большое спасибо, я попробую! – user2962977

6

Чтобы сравнить данные, на которые указывает void*, вы должны знать, что это за тип. Если вы знаете, что такое тип, нет необходимости в void*. Если вы хотите, чтобы написать функцию, которая может быть использована для нескольких типов, можно использовать шаблоны:

template<typename T> 
bool compare(const T& firstVal, const T& secondVal) 
{ 
    if (firstVal < secondVal) 
    { 
     // do something 
    } 
    return something; 
} 

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

bool compare(void* firstVal, void* secondVal) 
{ 
    if (*firstVal < *secondVal) // ERROR: cannot dereference a void* 
    { 
     // do something 
    } 
    return something; 
} 

Итак, вам нужно чтобы узнать размер для сравнения, что означает, что вам нужно либо пройти в параметре std::size_t, либо вам нужно знать тип (и, действительно, для того, чтобы пройти в параметре std::size_t, вы должны знать тип):

bool compare(void* firstVal, void* secondVal, std::size_t size) 
{ 
    if (0 > memcmp(firstVal, secondVal, size)) 
    { 
     // do something 
    } 
    return something; 
} 

int a = 5; 
int b = 6; 
bool test = compare(&a, &b, sizeof(int)); // you know the type! 

Это было необходимо в C, поскольку шаблоны не существовали. В C++ есть шаблоны, которые делают этот тип объявления функций ненужным и неполным (шаблоны позволяют применять безопасность типа - указатели void не имеют значения, как я покажу ниже).

Проблема возникает, когда вы делаете что-то (глупо), как это:

int a = 5; 
short b = 6; 
bool test = compare(&a, &b, sizeof(int)); // DOH! this will try to compare memory outside the bounds of the size of b 
bool test = compare(&a, &b, sizeof(short)); // DOH! This will compare the first part of a with b. Endianess will be an issue. 

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

+2

Это путь. OP отмечает вопрос с C++, а использование указателей void - это C. –

0

Да. и на самом деле ваш код верен, если тип is unsigned int. литье значений int для указателя пустоты часто используется даже не рекомендуется.

Также вы могли бы бросить указатели, но вы должны бросить их непосредственно к типу INT:

if ((int)firstVal < (int)secondVal) 

Примечание: нет * на всех.

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

if ((intptr_t)firstVal < (intptr_t)secondVal) 
Смежные вопросы