Os membros da class / struct sempre são criados na memory na ordem em que foram declarados?

Esta é uma pergunta que foi provocada pela resposta de Rob Walker aqui .

Suponha que eu declare uma class / struct assim:

struct { char A; int B; char C; int D; }; 

É seguro assumir que esses membros serão declarados exatamente nessa ordem na memory, ou isso é uma coisa dependente do compilador? Estou perguntando porque sempre achei que o compilador pode fazer o que quiser com eles.

Isso leva à minha próxima pergunta. Se o exemplo acima causar problemas de alinhamento de memory, por que o compilador não pode transformar isso em algo assim implicitamente:

 struct { char A; char C; int B; int D; }; 

(Eu estou principalmente perguntando sobre C ++, mas eu estaria interessado em ouvir a resposta C também)

tópicos relacionados

  • Por que o GCC não otimiza as estruturas?

C99 §6.7.2.1 cláusula 13 declara:

Dentro de um object de estrutura, os membros de campo não-bit e as unidades nas quais residem os campos de bits têm endereços que aumentam na ordem em que são declarados.

e continua falando um pouco mais sobre preenchimento e endereços. A seção equivalente C89 é §6.5.2.1.

C ++ é um pouco mais complicado. Nos padrões de 1998 e 2003, há §9.2 cláusula 12 (cláusula 15 em C + + 11):

Os membros de dados não estáticos de uma class (não-união) declarada sem um especificador de access interveniente são alocados para que os membros posteriores tenham endereços mais altos dentro de um object de class. A ordem de alocação de membros de dados não estáticos separados por um especificador de access não é especificada (11.1). Os requisitos de alinhamento de implementação podem fazer com que dois membros adjacentes não sejam alocados imediatamente após o outro; Portanto, talvez requisitos para espaço para gerenciamento de funções virtuais (10.3) e classs base virtuais (10.1).

Os membros de dados são organizados na ordem declarada. O compilador é livre para intercalar o preenchimento para organizar o alinhamento de memory que ele gosta (e você verá que muitos compiladores têm um boatload de opções de especificação de alinhamento – útil se misturar bits compilados por programas diferentes).

Veja também Por que o GCC não otimiza as estruturas? .


Parece que esta resposta é um pouco obsoleta para C ++. Você aprende algo todo dia. Obrigado aib, Nemanja.

Basicamente, você pode contar com isso apenas para as classs com layout padrão . Estritamente falando, layout padrão é uma coisa C ++ 0x, mas é realmente apenas padronizar a prática existente /

Eu não posso falar em C ++, mas em C a ordem é garantida como sendo a mesma ordem na memory como declarada na estrutura.

Além do preenchimento para alinhamento, nenhuma otimização de estrutura é permitida por qualquer compilador (que eu saiba) para C ou C ++. Eu não posso falar em classs C ++, pois elas podem ser outra besta completamente.

Considere que seu programa está interagindo com o código do sistema / biblioteca no Windows, mas você deseja usar o GCC. Você teria que verificar se o GCC usava um algoritmo de otimização de layout idêntico para que todas as suas estruturas fossem agrupadas corretamente antes de enviá-las para o código compilado pelo MS.

Enquanto navegava pelos tópicos relacionados à direita, olhei para essa questão . Eu acho que isso pode ser um caso interessante quando se pensa sobre essas questões (a menos que seja mais comum do que eu imagino).

Parafraseando, se você tem uma estrutura em C que se parece com isso:

 struct foo{}; 

e subclass-o assim em C ++ (usando uma unidade de compilation separada):

 extern "C" foo; struct bar: public foo{}; 

Então o alinhamento da memory não será necessariamente o mesmo pelas razões que o aib menciona (mesmo entre os compiladores do mesmo fornecedor).