2013-04-15 17 views
13

ero alla ricerca di un modo per trovare la dimensione di un array in C senza l'utilizzo di sizeof in C e ho trovato il seguente codice:dimensioni Ricerca di array senza utilizzare sizeof in C

int main() 
{ 
    int arr[100]; 
    printf ("%d\n", (&arr)[1] - arr); 
    return 0; 
} 

Qualcuno può per spiegami come funziona?

+3

Non c'è mai un motivo per cui non è possibile utilizzare 'sizeof'. – Lundin

+0

Sembra che la matrice, che ha 100 elementi, sia effettivamente trattata come elemento 0 di una matrice (senza nome). – enhzflep

+0

Bel trucco, è anche conforme agli standard. – effeffe

risposta

23

&arr è un puntatore a un array di 100 int s.

Il [1] significa "aggiungi la dimensione della cosa puntata", che è una matrice di 100 int s.

Quindi la differenza tra e arr è 100 int s.

(Si noti che questo trucco funziona solo in luoghi dove sizeof avrebbe funzionato comunque.)

+6

' [1] 'non significa" aggiungi la dimensione della cosa puntata ". Significa "aggiungi la dimensione della cosa puntata e poi dereferenzia il puntatore risultante". –

12

&arr ti dà un puntatore alla matrice. è equivalente a *(&arr + 1). &arr + 1 fornisce un puntatore all'array di 100 ints che segue arr. Dereferenziarlo con * ti dà quella matrice che segue. Poiché questo array viene utilizzato in un'espressione additiva (-), decompone il puntatore al suo primo elemento. Lo stesso accade a arr nell'espressione. Quindi devi sottrarre ai puntatori, uno che punta all'elemento inesistente subito dopo arr e l'altro che punta al primo elemento di arr. Questo ti dà 100.

Ma non funziona. %d viene utilizzato per int. La differenza di puntatore ti restituisce ptrdiff_t e non int. È necessario utilizzare %td per ptrdiff_t. Se menti a printf() dei tipi di parametri che stai passando ad esso, ottieni un comportamento indefinito meritato.

EDIT: maggio causa comportamento non definito. Non è completamente chiaro. Vedi i commenti qui sotto, se interessati.

+2

Non è '(& arr) [1] - arr' anche un comportamento indefinito? –

+2

@DanielFischer C99: Operatori additivi: 'Ai fini di questi operatori, un puntatore a un oggetto che non è un elemento di una matrice si comporta come un puntatore al primo elemento di una matrice di lunghezza uno con il tipo di oggetto come il suo tipo di elemento. Quindi, sembra che questo sia OK. Intendo la parte '[1]'. E il resto è come al solito. –

+0

Ma l'ultima frase nel paragrafo 8 di questo è "Se il risultato punta oltre l'ultimo elemento dell'oggetto array, non deve essere usato come l'operando di un operatore un *' 'che viene valutato." E '(& arr) [1]' valuta il '*' in '* (& arr + 1)', se ho capito bene. Va bene se si prende l'indirizzo, di '(& arr) [1]', o si applica 'sizeof' ad esso, che non valuta il' * ', ma con' -'? –

1

generale (secondo studio visivo), per un array &arr è stessa arr, che restituisce l'indirizzo base di partenza della nostra funzione.

(&arr)[0] non è altro che &arr o arr

ex: tornerà qualche indirizzo: 1638116

Ora, significa che siamo partiti l'accesso alla gamma di rimbalzo significa successivo array o segmento successivo la dimensione dell'array attuale (100 avanti).

ex: tornerà qualche indirizzo: 1638216

Ora, sottraendo (&arr)[1] - (&arr)[0]=100

+0

"***' (& arr) [0] 'non è altro che' & arr' o 'arr' ***" - 'arr' e' & arr' hanno diversi tipi quando entrambi puntano alla stessa posizione. Il primo è di tipo 'int *' mentre il secondo è di tipo 'int (*) [100]'. –

0

&variable dà posizione della variabile (lo chiamano come P)
&variable + 1 dà indirizzo del luogo accanto alla variabile. (Chiamare come N)

(char*)N-(char*)P dà quanti caratteri ci sono tra N e P. Poiché ciascun carattere ha una dimensione di 1 byte, il risultato sopra riportato indica il numero di byte P e N. (che è uguale alla dimensione della matrice in byte).

Analogamente, (char*) (a+1)-(char*)a; fornisce la dimensione di ogni elemento della matrice in byte.

Così il numero di elementi nella matrice = (size of array in bytes)/(size of each element in the array in bytes)

#include<stdio.h> 

int main() 
{ 
    int a[100]; 
    int b = ((char*)(&a+1)-(char*)(&a)); 
    int c = (char*) (a+1)-(char*)a; 
    b = b/c; 
    printf("The size of array should be %d",b); 
    return 0; 

} 
-1
int main() 
{ 
    int arr[100]; 
    printf ("%d\n", ((char*)(&arr+1) - (char*)(&arr))/((char*) (arr+1) -(char*) (arr))); 
    return 0; 
} 
+2

Sebbene questo codice possa rispondere alla domanda, fornire un contesto aggiuntivo sul perché e/o su come questo codice risponde alla domanda migliora il suo valore a lungo termine. – JAL

+0

Sarò felice di revocare la tua risposta se aggiungerai qualche spiegazione su come funziona il tuo codice. A proposito, dovresti usare '% ld', non'% d'. –