Pasando una estructura a una función en C

Si tengo lo siguiente: –

struct foo { int a; int *b; } bar; void baz(struct foo qux) { } 

¿Estoy en lo cierto al pensar que pasar de bar a baz() da como resultado una copia local de bar se empuja en la stack? Si es así, ¿qué tipo de copia es esta? en C ++, asumo que llamaría al constructor de copia, o al constructor de copia predeterminado, pero realmente no sé cómo funcionaría esto en C.

¿C tiene alguna noción de un constructor de copia predeterminado y esto tiene un nombre? ¿Se podría hacer algo para realizar una copia profunda? (hipotéticamente). La única forma en que podría pensar es en hacer una copia profunda y luego pasarla a la función.

Por lo general, pasaría un puntero a un foo pero tengo curiosidad por saber cómo funciona. Además, tengo la impresión de que pasar un puntero es más rápido, ahorra memoria y es el curso de acción recomendado para realizar este tipo de operación. Supongo que es una copia superficial; ¿Se puede cambiar esto?

¿Estoy en lo cierto al pensar que pasar de barra a baz () da como resultado una copia local de barra que se empuja en la stack?

Sí.

Realmente no sé cómo funcionaría esto en C.

Sustancialmente como lo haría con el constructor de copia predeterminado en C ++; Cada campo de la copia se inicializa con el campo correspondiente del original. Por supuesto, debido a la regla “como si”, todo puede reducirse a un memcpy .

Tengo la impresión de que pasar un puntero es más rápido, ahorra memoria y es el curso de acción recomendado para realizar este tipo de operación.

Para struct más grandes es a menudo el caso, pero no siempre es así; Si tiene una struct pequeña de pocos campos pequeños, la sobrecarga de la copia probablemente será menor que la de la dirección indirecta (también, usar parámetros de puntero puede ser costoso porque las reglas de aliasing de C y C ++ pueden evitar algunas optimizaciones).

Supongo que es una copia superficial; ¿Se puede cambiar esto?

No, una copia superficial (copia a ciegas de cada campo) es lo que sucede con el constructor de copia predeterminado (mientras que con “copia profunda” generalmente significa también crear una copia de cada objeto al que se hace referencia en los campos de puntero / referencia).

Lo que quiere decir es “pasar por referencia”, y no es el valor predeterminado permitir la máxima flexibilidad (y por coherencia con el paso de los tipos primitivos). Si desea pasar por referencia, pasa un puntero (o una referencia en C ++), a menudo const si está solo por el rendimiento, de lo contrario pasa el objeto en sí.

Sí, se empuja una copia local de la barra a la stack. y el rest se comenta en el siguiente ejemplo de trabajo.

  #include  struct foo { int a; int *b; } bar; void baz(struct foo qux) { bar.a = 2; // if its a different copy then printf on main should print 1 not 2. *bar.b = 5; // if its a different copy then printf on main should print 5 not 4. since the place pointer pointing to is same } int main(){ bar.a=1; bar.b = (int*)malloc(sizeof(int)); *bar.b = 4; baz(bar); // pass it to baz(). now the copy of bar in the stack which is what baz going to use printf("a:%d | b:%d\n",bar.a,*bar.b); //answer is 2 and 5 /*So indeed it does a shallow copy thats why we lost the "4" stored in bar.b it did not created new space in heap to store "5" instead it used the same space that b was pointing to. */ return 0; }