Pergunta

Eu estou trabalhando em turbo C em janelas onde Char toma um byte.Now meu problema é com o abaixo União.

union a
{
 unsigned char c:2;
}b;
void main()
{
printf("%d",sizeof(b));  \\or even sizeof(union a)
}

Este programa é imprimir saída como 2 onde, como a união deve ser tomada apenas 1 byte. Por que é tão?

para struct é bom dar 1 byte mas esta união está trabalhando de forma inadequada.

E mais coisa como acessar esses campos de bits.

scanf("%d",&b.c);  //even scanf("%x",b.c);

não está funcionando porque não podemos ter endereço para bits.So temos que usar outra variável como abaixo

int x;
scanf("%d",&x);
b.c=x;

Cant que nós evitá-lo ?? existe alguma outra maneira ???

Foi útil?

Solução

Turbo C é baseado em microprocessador 8086 que tem duas palavras byte fronteira . A leitura atômica e escrita é tipicamente ligada à arquitetura da CPU, para que o compilador está adicionando alguma folga bytes para alinhar sua estrutura de dados.

text alt

Chamando #pragma pack(1) pode ser capaz de desativá-lo, mas não tenho certeza se ele funciona em Turbo C.

Outras dicas

Os compiladores estão autorizados a adicionar preenchimento de estruturas e sindicatos e ao mesmo tempo, eu admito, que é um pouco surpreendente que o seu faz rodada até a união com um tamanho de dois bytes quando você é capaz de obter um struct um byte é perfeitamente permitido .

Em resposta à sua segunda pergunta: não, não é evitável. campos de bits são uma otimização struct embalagem e o desempenho e conveniência pena de pagar é que os membros do campo de bits não são individualmente endereçável.

Eu não tenho certeza onde você encontra a exigência de que a união deve ser exatamente o tamanho mínimo. Um objeto deve ser pelo menos tão grande quanto seus membros, mas que é um limite inferior somente.

Você não pode obter o endereço de um campo de bits; o que seria o seu tipo? Não pode ser int *. scanf (% d) vai escrever sizeof (int) * pedaços CHAR_BIT à int * você passar. Isso é escrever mais de 2 bits, mas você não tem esse espaço.

Há um parágrafo na norma que afirma não haverá preenchimento antes do primeiro membro de um struct. Mas ela não diz explicitamente por isso cerca de sindicatos. A diferença no tamanho poderia vir porque quer alinhar a união em 2 limites de byte, mas como ele não pode pad antes do primeiro membro de um struct, a estrutura terá um alinhamento byte. Observe também que uma união poderia ter mais membros com diferentes tipos, o que poderia ampliar o alinhamento necessário de sua união. Pode haver razões para o compilador a dar-lhes pelo menos dois bytes de alinhamento, por exemplo, para aliviar código que tem de lidar de acordo com o alinhamento necessário de uma união.

De qualquer forma, não há nenhuma exigência de que sua união deve ser um byte exatamente. Ele só tem que ter lugar para todos os seus membros.

Aqui está o que o padrão C tem a dizer sobre sua segunda pergunta:

The operand of the unary & operator shall be either a function designator or an lvalue that designates an object that is not a bit-field and is not declared with the register storage-class specifier.

Então, sua melhor aposta é usar seu caminho usando o int. você pode colocar as cintas em torno do código, de modo que a variável temporária é mantido locais:

void func(void) { struct bits f; { int x; scanf("%d", &x); f.bitfield = x; } /* ... */ }

Há muita desinformação nas respostas por isso vou esclarecer. Poderia ser para um dos 2 motivos (eu não estou familiarizado com o compilador).

  1. A unidade de armazenamento de campo de bits é 2.

  2. O alinhamento é forçado a palavra (2 byte) limite.

Eu duvido que é o primeiro caso, uma vez que é uma extensão comum para levar a unidade de armazenamento bitfield como o tamanho do tipo de "base", declarou. Neste caso o tipo é char que sempre tem um tamanho de 1.

[No padrão que você só pode declarar bitfields do tipo int ou int sem sinal ea "unidade de armazenamento", no qual bitfields são agrupados é fixo (geralmente o mesmo tamanho de um int). Mesmo um único bit bitfield vai usar uma unidade de armazenamento.]

No segundo caso, é comum para compiladores C para implementar #pragma pack para permitir o controlo de alinhamento. Eu suspeito que a embalagem padrão é 2, caso em que um byte de bloco será adicionado no final da união. A maneira de evitar isso é usar:

#pragma pack(1)

Você também deve usar #pragma pack() depois para trás set para o padrão (ou melhor ainda usar o push e pop argumentos se suportado pelo seu compilador).

Para todos os repliers que disseram que você deve colocar-se com o que o compilador faz, isto é contrário ao espírito do C. Você deve ser capaz de usar bitfields para mapear para qualquer tamanho ou bit de ordem em situações onde você não tem controle sobre ele, como um mapeamento de formato de arquivo ou hardware.

Claro que isto é altamente não-portátil uma vez que diferentes implementações têm diferentes ordens de byte, ordens que os bits são adicionados a uma unidade de armazenamento de campo de bits (de cima ou de baixo), tamanho de unidades de armazenamento, por defeito de alinhamento etc.

Quanto à sua segunda pergunta, eu não posso ver o problema, embora eu nunca usar scanf como é problemático.

Além do fato de que há "também pode haver preenchimento sem nome, no final de uma estrutura ou união", o compilador é permitido colocar um campo de bits em "qualquer unidade de armazenamento endereçável suficientemente grande para conter um campo de bits" . (Ambas as citações são do padrão C90 - não é semelhante, mas diferente, frase estanho o padrão C99).

Observe também que o padrão diz que um "bit-campo deve ter um tipo que é uma versão qualificado ou não qualificado de int, int não assinado, ou int assinado", assim que ter um pouco de campo em um tipo char é não- padrão.

Como o comportamento de bitfields são tão dependentes de detalhes não especificados implementação do compilador (há vários outros problemas não-portáteis com bitfields que eu não tenha mencionado), utilizando-los é quase sempre uma má idéia. Em particular, eles são uma má idéia quando você está tentando modelo de bits campos em um formato de arquivo, protocolo de rede, ou se registrar hardware.


Mais informação de outra resposta SO :

Em geral, você deve evitar bitfields e usar outras constantes de manifesto (enums ou qualquer outra coisa) com pouco explícita mascarando e mudando para acessar o 'sub-campos' em um campo.

Aqui está uma razão pela qual bitfields deve ser evitados - eles não são muito portátil entre compiladores mesmo para o mesmo plataforma. a partir do padrão C99 (Há uma redacção semelhante no C90 standard):

Uma implementação pode alocar qualquer unidade de armazenamento endereçáveis ??suficientemente grande para manter um campo de bits. Se espaço suficiente permanece, um bit-campo que imediatamente segue outro bit-campo em um estrutura devem ser embalados em bits adjacentes da mesma unidade. E se insuficiência de restos de espaço, se um bit-campo que não cabe é put para a próxima unidade ou sobreposições unidades adjacentes está definido pela implementação. A ordem de alocação de bit-campos dentro de uma unidade (De alta para baixa ordem ou de ordem inferior a de ordem alta) é definido pela implementação. o alinhamento do armazenamento endereçáveis ??unidade está não especificado.

Você não pode garantir se um pouco campo vai 'espaço' um limite int ou não e você não pode especificar se uma bitfield começa no low-end do int ou a parte alta do int (este é independente de se o processador é grande ou-endian little-endian).

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top