Não conseguimos carregar os anúncios.Se usa bloqueador, considere liberar o Viva o Linux para nos patrocinar.
2. Re: offsetof()
EnzoFerberusa FreeBSD
Post recolhido
Enviado em 14/11/2016 - 08:09h
Olá,
O problema que você encontrou chama-se alinhamento de memória.
O processador lê dados da memória em "pacotes", normalmente de 32bits ou 64bits (dependendo da sua arquitetura).
Isso acontece pois o processador tem que ler os dados da memória e armazena-los em um registrador, pois um CPU só pode realizar operações em dados nos registradores.
Os compiladores C normalmente alinham os dados de variáveis e estruturas para refletir isso, de forma que quando você acessar os dados, nenhuma operação de shift seja necessaria para manipular os dados.
No GCC existe um atributo chamado packed que possiblita compactar a estrutura, e você verá exatamente o que estava esperando:
"(...)all right-thinking people know that (a) K&R are _right_ and (b) K&R are right."
- linux/Documentation/CodingStyle - TORVALDS, Linus.
3. Re: offsetof()
paulo1205usa Ubuntu
Post recolhido
Enviado em 14/11/2016 - 13:34h
Como o Enzo disse, tudo tem a ver com a arquitetura particular que você estiver usando.
Algumas arquiteturas obrigam todos os acessos em memória a estarem alinhados com o tamanho da palavra do processador (e.g. numa máquina com palavras de 32 bits, ou 4 bytes, todos os dados, independentemente de seus tamanhos individuais, devem estar dispostos em endereços que sejam múltiplos de 4 bytes). Outras permitem dispor dados de diferentes tamanhos em endereços que sejam múltiplos do tamanho daquele dado. Outras ainda permitem que qualquer dado possa estar em qualquer endereço, mas podem ter desempenho degradado se os dados estiverem com alinhamento diferente do esperado.
Nossos PCs até permitem o uso de dados desalinhados, com possível degradação de desempenho. No entanto, os compiladores de linguagens de alto nível preferem evitar o desempenho degradado, e para tanto forçam um realinhamento dos dados. Esse realinhamento é particularmente mais visível quando você colocar diversos membros de tamanhos diferentes dentro de uma estrutura.
A julgar pelos números que você apresentou, você deve estar usando uma arquitetura de 64 bits. Em arquiteturas assim, dados de até oito bytes podem ser lidos ou escritos em memória com uma única operação, desde que estejam devidamente alinhados num endereço que seja múltiplo de oito bytes. Se você os dispuser de outra forma, uma operação de leitura de 64 bits teria de ser feita em duas ou mais etapas (por exemplo: duas operações de 32 bits).
Uma dica para trabalhar com estruturas, de modo a não precisar de atributos como packed (até porque esses atributos podem não ser portáveis entre diferentes compiladores) nem desperdiçar muita memória com padding, é procurar dispor os membros da estrutura numa ordem que vá do maior para o menor.
Veja o seguinte exemplo:
#include <stddef.h>
#include <stdio.h>
struct dic { double d; int i; char c; };
struct dci { double d; char c; int i; };
struct idc { int i; double d; char c; };
struct icd { int i; char c; double d; };
struct cdi { char c; double d; int i; };
struct cid { char c; int i; double d; };
#define PRINT_INFO(x, a, b, c) \
printf( \
"sizeof(" #x ")=%zd\n" \
"\toffset of " #a ": %zd\n" \
"\toffset of " #b ": %zd\n" \
"\toffset of " #c ": %zd\n", \
sizeof(x), offsetof(x, a), offsetof(x, b), offsetof(x, c) \
)
int main(void){
printf(
"sizeof(char)=%zd; sizeof(int)=%zd; sizeof(double)=%zd\n",
sizeof(char), sizeof(int), sizeof(double)
);
PRINT_INFO(struct dic, d, i, c);
PRINT_INFO(struct dci, d, c, i);
PRINT_INFO(struct idc, i, d, c);
PRINT_INFO(struct icd, i, c, d);
PRINT_INFO(struct cdi, c, d, i);
PRINT_INFO(struct cid, c, i, d);
}
Compilando-o e rodando numa máquina de 64 bits (com opções default na compilação), eis a saída.
sizeof(char)=1; sizeof(int)=4; sizeof(double)=8
sizeof(struct dic)=16
offset of d: 0
offset of i: 8
offset of c: 12
sizeof(struct dci)=16
offset of d: 0
offset of c: 8
offset of i: 12
sizeof(struct idc)=24
offset of i: 0
offset of d: 8
offset of c: 16
sizeof(struct icd)=16
offset of i: 0
offset of c: 4
offset of d: 8
sizeof(struct cdi)=24
offset of c: 0
offset of d: 8
offset of i: 16
sizeof(struct cid)=16
offset of c: 0
offset of i: 4
offset of d: 8
A título de comparação, veja o que acontece quando eu compilo e rodo o mesmo programa em modo de 32 bits.
sizeof(char)=1; sizeof(int)=4; sizeof(double)=8
sizeof(struct dic)=16
offset of d: 0
offset of i: 8
offset of c: 12
sizeof(struct dci)=16
offset of d: 0
offset of c: 8
offset of i: 12
sizeof(struct idc)=16
offset of i: 0
offset of d: 4
offset of c: 12
sizeof(struct icd)=16
offset of i: 0
offset of c: 4
offset of d: 8
sizeof(struct cdi)=16
offset of c: 0
offset of d: 4
offset of i: 12
sizeof(struct cid)=16
offset of c: 0
offset of i: 4
offset of d: 8