2011-06-30 8 views
9

Este ejemplo:Cómo comparar objetos de tipo POD

#include <iostream> 
#include <cstring> 

struct A 
{ 
    int a; 
    bool b; 
}; 

bool foo(const A a1, const A a2) 
{ 
    return (0 == std::memcmp(&a1, &a2, sizeof(A))); 
} 

int main() 
{ 
    A a1 = A(); 
    a1.a = 5;a1.b = true; 
    A a2 = A(); 
    a2.a = 5;a2.b = true; 

    std::cout<<std::boolalpha << foo(a1, a2) << std::endl; 
} 

va a producir false, a causa de relleno.

No tengo acceso a la función foo, y no puedo cambiar la forma en que se realiza la comparación.

Suponiendo una bool ocupa 1 byte (eso es cierto en mi sistema), si cambio el struct A a esto:

struct A 
{ 
    int a; 
    bool b; 
    char dummy[3]; 
}; 

entonces funciona bien en mi sistema (la salida es true).

¿Hay algo más que pueda hacer para solucionar el problema anterior (obtenga la salida true)?

+0

¿Por qué estás pasando por 'const' value y no por' const & '? ==> 'foo (const A a1, const A a2);' – iammilind

+0

@iammilind La función 'foo' es de una biblioteca de terceros, y no tengo acceso para cambiar su firma –

+0

¿Ha intentado empaquetar la estructura desde que parece tener control sobre eso? De esta forma, es posible que no tengas que usar el "truco" del memset. VS: '#pragma pack (1)' justo antes de la estructura. G ++ mismo. http://msdn.microsoft.com/en-us/library/2e70t5y1%28v=vs.80%29.aspx http://gcc.gnu.org/onlinedocs/gcc/Structure_002dPacking-Pragmas.html – RedX

Respuesta

11

El primero no funciona debido al relleno en la estructura. El relleno tiene diferentes patrones de bits para ambos objetos.

Si utiliza memset para establecer todos los bits en el objeto antes de usarlo, entonces todo funcionará:

A a1; 
std::memset(&a1, 0, sizeof(A)); 
a1.a = 5;a1.b = true; 

A a2; 
std::memset(&a2, 0, sizeof(A)); 
a2.a = 5;a2.b = true; 

demostraciones en línea:


Por cierto, puede escribir operator<, operator== etc., también para POD.

+0

'A a1 = A();' es igual que 'A a1; std :: memset (& a1, 0, sizeof (A)); '. Puedo escribir operadores para POD, pero no tengo acceso a la función que realiza la comparación, por lo tanto estoy atascado con std :: memcmp –

+1

@VJo: NO. No es lo mismo 'A a1 = A()' inicializa solo los miembros, no el relleno. Es decir, 'A a1 = A()' es equivalente a 'A a1; memset (& a1.a, 0, sizeof (a1.a)); memset (& a1.b, 0, sizeof (a1.b)); '. Los bytes restantes '(sizeof (A) - sizeof (a1.a) - sizeof (a1.b))' permanecen como tales, y contienen basura. – Nawaz

+0

Bueno, diciendo estrictamente, 'A a1 = A()' *** no está garantizado *** para inicializar el relleno, pero aún puede hacerlo. – sharptooth

Cuestiones relacionadas