2012-04-18 6 views
12

Tengo una estructura de este tipo (por alguna razón no puedo sólo tiene que utilizar una matriz):sizeof error de cálculo miembro de

struct OperatorData 
    { 
    char m_record_0[RIX_OPERATOR_CONFIG_SIZE]; 
    char m_record_1[RIX_OPERATOR_CONFIG_SIZE]; 
    //.... 
    char m_record_9[RIX_OPERATOR_CONFIG_SIZE]; 
    }; 

Y yo estoy tratando de calcular la cantidad de campos en tiempo de compilación:

enum {fieldsAmount = sizeof(OperatorData)/sizeof(OperatorData::m_record_0)}; 
un mensaje

y los informes del compilador como:

Error: #245: a nonstatic member reference must be relative to a specific object 
    enum{fieldsAmount = sizeof(OperatorData)/sizeof(OperatorData::m_record_0)}; 
                   ^

utilizo Keil uVision3 V3.60. No importa dónde coloque la declaración enum dentro o fuera de la estructura. ¿Por qué no puede el compilador tomar el tamaño de este membmer?

+0

El argumento de 'sizeof' debe ser un tipo (no es cierto aquí) o un valor L (tampoco es verdad) – Matthias

+0

@Matthias: el operando no tiene que ser un _lvalue_; se permite cualquier expresión, siempre que su tipo sea apropiado para 'sizeof'. –

+2

También debería considerar la alineación de datos, controlada por pragmas, como se describe aquí http://stackoverflow.com/a/10207185/147763 –

Respuesta

12

Parece que su compilador no admite C++ 11 que permite el uso de Type::member en expresiones no evaluadas.Vas a tener que fabricar una expresión del tipo correcto, algo así como:

OperatorData* noImpl(); 

enum{fieldsAmount = sizeof(OperatorData)/sizeof(noImpl()->m_record_0)}; 
+0

+1. Buena esa. ¡Mejor que el mío! – Nawaz

+1

Por cierto, 'OperatorData noImpl();' también está bien. Luego debe escribir 'sizeof (noImpl(). M_record_0)'. – Nawaz

+0

¿No es 'noImpl' una función? –

0

Esto es porque m_record_0 no es un miembro estático de la estructura OperatorData. Solo puedes hacer eso cuando es un miembro estático.

+0

¿Pero no se conoce el tamaño del campo en tiempo de compilación? –

+0

Sí, sizeof es un operador en tiempo de compilación que es correcto. El problema es que no puede hacer referencia al miembro por OperatorData :: m_record_0 sin importar cuándo, si m_record_0 no es un miembro estático de su estructura. –

0

Crea un objeto de tu estructura y usa el operador sizeof() en él.

4

No creo que esto sea seguro; puede haber relleno añadido entre o después de los miembros, que se incluirá en sizeof (OperatorData) pero no en el tamaño de ningún miembro específico.

Por supuesto, usted podría utilizar el valor ya disponible RIX_OPERATOR_CONFIG_SIZE para obtener una aproximación:

const size_t num_records = sizeof (OperatorData)/RIX_OPERATOR_CONFIG_SIZE; 

suponiendo que sólo se usa para char matrices, y que los enanos cualquier relleno.

También puede utilizar offsetof(), esto tiene la ventaja de incluir al menos relleno entre los miembros:

const size_t num_records = sizeof (OperatorData)/
     (offsetof(OperatorData, m_record_1) - offsetof(OperatorData, m_record_0)); 

nota, de nuevo, que esto también es sólo una aproximación. Con suerte, cualquier relleno será mucho más pequeño que los propios miembros para que su contribución se redondeará.

3

No se puede acceder a un miembro no estático mediante el operador ::.

En C++ 11, se puede hacer esto (quick demo):

#include <utility> 

size = sizeof(OperatorData)/sizeof(std::declval<OperatorData>().m_record_0); 

Y en C++ 03, haga lo siguiente:

size = sizeof(OperatorData)/sizeof(((OperatorData*)(0))->m_record_0); 

El tipo de la expresión ((OperatorData*)(0)) es OperatorData* , así que uso ((OperatorData*)(0))->m_record_0 para obtener el tamaño que es más o menos equivalente a esto:

OperatorData* od = ((OperatorData*)(0)); 
size_t size = sizeof(od->m_record_0); 

Pero no es exactamente lo mismo, ya que la declaración anterior se ejecutará, pero la expresión en sizeof() no se ejecutará.

5

Use typedefs:

typedef char RecordType[RIX_OPERATOR_CONFIG_SIZE]; 

struct OperatorData 
{ 
    RecordType m_record_0; 
    RecordType m_record_1; 
    //.... 
    RecordType m_record_9; 
}; 

continuación:

enum {fieldsAmount = sizeof(OperatorData)/sizeof(RecordType)}; 
+0

+1: Hombre, eres más rápido que yo;) –