Pregunta

En el programa de C por debajo, no entiendo por qué buf [0] = 'A' después de que llamo foo. No está haciendo foo pase por valor?

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

salida:

before foo | buf[0] = 'B' 
after foo | buf[0] = 'A'
¿Fue útil?

Solución

void foo(char buf[])

es el mismo que

void foo(char* buf)

Cuando se llama a ella, foo(buf), se pasa un puntero de valor, por lo que se hace una copia del puntero.

La copia de los puntos de puntero para el mismo objeto que el puntero original (o, en este caso, al elemento inicial de la matriz).

C no tiene pase por la semántica de referencia en el sentido de que C ++ tiene pase por la semántica de referencia. Todo en C se pasa por valor. Los punteros se utilizan para obtener un pase por la semántica de referencia.

Otros consejos

una matriz es sólo una forma elegante de utilizar un puntero. Cuando se pasa a la función buf, estás pasando un puntero por valor, pero cuando deja de hacer referencia el puntero, todavía estás referencia a la cadena que apunta.

Array como parámetro de la función es equivalente a un puntero, así que la declaración

void foo( char buf[] );

es el mismo que

void foo( char* buf );

El argumento de matriz es entonces cariado al puntero a su primer elemento.

Las matrices se tratan de manera diferente que otros tipos; no se puede pasar una matriz "por valor" en C.

C99 línea estándar (proyecto n1256) , sección 6.3.2.1, "Lvalues, órdenes, y designadores de función", párrafo 3:

  

A menos que cuando es el operando del operador sizeof o el unario operador &, o es una   literal cadena que se utiliza para inicializar una matriz, una expresión que tiene el tipo ‘‘matriz de tipo’’ es   convertido a una expresión con el tipo ‘‘puntero al tipo’’ que apunta al elemento inicial de   el objeto de matriz y no es un lvalue. Si el objeto de matriz tiene clase de registros de almacenamiento, la   comportamiento no está definido.

En la llamada

foo(buf);

el buf expresión de matriz no es el operando de sizeof o &, ni es una cadena literal que se utiliza para inicializar una matriz, por lo que se convierte implícitamente ( "desintegraciones") de tipo "array de 10 elementos de char" a "puntero a char", y el dirección del primer elemento se pasa a foo. Por lo tanto, cualquier cosa que haga a buf en foo() se refleja en la matriz buf en main(). Debido a cómo se define subíndices de matriz, se puede utilizar un operador subíndice en un tipo de puntero por lo que miradas como si estuvieras trabajando con un tipo de matriz, pero que no lo son.

En el contexto de una declaración de parámetros de función, T a[] y T a[N] son sinónimo de T *a, pero esto es solamente caso de que eso es cierto.

* auto char buf [] significa en realidad char ** por lo que estás pasando por puntero / referencia. Eso le da esa buf es un puntero, tanto en el principal () y foo () función.

Debido a que usted está pasando un puntero a buf (por valor). Por lo que el contenido que está siendo apuntado por buf se cambia.

Con punteros es diferente; está de paso por valor, pero lo que está pasando es el valor del puntero, que no es el mismo que el valor de la matriz.

Por lo tanto, el valor del puntero no cambia, sino que se está modificando lo que está señalando.

arreglos y apuntadores son (casi) la misma cosa.

int* foo = malloc(...)

foo[2] es el mismo que *(foo+2*sizeof(int))

anécdota: usted escribió

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

También es legal (compilará y funcionan de la misma) para escribir

int main(int argc, char **argv)

y

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

son efectivamente la misma. Es un poco más complicado que eso, debido a una serie sabe cuántos elementos tiene, y un puntero no lo hace. pero se utilizan de la misma.

a fin de pasar de que por valor, la función tendría que conocer el tamaño del argumento. En este caso estás de paso a un puntero.

está de paso por referencia aquí. En este ejemplo, puede resolver el problema haciendo pasar una sola Char en el índice de la matriz deseada.

Si desea conservar el contenido de la matriz original, que podría copiar la cadena de almacenamiento temporal en la función.

editar: ¿Qué pasaría si su matriz de caracteres envuelto en una estructura y pasó la estructura? Creo que el trabajo de fuerza también, aunque no sé qué tipo de sobrecarga que pueda crear en el nivel compilador.

Lo favor nota uno,

declaración

void foo(char buf[])

dice, que va a utilizar [] notación. No es el que elemento de la matriz que va a utilizar.

si le gustaría señalar que, desea obtener algún valor específico, entonces usted debe declarar esta función como

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

Por supuesto que no es posible, porque sería inútil (función para operar en el n-ésimo elemento de la matriz?). Usted no tiene que anotar la información qué elemento de la matriz que desea obtener. Todo lo que necesita es simple declaración:

voi foo(char value);

así que ...

void foo(char buf[])

Es una declaración que dice lo que la notación que desea utilizar. ([] - parte), y también contiene algunos datos de puntero a

Además ... ¿qué se puede esperar ... que envió a la función foo un nombre de array

foo(buf);

que es equivalente a y buf [0]. Así que ... esto es un puntero.

matrices en C no se pasan por valor. Ni siquiera son parámetros de la función legítimos. En su lugar, el compilador ve que usted está tratando de pasar una matriz y degrada al puntero. Lo hace en silencio, ya que el mal mismo. También le gusta cachorros de patada.

El uso de matrices de parámetros de la función es una buena manera de señal a sus usuarios de la API de que esto debe ser un bloque de memoria segmentada en n bytes de tamaño trozos, pero no espere a los compiladores importa si se escribe char *foo char foo[] o char foo[12] en parámetros de función. No lo harán.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top