Domanda

Nel programma C riportato di seguito, non capisco perché buf[0] = 'A' dopo aver chiamato foo.foo non sta facendo pass-by-value?

#include <stdio.h>
#include <stdlib.h>

    void foo(char buf[])
    {
      buf[0] = 'A';
    }

    int main(int argc, char *argv[])
    {
      char buf[10];

      buf[0] = 'B';
      printf("before foo | buf[0] = %c\n", buf[0]);
      foo(buf);
      printf("after foo | buf[0] = %c\n", buf[0]);

      system("PAUSE"); 
      return 0;
      }

produzione:

before foo | buf[0] = 'B' 
after foo | buf[0] = 'A'
È stato utile?

Soluzione

void foo(char buf[])

è lo stesso di

void foo(char* buf)

Quando si chiama esso, foo(buf), si passa un puntatore per valore, per cui una copia del puntatore è fatto.

La copia dei punti puntatore allo stesso oggetto come puntatore originale (o, in questo caso, all'elemento iniziale dell'array).

C non ha passaggio dalla semantica di riferimento nel senso che C ++ ha passaggio dalla semantica di riferimento. Tutto in C è passato per valore. I puntatori sono utilizzati per ottenere passaggio dalla semantica di riferimento.

Altri suggerimenti

un array è solo un modo elegante per utilizzare un puntatore. Quando si passa buf alla funzione, si sta passando un puntatore per valore, ma quando si dereference il puntatore, si sta ancora riferimento la stringa a cui punta.

matrice come parametro di funzione è equivalente a un puntatore, quindi la dichiarazione

void foo( char buf[] );

è lo stesso di

void foo( char* buf );

L'argomento matrice è allora decaduto al puntatore al suo primo elemento.

Gli array vengono trattati in modo diverso rispetto agli altri tipi;non è possibile passare un array "per valore" in C.

Norma C99 online (bozza n1256), sezione 6.3.2.1, "Lvalue, array e designatori di funzioni", paragrafo 3:

Tranne quando è l'operando dell'operatore sizeof o Unary & Operator, o è una stringa letterale usata per inizializzare un array, un'espressione che ha un tipo "array di tipo" viene convertito in un'espressione con punta '' digitare '' che indica l'elemento iniziale dell'oggetto array e non è un lValue.Se l'oggetto array ha una classe di archiviazione del registro, il comportamento non è definito.

Nella chiamata

foo(buf);

l'espressione dell'array buf non è l'operando di sizeof O &, né è una stringa letterale utilizzata per inizializzare un array, quindi viene implicitamente convertito ("decadimento") dal tipo "array di 10 elementi di carattere" a "puntatore a carattere", e il indirizzo del primo elemento viene passato a foo.Pertanto, qualsiasi cosa tu faccia buf In foo() si rifletterà nel buf schieramento in main().A causa del modo in cui viene definito l'indice dell'array, è possibile utilizzare un operatore di indice su un tipo di puntatore in questo modo sembra come se stessi lavorando con un tipo di array, ma non lo sei.

Nel contesto di una dichiarazione di parametro di funzione, T a[] E T a[N] sono sinonimi di T *a, ma questo è soltanto caso in cui ciò sia vero.

* char buf [] in realtà significa char ** così si passa dal puntatore / riferimento. Che ti dà che buf è un puntatore, sia nel principale () e foo () la funzione.

Perché si passa un puntatore a buf (in valore). Così il contenuto che viene puntato da buf viene modificato.

Con i puntatori è diverso; si passa per valore, ma ciò che si sta passando è il valore del puntatore, che non è lo stesso del valore della matrice.

Quindi, il valore del puntatore non cambia, ma si sta modificando quello che sta indicando.

array e puntatori sono (quasi) la stessa cosa.

int* foo = malloc(...)

foo[2] è lo stesso di *(foo+2*sizeof(int))

aneddoto: hai scritto

int main(int argc, char *argv[])

è anche legale (compilerà e lavorare lo stesso) per scrivere

int main(int argc, char **argv)

e anche

int main(int argc, char argv[][])

essi sono effettivamente la stessa. sua leggermente più complicato di quello, perché un array sa quanti elementi ha, e un puntatore non lo fa. ma sono utilizzati lo stesso.

al fine di passare che per valore, la funzione avrebbe bisogno di conoscere la dimensione dell'argomento. In questo caso siete solo di passaggio un puntatore.

si passa per riferimento qui. In questo esempio, è possibile risolvere il problema facendo passare un singolo carattere in corrispondenza dell'indice dell'array desiderato.

Se si desidera conservare il contenuto della matrice originale, è possibile copiare la stringa di deposito temporaneo nella funzione.

modifica: Che cosa accadrebbe se si avvolto l'array char in una struttura e ha superato la struct? Credo che il lavoro potrebbe anche, anche se non so che tipo di spese generali che potrebbero creare a livello di compilatore.

Si prega di notare una cosa,

Dichiarazione

void foo(char buf[])

dice, che utilizzeranno [] notazione. Non quale elemento dell'array si intende utilizzare.

se si desidera precisare che, si vuole ottenere qualche valore specifico, allora si dovrebbe dichiarare questa funzione come

void foo(char buf[X]); //where X would be a constant.

Naturalmente non è possibile, perché sarebbe inutile (funzione per funzionare a n-esimo elemento dell'array?). Non è necessario annotare informazioni quale elemento di array che si desidera ottenere. Tutto quello che vi serve è semplice dichiarazione:

voi foo(char value);

così ...

void foo(char buf[])

è una dichiarazione che dice che la notazione che si desidera utilizzare. ([] - parte), e contiene anche puntatore ad alcuni dati

Inoltre ... che cosa ci si può aspettare ... hai mandato alla funzione foo un nome di array

foo(buf);

che è equivalente a & buf [0]. Quindi ... questo è un puntatore.

Array in C non sono passati per valore. Essi non sono nemmeno parametri di funzione legittimi. Al contrario, il compilatore vede che si sta cercando di passare un array e declassa al puntatore. Lo fa in silenzio, perché è il male. E piace anche a cuccioli calcio.

Utilizzo degli array di parametri di funzione è un bel modo per segnalare agli utenti API che questa cosa dovrebbe essere un blocco di memoria segmentata in n-byte di dimensioni pezzi, ma non aspettatevi compilatori per importa se si scrive char *foo char foo[] o char foo[12] in parametri di funzione. Non lo faranno.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top