estructura - punteros c++
¿Está arrojando un puntero a diferentes estructuras garantizadas para ser significativas en C89? (2)
C89 permite la conversión, por conversión, de un puntero a un tipo de objeto a un puntero a un tipo de objeto diferente.
Sin embargo, antes de llegar a la desreferenciación, se garantiza que el puntero convertido será válido solo si el tipo al que se hace referencia del puntero original ha requerido una alineación al menos tan estricta como la del tipo al que hace referencia el puntero de resultado. La alineación es completamente dependiente de la implementación. En su ejemplo particular, es probable, pero no está garantizado , que los dos tipos de struct
tengan el mismo requisito de alineación.
Suponiendo que la conversión produzca un puntero válido, el estándar no define con precisión cómo se struct
miembros de la struct
dentro de la representación de un objeto struct
. Los miembros deben aparecer en el mismo orden que en la definición de struct
, y no debe haber ningún relleno antes del primero, pero no se definen otros detalles. En su ejemplo, por lo tanto, se garantiza que X->x
corresponderá a Y->a
(suponiendo, de nuevo, que el puntero convertido es válido en primer lugar), pero indefinido si X->y
corresponderá a Y->b
.
Tengo dos estructuras como
struct X {
int x;
double *y;
};
struct Y {
int a;
double *b;
char c;
};
¿Está arrojando un puntero a struct Y
a un puntero a struct X
garantizado para comportarse de manera consistente de una manera razonable (es decir, x->x
x->y
corresponden a y->a
y y->b
respectivamente) según el estándar C89? Menos importante, pero sería genial si también lo sabe, esto también es válido para estándares posteriores (por ejemplo, C11) y otros lenguajes que tienen una superposición sintáctica y semántica significativa con C (por ejemplo, C ++ XX, Objective-C )?
Es un comportamiento indefinido. Python confió en esto antes y tuvo que arreglar eso. Si tiene struct Y
include struct X
como su primer elemento, puede usarlo para un efecto similar:
struct Y {
struct X a;
char c;
};
struct Y y;
struct X *x = (struct X *) &y; /* legal! */
También hay un caso especial para los sindicatos:
struct X {
int x;
double *y;
};
struct Y {
int a;
double *b;
char c;
};
union XY {
struct X x;
struct Y y;
};
union XY xy;
xy.x.x = 0;
printf("%d/n", xy.y.a); /* legal! */
En versiones posteriores del estándar C, el compilador solo necesita manipular objetos X
e Y
alias entre sí si una definición de unión como esta está realmente dentro del alcance, pero en C89, tiene que suponer que dicha definición existe en alguna parte. Sin embargo, eso todavía no hace seguro lanzar una struct Y *
a una struct X *
; si el compilador sabe que una struct Y
específica no es parte de una unión, aún puede suponer que una struct X *
posiblemente no pueda alias.