2011-10-11 19 views
7

He leído que si se declara dos estructuras de esta manera:¿Este código está garantizado por el estándar C?

struct Node { 
    int a, b, c; 
}; 

struct DerivedNode { 
    struct Node base; 
    int d, e, f; 
}; 

continuación, puede utilizar punteros a ellos de esta manera:

struct DerivedNode myDerivedNode; 
struct Node *regularNode = (struct Node *) &myDerivedNode; 

regularNode->a = 3; 

En otras palabras, los desplazamientos de dirección para a, b, c son los mismos dentro de struct Node y struct DerivedNode. Para que pueda obtener un tipo de polimorfismo, donde puede pasar por la fuerza (struct Node *) -cast DerivedNode puntero siempre que un puntero de nodo normalmente se tomaría.

Mi pregunta es si este comportamiento es garantizado. Sé que hay algunos problemas de alineación de memoria extraños y que el compilador a veces reordena los campos para lograr un mejor empaque en la memoria. ¿Encontrará el campo base en algún lugar excepto el comienzo de struct DerivedNode?

+0

Olvidó la palabra clave 'struct' en varios lugares, ¿no? –

+0

@Jens Oh sí, probablemente. Lo siento –

Respuesta

13

Se garantiza que funciona de manera estándar. Miembros en estructuras se nos extienden secuencialmente en el orden que especifique y el primer miembro siempre aparece en el offset 0.

extractos pertinentes de la norma ANSI C:

una estructura es que consiste en un tipo de una secuencia de miembros, cuyo almacenamiento se asigna en una secuencia ordenada.

Esto indica que los miembros se disponen secuencialmente.

Puede haber un relleno sin nombre dentro de un objeto de estructura, pero no al principio.

los medios que el primer elemento se coloca en el desplazamiento 0.

Nota: extractos estándar tomados de la sección 6.7.2.1 de la norma ISO/IEC 9899: TC3 de septiembre de 2007 Proyecto.

3

Como dice David esto está garantizado siempre y cuando base permanezca como el primer elemento en DerivedNode.

Pero generalmente esto es una mala práctica. No puedo averiguar mucho circunstancias en las que no se puede decir

struct Node *regularNode = &myDerivNode.base; 

de error que es mucho más claro y menos propenso en caso de que modificar sus estructuras más adelante.

+0

+1 Estoy totalmente de acuerdo con esto. –

+0

La circunstancia es que estoy en una clase de estructuras de datos en la que estoy atrapado en 1975 fastidiándome con una sola bifurcación (espere ...) búsqueda binaria. :PAG –

1

Esto no responderá a su pregunta, pero alguien que se preocupe por escribir el estándar ANSI (ISO) C podría compilar su código con gcc -pedantic o -pedantic-errors. Esas opciones deberían aumentar la compilación de advertencias/errores en líneas de código no estándar.

Tenga en cuenta que esto no es 100% eficaz, desde man gcc:

[-pedantic] encuentra algunas prácticas no ISO, pero no todos --- solo aquellos de los que ISO C requiere una diagnóstico, y algunos otros para los que se han agregado diagnósticos .

Cuestiones relacionadas