Ir ao conteúdo
  • Cadastre-se

C Tamanho de uma struct


alecounter

Posts recomendados

Oi pessoal tudo bem? seguinte, criei a seguinte estrutura:

typedef struct {
    int numero1;
    float numero2;
    char letra;
} DADOS;

Eu esperava que essa estrutura tivesse tamanho igual a 7 bytes (int = 2 bytes, float = 4 bytes, char 1 byte) porém quando mando imprimir sizeof(DADOS) a saída é 12! alguém saberia me explicar o por quê?

Link para o comentário
Compartilhar em outros sites

agora, AnsiC disse:

Bem, provavelmente está promovendo o inteiro char para int

então vou criar uma estrutura só de char's para ver se isso realmente está acontecendo, um momento

adicionado 1 minuto depois

criei aqui e está dando 3 bytes(criei uma estrutura com 3 char).

adicionado 2 minutos depois

engraçado que quando crio apenas uma estrutura com 1 char , o "peso" é 1B. agora se coloco um int na estrutura, passa a "pesar" 8B. porque isso?

Link para o comentário
Compartilhar em outros sites

3 minutos atrás, alecounter disse:

então vou criar uma estrutura só de char's para ver se isso realmente está acontecendo, um momento

Essa promoção pode apenas ocorrer se houver um ou mais itens do tipo int, junto com número cuja a divisão por 4 de resto do tipo char.

adicionado 1 minuto depois

Exemplo:

typedef struct {
        char letra1;
        int letra0;
} Dados;

O resultado vai ser 8.

  • Curtir 1
Link para o comentário
Compartilhar em outros sites

5 minutos atrás, AnsiC disse:

Essa promoção pode apenas ocorrer se houver um ou mais itens do tipo int, junto com número cuja a divisão por 4 de resto do tipo char.

adicionado 1 minuto depois

Exemplo:


typedef struct {
        char letra1;
        int letra0;
} Dados;

O resultado vai ser 8.

por qual motivo isso acontece? e uma curiosidade, onde voce aprendeu C?

Link para o comentário
Compartilhar em outros sites

5 minutos atrás, AnsiC disse:

Isso ocorre para otimizar o acesso a memória, e mais fácil calcular o tamanho do bloco de dados quando esse da salto de 1 em 1 ou de 2 em 2, ou de 4 em 4.

adicionado 1 minuto depois

No curso de Física

acho que entendi, mas você aprendeu C no curso ou aprendeu usando algum livro? porque você sempre fala de regras, e no livro que estou usando não estou vendo nada disso

Link para o comentário
Compartilhar em outros sites

2 minutos atrás, alecounter disse:

acho que entendi, mas você aprendeu C no curso ou aprendeu usando algum livro? porque você sempre fala de regras, e no livro que estou usando não estou vendo nada disso

Essas coisas existem apenas em livros velhos do tempo do ANSI C que você encontra nas bibliotecas ou em artigos na internet. Meu caso foi na biblioteca mesmo, a maioria é inglês.

 

Você pode pesquisar esses assunto, porém os melhores resultados vem de postes internacionais. Experientemente pesquisar: size of struct in C, ou sizeof dispensed more size struct

 

Coisas assim vai lhe ajudar nas dúvidas, e se não nos conte que nós ajudaremos.

adicionado 2 minutos depois

Lembrei de um: A Bíblia do C\C++ - ótimo livro.

adicionado 3 minutos depois

Esse foi traduzido, acho que você pode encontra na internet em pdf!

  • Curtir 1
Link para o comentário
Compartilhar em outros sites

Primeiro, vários dos tipos básicos do C tem um tamanho mínimo necessário, mas o tamanho real depende da implementação do compilador e do sistema onde está sendo usado.

 

Então, a norma define que o tipo int deve ter pelo menos 2 bytes de comprimento, mas na prática costuma ser implementado com 4 bytes em compiladores para computadores (mas um compilador para um sistema embarcado por exemplo poderia usar int com 2 bytes).

 

Para saber qual o tamanho de cada tipo cuja norma só define um tamanho mínimo basta testar cada um com sizeof no seu compilador, ou pesquisar na internet.

 

