c - pagina - meta keywords ejemplos
¿Qué tienen de especial las estructuras? (4)
Sé que en C no podemos devolver una matriz de una función, sino un puntero a una matriz.
Pero quiero saber qué es lo especial de las
structs
que los hace
structs
por funciones, aunque puedan contener matrices.
¿Por qué la
struct
envoltura hace que el siguiente programa sea válido?
#include <stdio.h>
struct data {
char buf[256];
};
struct data Foo(const char *buf);
int main(void)
{
struct data obj;
obj = Foo("This is a sentence.");
printf("%s/n", obj.buf);
return 0;
}
struct data Foo(const char *buf)
{
struct data X;
strcpy(X.buf, buf);
return X;
}
En primer lugar, para citar
C11
, capítulo §6.8.6.4, declaración de
return
, (
énfasis mío
)
Si se ejecuta una declaración de
return
con una expresión, el valor de la expresión se devuelve al llamante como el valor de la expresión de llamada de función.
Es posible devolver una variable de estructura (y correcta) porque se devuelve el
valor de
la estructura.
Esto es similar a devolver cualquier tipo de datos primitivos (devolviendo
int
, por ejemplo).
Por otro lado, si devuelve una
matriz
, al usar
return <array_name>
, esencialmente devuelve la
dirección del primer elemento
de la matriz
NOTA
, que se invalida en la persona que llama si la matriz era local para las funciones llamadas.
Por lo tanto, no es posible devolver la matriz de esa manera.
Entonces,
TL; DR
, no hay nada
especial
con las
struct
, la especialidad está en las
matrices
.
NOTA:
Citando de nuevo
C11
, capítulo §6.3.2.1, (
mi énfasis
)
Excepto cuando es el operando del operador
sizeof
, el operador_Alignof
, o el operador unario&
, o es un literal de cadena utilizado para inicializar una matriz, una expresión que tiene el tipo '''' matriz de tipo '''' se convierte en una expresión con escriba '''' puntero para escribir '''' que apunta al elemento inicial del objeto de matriz y no es un valor l. [...]
Las estructuras tienen miembros de datos públicos de forma predeterminada, por lo que es posible en caso de estructura acceder a los datos en main pero no en el caso de la clase. Entonces, la envoltura de estructura es válida.
No hay nada especial sobre los tipos de
struct
;
Es que hay algo especial sobre los tipos de
matriz
que impide que sean devueltos directamente desde una función.
Una expresión de
struct
se trata como una expresión de cualquier otro tipo que no sea de matriz;
evalúa el
valor
de la
struct
.
Entonces puedes hacer cosas como
struct foo { ... };
struct foo func( void )
{
struct foo someFoo;
...
return someFoo;
}
La expresión
someFoo
evalúa el
valor
del objeto
struct foo
;
el contenido del objeto se devuelve desde la función (incluso si ese contenido contiene matrices).
Una expresión de matriz se trata de manera diferente;
si no es el operando de
sizeof
o unary
&
operadores, o si no se utiliza un literal de cadena para inicializar otra matriz en una declaración, la expresión se convierte ("decae") del tipo "matriz de
T
" a " puntero a
T
", y el valor de la expresión es la dirección del primer elemento.
Por lo tanto, no puede devolver una matriz por valor de una función, porque cualquier referencia a una expresión de matriz se convierte automáticamente en un valor de puntero.
Una mejor manera de hacer la misma pregunta sería "qué tienen de especial las matrices", ya que son las matrices las que tienen un manejo especial asociado, no las
struct
.
El comportamiento de pasar y devolver matrices por puntero se remonta a la implementación original de C. Las matrices "decaen" a los punteros, causando una gran confusión, especialmente entre las personas nuevas en el lenguaje.
Las estructuras, por otro lado, se comportan como los tipos integrados, como
int
s,
double
s, etc. Esto incluye cualquier matriz incrustada en la
struct
, excepto los
miembros de matriz flexible
, que no se copian.