Ir ao conteúdo
  • Comunicados

    • Gabriel Torres

      Seja um moderador do Clube do Hardware!   12-02-2016

      Prezados membros do Clube do Hardware, Está aberto o processo de seleção de novos moderadores para diversos setores ou áreas do Clube do Hardware. Os requisitos são:   Pelo menos 500 posts e um ano de cadastro; Boa frequência de participação; Ser respeitoso, cordial e educado com os demais membros; Ter bom nível de português; Ter razoável conhecimento da área em que pretende atuar; Saber trabalhar em equipe (com os moderadores, coordenadores e administradores).   Os interessados deverão enviar uma mensagem privada para o usuário @Equipe Clube do Hardware com o título "Candidato a moderador". A mensagem deverá conter respostas às perguntas abaixo:   Qual o seu nome completo? Qual sua data de nascimento? Qual sua formação/profissão? Já atuou como moderador em algo outro fórum, se sim, qual? De forma sucinta, explique o porquê de querer ser moderador do fórum e conte-nos um pouco sobre você.   OBS: Não se trata de função remunerada. Todos que fazem parte do staff são voluntários.
    • DiF

      Poste seus códigos corretamente!   21-05-2016

      Prezados membros do Fórum do Clube do Hardware, O Fórum oferece um recurso chamado CODE, onde o ícone no painel do editor é  <>     O uso deste recurso é  imprescindível para uma melhor leitura, manter a organização, diferenciar de texto comum e principalmente evitar que os compiladores e IDEs acusem erro ao colar um código copiado daqui. Portanto convido-lhes para ler as instruções de como usar este recurso CODE neste tópico:  
alecounter

C Tamanho de uma struct

Recommended Posts

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ê?

Compartilhar este post


Link para o post
Compartilhar em outros sites

Para Windows 32bits essa estrutura tem: 9 bytes.

char: 1 byte

int: 4 bytes

float: 4 bytes

  • Curtir 1

Compartilhar este post


Link para o post
Compartilhar em outros sites
2 minutos atrás, AnsiC disse:

Para Windows 32bits essa estrutura tem: 9 bytes.

char: 1 byte

int: 4 bytes

float: 4 bytes

to usando win64 aqui... quanto deveria dar?

Compartilhar este post


Link para o post
Compartilhar em outros sites
15 minutos atrás, alecounter disse:

to usando win64 aqui... quanto deveria dar

Por padrão gcc compila em 32 bits independente do Windows 64, qual nome do seu compilador?

Editado por AnsiC
  • Curtir 1

Compartilhar este post


Link para o post
Compartilhar em outros sites
agora, AnsiC disse:

Por padrão gcc compila em 32 bits independente do Windows, qual nome do seu compilador?

é o gcc mesmo. mas você disse que a soma deu 9B, mas quando eu faço sizeof(DADOS) a resposta é 12B... o que está consumindo esses 3B?

Compartilhar este post


Link para o post
Compartilhar em outros sites

Ps.: Faça sizeof para cada tipo é constante seus tamanhos individuais.

Editado por AnsiC
  • Curtir 1

Compartilhar este post


Link para o post
Compartilhar em outros sites
2 minutos atrás, AnsiC disse:

Ps.: Faça sizeof para tipo é constante seus tamanhos.

eu fiz aqui...
sizeof(int)=4B
sizeof(float)=4B
sizeof(char)=1B

 

somatório = 9B. mas sizeof(DADOS)=12B != 9B... por que a diferença?

Editado por alecounter

Compartilhar este post


Link para o post
Compartilhar em outros sites

Bem, provavelmente está promovendo o inteiro char para int

  • Curtir 1

Compartilhar este post


Link para o post
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?

Compartilhar este post


Link para o post
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

Compartilhar este post


Link para o post
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?

Compartilhar este post


Link para o post
Compartilhar em outros sites

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
2 minutos atrás, alecounter disse:

onde voce aprendeu C?

No curso de Física

  • Curtir 1

Compartilhar este post


Link para o post
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

Compartilhar este post


Link para o post
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

Compartilhar este post


Link para o post
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.

Editado por isrnick
Erro meu apontado pelo AnsiC
  • Curtir 2
  • Obrigado 1

Compartilhar este post


Link para o post
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

Compartilhar este post


Link para o post
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

 

Editado por vangodp
  • Curtir 4

Compartilhar este post


Link para o post
Compartilhar em outros sites

Ou mais precisamente na verdade tem isso:

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

 

  • Curtir 2

Compartilhar este post


Link para o post
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

Compartilhar este post


Link para o post
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?

Editado por AnsiC
PS
  • Curtir 2
  • Obrigado 1

Compartilhar este post


Link para o post
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

Compartilhar este post


Link para o post
Compartilhar em outros sites

Crie uma conta ou entre para comentar

Você precisar ser um membro para fazer um comentário






Sobre o Clube do Hardware

No ar desde 1996, o Clube do Hardware é uma das maiores, mais antigas e mais respeitadas publicações 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

×