Então teoricamente sua struct teria 4 + 4 + 1 = 9 bytes.

 

 

Mas acontece que num sistema de 32 bits memória é dividida em blocos de 32 bits ou 4 bytes, então a memória é alocada em múltiplos de 4 bytes.

 

Então, sua struct precisa alocar 4 bytes para o int, 4 bytes para o float, e 4 bytes para o char (apesar do tipo char ter tamanho 1 byte), totalizando 12 bytes para a struct inteira.

 

Do último byte alocado apenas 1 byte será utilizado de fato, para armazenar o valor do tipo char, os outros 3 bytes não são utilizados. Mas note que poderia adicionar outras variáveis char, ou até uma variável short int, no fim da struct, e essas variáveis ocupariam e usariam esses bytes que foram alocados mas não foram utilizados, e o tamanho total da struct ficaria inalterado.

 

Isso também implica que a ordem dos itens na struct é importante, pois uma struct mal organizada pode aumentar muito o espaço ocupado pela struct.

 

Por exemplo:

//Essa struct mal organizada ocupa 16 bytes:
struct est{
    int a;
    char b;
    int c;
    short int d;
}

//Mas essa ocupa apenas 12 bytes:
struct est2{
    int a;
    int c;
    char b;
    short int d;
}

O problema na primeira struct é que 4 bytes são alocados para o char b, mas esse só usa 1 dos 4 bytes, e sobram 3 bytes, mas o int c ocupará 4 bytes, então não cabe nos 3 bytes que sobraram na alocação do char c, logo precisa ser alocado um novo grupo de 4 bytes para guardar o int c, e os 3 bytes não utilizados são desperdiçados.

 

Já na segunda struct o char b (1 byte) e o short int d (2 bytes) cabem juntos dentro de apenas 1 grupo de 4 bytes que foi alocado, ocupando 3 bytes, e apenas 1 byte fica sobrando não utilizado.

  • Curtir 2
  • Obrigado 1
Link para o comentário
Compartilhar em outros sites

4 minutos atrás, isrnick disse:

Mas acontece que num sistema de 32 bits memória é dividida em blocos de 32 bits ou 4 bytes, então a memória é alocada em múltiplos de 4 bytes.

Discordo!

typedef struct {
        char letra1;
        char letra2;
        char letra3;
} Dados;

Se testar para esse estrutura a resposta vai ser: 3 bytes, e não 4.

adicionado 2 minutos depois

O que implica a promoção é a presença de um tipo de 4 bytes.

adicionado 4 minutos depois

Não importa se ele está em cima, ou embaixo, ou no meio. Trata-se de uma otimização.

adicionado 6 minutos depois
13 minutos atrás, isrnick disse:

Isso também implica que a ordem dos itens na struct é importante, pois uma struct mal organizada pode aumentar muito o espaço ocupado pela struct.

Concordo!

  • Curtir 2
  • Obrigado 1
Link para o comentário
Compartilhar em outros sites

resumindo...

Ao ter:

typedef struct {
    int numero1;
    float numero2;
    char letra;
} DADOS;

 

você pensa que tem isso:

+-------+-------+-------+-------+
|            numero1            |
+-------+-------+-------+-------+
|            numero2            |
+-------+-------+-------+-------+
| letra |
+-------+


mas na verdade você tem isso:

+-------+-------+-------+-------+
|            numero1            |
+-------+-------+-------+-------+
|            numero2            |
+-------+-------+-------+-------+
|             letra             |
+-------+-------+-------+-------+

pois o compilador fez um preenchimento(padding) e alinhou letra para que tenha o mesmo tamanho das outras variáveis, pois é mais fácil para o sistema "mastigar" 4 bytes, ou 32 bits, neste caso, que 4 bytes é o " tamanho da palavra do sistema", isso se chama Byte Aligne ou o que é o mesmo, alinhamento de bytes.

 

Isso tudo depende de uma série de fatores que você precisa entender para saber prever o preenchimento de bytes.
 

adicionado 1 minuto depois

De uma olhada aqui: https://www.youtube.com/watch?v=COGGLrAJJGU

 

