2010-03-17 18 views
8

In che modo C++ ottiene la lunghezza dell'array solo con i puntatori? So che il nome della scheda è puntatore al primo elemento, ma quale sarà il prossimo?Lunghezza array con puntatori

risposta

9

Non è possibile. Un puntatore è solo una posizione di memoria e non contiene nulla di speciale che possa determinare la dimensione.

Poiché si tratta di C++, che cosa si può fare è passare la matrice per riferimento in questo modo:

template <typename T, size_t N> 
void handle_array(T (&pX)[N]) 
{ 
    // the size is N 

    pX[0] = /* blah */; 
    // ... 
    pX[N - 1] = /* blah */; 
} 

// for a specific type: 
template <size_t N> 
void handle_array(int (const &pX)[N]) // const this time, for fun 
{ 
    // the size is N 

    int i = pX[0]; // etc 
} 

Ma per il resto è necessario passare iniziare & fine e fare una sottrazione, come suggerisce Alok, un inizio & dimensioni, come suggerisci tu, o metti un array statico e usa un vettore, come suggerisce Tyler.

Se si conosce la dimensione della matrice lavorerete con, si può fare una typedef:

typedef int int_array[10]; 

void handle_ten_ints(int_array& pX) 
{ 
    // size must be 10 
} 

E proprio per le dimensioni:

template <typename T, size_t N> 
size_t countof(T (&pX)[N]) 
{ 
    return N; 
} 

template <typename T, size_t N> 
T* endof(T (&pX)[N]) 
{ 
    return &pX[0] + N; 
} 

// use 
int someArray[] = {1, 2, 6, 2, 8, 1, 3, 3, 7}; 

size_t count = countof(someArray); // 9 
std::for_each(someArray, endof(someArray), /* ... */); 

io uso queste funzioni di utilità di volta in volta.

+0

È meglio usare 'typedef' per creare un tipo di array e accettare un riferimento a questo, per eliminare il' template', a meno che questi metodi non si trovino in un file di intestazione e la dimensione dell'array effettivamente vari (rimanendo deterministico in fase di compilazione). – Potatoswatter

+0

@Potatoswatter: non sono a conoscenza di un modo per creare un typedef del genere. N non è noto alla funzione finché non viene istanziato con una chiamata. Aggiungerò un esempio di typedef, è questo che intendevi? – GManNickG

+0

Sì, l'esempio che hai aggiunto è ciò che intendevo. 'template ' è carino con auto-sized 'int ary [] = {...};' ma l'istanza potrebbe essere scomoda/confusa e il vantaggio è piccolo AFAIK a meno che l'array non sia dichiarato così. O l'utente sta lavorando con diverse dimensioni fisse. – Potatoswatter

15

Non puoi farlo. È necessario passare la lunghezza dell'array insieme al puntatore dell'array oppure è necessario utilizzare un oggetto contenitore come std::vector.

+0

E presto std :: array :) – coelhudo

+2

A questo punto mi aspetto di raccogliere la sicurezza sociale al momento in cui C++ 4x è finalizzato. –

+0

Non vedo quale sia il grosso problema: puoi usare boost :: array adesso. –

3

Vuoi dire qualcosa come:

int a[10]; 
int *start = a; 
int *end = a + 10; 
size_t n = end - start; /* pointers! :-) */ 
+2

No, un puntatore "fine" è convenzionalmente one-past-the-end (che è legale) in modo specifico in modo che end - start = length, e in modo che tu possa fare cose come 'for (int * i = start; i! = end; ++ i)'. –

+0

@Tyler: grazie. –

0

Non è possibile, se non sai cosa le dereferenziazioni di puntatori end a. Nel caso di array di caratteri, è un '\ 0', quindi è possibile eseguire il ciclo finché non si legge quel carattere per calcolare la lunghezza.

+1

Nel caso di * stringhe * è convenzionalmente '\ 0'. Non tutti gli array di caratteri sono una stringa. – Potatoswatter