2012-04-18 6 views
12

Ich habe eine solche Struktur (aus irgendeinem Grund kann ich nicht nur ein Array verwenden):sizeof Berechnungsfehler Mitglied

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]; 
    }; 

Und ich versuche Menge von Feldern zur Compile-Zeit zu berechnen:

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

und der Compiler Berichte eine solche Nachricht:

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

ich benutze keil uVision3 V3.60. Es ist egal, wo ich enum Deklaration innerhalb oder außerhalb der Struktur platzieren. Warum kann der Compiler die Größe dieses Elements nicht annehmen?

+0

Das Argument der 'sizeof' sollte ein Typ (nicht wahr hier) oder ein L-Wert sein (auch nicht wahr). – Matthias

+0

@Matthias: Der Operand muss kein _lvalue_ sein; Jeder Ausdruck ist erlaubt, solange sein Typ für 'sizeof' geeignet ist. –

+2

Sie sollten auch die Datenausrichtung berücksichtigen, die von Pragmas gesteuert wird, wie hier beschrieben http://stackoverflow.com/a/10207185/147763 –

Antwort

12

Offenbar unterstützt Ihr Compiler nicht C++ 11, das die Verwendung von Type::member in nicht bewerteten Ausdrücken ermöglicht.Sie werden einen Ausdruck des richtigen Typs herstellen müssen, so etwas wie:

OperatorData* noImpl(); 

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

+1. Schön. Besser als meins! – Nawaz

+1

Übrigens ist 'OperatorData noImpl();' auch in Ordnung. Dann musst du 'sizeof (noImpl(). M_record_0)' schreiben. – Nawaz

+0

Ist 'noImpl' nicht eine Funktion? –

0

Dies liegt daran, m_record_0 ist kein statisches Mitglied der Struktur OperatorData. Sie können das nur tun, wenn es sich um ein statisches Mitglied handelt.

+0

Aber ist Größe des Feldes nicht zur Kompilierzeit bekannt? –

+0

Ja, sizeof ist ein Kompilieroperator, der korrekt ist. Das Problem ist, dass Sie von OperatorData :: m_record_0 nicht auf das Member verweisen können, egal wann, wenn m_record_0 kein statisches Member Ihrer Struktur ist. –

0

Erstellen Sie ein Objekt Ihrer Struktur und verwenden Sie sizeof() Operator darauf.

4

Ich glaube nicht, dass das sicher ist; Zwischen den Mitgliedern oder nach den Mitgliedern kann ein Padding eingefügt werden, der in sizeof (OperatorData) enthalten ist, aber nicht in einer bestimmten Mitgliedsgröße.

Natürlich können Sie den bereits verfügbaren RIX_OPERATOR_CONFIG_SIZE Wert verwenden könnte eine Annäherung zu bekommen:

const size_t num_records = sizeof (OperatorData)/RIX_OPERATOR_CONFIG_SIZE; 

es unter der Annahme, nur für char Arrays verwendet, und dass es Zwerge jede Polsterung.

Sie auch offsetof() verwenden können, hat dies den Vorteil, zumindest Polsterung zwischen den Mitgliedern, darunter:

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

Hinweis, wieder, dass dies auch nur eine Annäherung ist. Hoffentlich ist jedes Padding viel kleiner als die Mitglieder selbst, so dass ihr Beitrag abgerundet wird.

3

Ein nicht statisches Element kann nicht mit dem Operator :: aufgerufen werden.

In C++ 11, Sie können dies tun (quick demo):

#include <utility> 

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

Und in C++ 03, dies zu tun:

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

Der Typ des Ausdrucks ((OperatorData*)(0)) ist OperatorData* , so verwenden ((OperatorData*)(0))->m_record_0 ich die Größe zu erhalten, die zu dieser entspricht in etwa:

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

Aber es ist nicht genau dasselbe, wie die obige Anweisung ausgeführt wird, aber der Ausdruck in sizeof() wird nicht ausgeführt.

5

Verwendung typedefs:

typedef char RecordType[RIX_OPERATOR_CONFIG_SIZE]; 

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

Dann:

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

+1: Mann, du bist schneller als ich;) –