E aqui: https://www.youtube.com/watch?v=SXu965b82Gk

 

  • Curtir 4
Link para o comentário
Compartilhar em outros sites

é... onde você tem o '?' é o preenchimento.

adicionado 6 minutos depois

Por isso se chama alinhar os bytes >_<

Existe uma forma de se desconectar o alinhamento, sobre tudo é recomendado quando os dados vão ser enviados para um arquivo, neste caso vira festa usar vários tipos de compiladores e com diferentes palavras. você pode levar um arquivo que foi usada um alinhamento diferentes para outro programa ler e dar tudo errado hahaha:atirador:

  • Curtir 2
Link para o comentário
Compartilhar em outros sites

A parte que tem a interrogação, ainda sim é acessível (leitura e gravação).

#include <stdio.h>  /*  ~incluir: printf */
#include <limits.h>  /* ~incluir: INT_MAX */
#define str(val)  #val
struct sttnumero {
          char caractere;
          int inteiro;
};

/** funcao main ~ principal do programa  */
int main (void){
  struct sttnumero me = {0, INT_MAX};
    * (int *) & me.caractere = INT_MAX;
    printf ("SizeOf %s: %u\n", str (me), sizeof me);
    printf ("Inteiro %s: %d\n", str (me.caractere), * (int *) & me.caractere);
    printf ("Inteiro %s: %d\n\n", str (me.inteiro), me.inteiro);
    
    printf ("Point %s: %u\n", str (me), & me);
    printf ("Point %s: %u\n", str (me.caractere), & me.caractere);
    printf ("Point %s: %u\n", str (me.inteiro), & me.inteiro);
  return 0;
}

Ps.: Bem previsível! 

adicionado 8 minutos depois

Ou seja com conhecimento em ponteiro, e melhor declarar essa estrutura assim:

struct sttnumero {
          char caractere;
          char inteiro[sizeof (int)];
};

E não se perderá memória!

adicionado 16 minutos depois

Dúvidas, ou sugestões?

  • Curtir 2
  • Obrigado 1
Link para o comentário
Compartilhar em outros sites

Só adicionei no código do @AnsiC para imprimir cada byte separadamente em hexadecimal:

 

#include <stdio.h>  /*  ~incluir: printf */
#include <limits.h>  /* ~incluir: INT_MAX */
#define str(val)  #val
struct sttnumero {
          char caractere;
          int inteiro;
};

/** funcao main ~ principal do programa  */
int main (void){
  struct sttnumero me = {0, INT_MAX};
    * (int *) & me.caractere = 0x04030201;
    printf ("SizeOf %s: %u\n", str (me), sizeof me);
    printf ("Inteiro %s: %d\n", str (me.caractere), * (int *) & me.caractere);
    printf ("Inteiro %s: %d\n", str (me.inteiro), me.inteiro);
    for(int i = 0; i < 4; i++){
        printf ("Char %d: 0x%02hhx\n", i, *(&me.caractere + i) );
    }
    
    printf ("\nPoint %s: %u\n", str (me), &me);
    printf ("Point %s: %u\n", str (me.caractere), &me.caractere);
    printf ("Point %s: %u\n", str (me.inteiro), &me.inteiro);
  return 0;
}

 

  • Curtir 2
  • Obrigado 1
Link para o comentário
Compartilhar em outros sites

Crie uma conta ou entre para comentar

Você precisa ser um usuário para fazer um comentário

Criar uma conta

Crie uma nova conta em nossa comunidade. É fácil!

Crie uma nova conta

Entrar

Já tem uma conta? Faça o login.

Entrar agora

Sobre o Clube do Hardware

No ar desde 1996, o Clube do Hardware é uma das maiores, mais antigas e mais respeitadas comunidades sobre tecnologia do Brasil. Leia mais

Direitos autorais

Não permitimos a cópia ou reprodução do conteúdo do nosso site, fórum, newsletters e redes sociais, mesmo citando-se a fonte. Leia mais

×
×
  • Criar novo...

 

GRÁTIS: ebook Redes Wi-Fi – 2ª Edição

EBOOK GRÁTIS!

CLIQUE AQUI E BAIXE AGORA MESMO!