1. Este site usa cookies. Ao continuar a usar este site está a concordar com o nosso uso de cookies. Saber Mais.

Manipulação de bist em C

Discussão em 'Programação' iniciada por chumbalala, 26 de Outubro de 2007. (Respostas: 20; Visualizações: 3527)

  1. Este deve permitir ao utilizador manipular os seguintes
    tipos de dados sem sinal: char, short , int e long.
    As funcionalidades mais simples permitem obter um determinado bit de um número e
    alterar um determinado bit com um valor booleano.
    Os seguintes protótipos servem de referência a estas funções:

    /* get a bit from an unsigned "byte" number */
    bool getBitByte(unsigned char num, unsigned short index);

    Alguem me pode dar uma ajudinha nesta situação??

    Obrigado
     
    Última edição: 26 de Outubro de 2007
  2. AragTey

    AragTey Power Member

    Epa já não me recordo muit bem disto, mas aqui vai.
    Convem saberes o numero de bits de cada tipo:

    char -> 1 bit
    int -> 2 bits
    short int -> 2 bits
    long int - >4 bits
    unsigned -> sem sinal que dizer que:

    int x - x varia de -32768 a 32768
    unsigned int x - x varia de 0 a 65536

    penso que é isto. Depois tens os operadores para manipular os bits:

    << , >> , &, |

    comeca por isto ... e vai lendo\ desenvolvendo. Duvidas pergunta ;)
     
  3. sapropel

    sapropel Power Member

    isso precisa aí de correcções, char 1 bit, int 2 bits sem falar no resto? erro MUTO GRAVE.

    quanto a descobrir bit:

    num >>= index; //num bit index 0 tem agora o bit do index que querias.
    if( num & 0x01 ) // 0x01 == 000(...)1 com um AND vao devolver 0 se tiver zero no de menor peso, 1 se tiver 1 no de menor peso.
    return 1;
    else
    return 0;

    PS: isto tendo em conta que o index começa em 0 ou seja se o num = 1 e o index = 0 a função ia devolver true porque existe um bit de valor 1 no index 0. se quiseres para index começar em 1 puxa um bocado pela cabeça, porque não é dificil. já agora adicionar um check para ver se o index não é maior que o numero de bits do tipo que está s er passao também não ficava mal.
     
    Última edição: 26 de Outubro de 2007
  4. AragTey

    AragTey Power Member

    Ups..parace que tava mesmo esquecido...fui pesquisar:

    char, signed char, unsigned char -> 8 bits
    int, short int, unsigned int -> 16 bits
    long, unsigned long -> 32 bits

    Peco desculpa ao OP se o induzi em erro e obrigado ao sapropel pela correção.

    Agora se me dão licença vou esconder-me ali ao canto...e esperar que o chefalhão nào ande aqui na TZ.
     
  5. Se bem entendi so devolve 1 ou 0??!!!

    num >>= index;
    if( num & 0x01 )
    return 1;
    else
    return 0;


    Com este codigo??

    e se colocar por exemplo o numero 12, nao pode so retornar 1 ou 0??!!!
     
  6. MadOnion

    MadOnion Folding Member

    O teu primeiro post estaria certo, se em vez de Bits, tivesses dito Bytes.
     
  7. sapropel

    sapropel Power Member

    nop, int, long, long int, etc tem tudo 4 bytes (32 bits).
    long long, double, etc tem tudo 8 bytes (64 bits).
    o unico certo é o char tem 1 byte (8 bits).

    chumbalala: a função devolve bool portanto ou é true ou false, segundo percebi queres que devolva 1 se o bit no index <index> tiver a 1. e que devolva 0 se esse bit tiver a 0.
    se meteres 12 e um index qualquer ele devolve true se esse index tiver o bit a 1 e false se tiver a 0.

    EDIT:
    12 = 1100 em bin
    se passares 12 como numero e 2 como index ele devolve true (1).
    1<index 3> 1<index 2> 0<index 1> 0<index 0>
    capiche? se não percebeste ainda, aconselho a pegares no livro de seja la qual for essa cadeira, e estudar.
     
    Última edição: 26 de Outubro de 2007
  8. Consu

    Consu Power Member

    Operadores Bitwise

    Convém referir primeiro algumas noções/revisões no que toca a operadores ao nível do bit:
    & -> E(AND) lógico ( 0&0 = 0; 0&1 = 1&0 = 0; 1&1 = 1 ) : Ambos a 1
    | -> OU(OR) lógico ( 0|0 = 0; 0|1 = 1|0 = 1; 1|1 = 1 ) : Pelo menos 1 a 1
    ^ -> OU-Exclusivo(XOR) ( 0|0 = 0; 0|1 = 1|0 = 1; 1|1 = 0 ) : Bits diferentes

    >> -> Shift Left ( Desloca os bits para a esquerda )
    << -> Shift Right ( Desloca os bits para a direita )

    Sempre que é usado var <operador>= valor é feita uma atribuição com o valor da operação.
    Ex: var = 0x01; var |= 0x02; ( var fica com o valor 0x02 -> 00000001 | 00000010 = 00000011 )

    Código:
    [LEFT][SIZE=2][FONT=Courier New][COLOR=#008100]/* get a bit from an unsigned "byte" number */[/COLOR][/FONT][/SIZE][/LEFT]
    [FONT=Courier New][SIZE=2][COLOR=#0000ff][COLOR=white]bool [/COLOR][/COLOR][/SIZE][/FONT][COLOR=white][FONT=Courier New][SIZE=2]getBitByte([/SIZE][/FONT][FONT=Courier New][SIZE=2]unsigned char [/SIZE][/FONT][FONT=Courier New][SIZE=2]num, [/SIZE][/FONT][FONT=Courier New][SIZE=2]unsigned short [/SIZE][/FONT][FONT=Courier New][SIZE=2]index) {
        return ( num & ( 1 << index ) );
    }
    [/SIZE][/FONT][/COLOR]


    Isto funciona para qualquer tipo de dados, tens é de ter cuidado se o index
    Aqui considerei que o 1º bit é o bit 0.
    Se queres usar uma função genérica para
    está dentro do limite dos dados.
    char, short , int e long sugiro que uses C++ e templates.

    Ex:
    Código:
    [FONT=Courier New][SIZE=2] template <class Num>
    bool getBitByte( Num num, unsigned short index ) {
         if( ( sizeof( Num ) << 3 ) <= index ) return false; [COLOR=DarkGreen]// Indíce inválido(tratar)[/COLOR]
    
            return ( num & ( 1 << index ) );
    }[/SIZE][/FONT]
    
    Notas:
    Shift para a direita de uma unidade é o mesmo que multiplicar por 2, logo x << 3 é o mesmo que multiplicar por 8.
    Shift para a esquerda é o mesmo que dividir por 2.

    Desta forma o compilador trata de criar funções para cada um dos tipos que queres e não precisas de escrever 4 funções.

    Num bit ou tens 0 ou 1 guardado, bit é uma abreviatura de binary digit( 0 ou 1 ).
    Se queres analisar cada uma das posições isso pode ser feito com um ciclo.

    Espero ter ajudado. :)
     
    Última edição: 30 de Outubro de 2007
  9. Os tamanhos dos tipos primitivos em c não são valores fixos, estes dependem da maquina que os compila. Os valores aqui apresentados estão correctos apenas para maquinas de 32 bits. Em maquinas de 64 bits por exemplo os valores sao diferentes.
     
  10. sapropel

    sapropel Power Member

    errado. o compilador (e consequentemente o fabricante dele) é que decide o tamanho dos tipos, e não a maquina. se eu quiser inteiros de 128 bits numa maquina de 16, é possivel desde que o implemente no meu compilador.

    dito isto o standard para maquinas 32bits (ILP32) define int, long int e ponteiros como 32bits, e o standard para maquinas 64bits (LP64) muda APENAS long int e ponteiros para 64bits o resto é totalmente igual.

    sure, pode existir compiladores que definem 256bit para um inteiro.. mas no mundo real se exister tal coisa será para apenas para um caso muito expecifico.
     
  11. este tópico foi-me bastante útil no entanto andei a testar e deparei-me com um problema.

    e se por exemplo quiser converter um nr de bits "11111001" para decimal, do tipo:


    unsigned char Char2Bit(unsigned char * ch)

    ou seja recbendo um unsigned char com "11111001" para returnar um valor 249.


    tentei:

    Código:
    unsigned char z;
        char bytes [9] = "11111001";
        bytes [8] = '\0';
    
        for(int i = 0; i<8; i++)
        {
            if(bytes[i] == '1')
            {
                z = z|1;
                z<<=1;
            }
            else
                z<<=1;
        }
    o normal seria:

    Código:
    unsigned char z = 0;
        char bytes [9] = "11111001";
        bytes [8] = '\0';
        int a, i;
    
        for (i = 7; i >= 0; i--)
        {
            if(i == 7)
            {
                a = 1;
    
                if(bytes[i] == '1')
                    z += a;
            }
            else
            {
                a *= 2; 
                if(bytes[i] == '1')
                    z += a;
            }} 
    (z = 249) assim já funciona, mas eu pretendia era com a utilização dos bitwises como tenho no 1º exemplo, alguma dica?
     
  12. manipulação de BITS em C

    alguém que me possa ajudar?! :'(
     
  13. bem, já resolvi o que pretendia, para quem precisar aqui fica o código.


    Código:
        unsigned char bytes1 [9] = "10110001";
        unsigned char * apt2 = bytes1;
        printf ("bin/dec - %s ", apt2);
        unsigned char dec = CharToBit(apt2);
        printf ("- %d \n", dec);
    
    unsigned char CharToBit(unsigned char *x)
    {
        unsigned char z;
        for(int i = 0; i<7; i++)
        {
            if(x[i] == '1')
            {
                z|=1;
                z<<=1;
            }
            else
                z<<=1;
        }
    
        if(x[7] == '1') 
            z|=1;
        
        return z;
    }
    cumps.
     
  14. Consu

    Consu Power Member

    Seria interessante ver o z inicializado a 0, caso contrário podem aparecer erros... ;)

    Código:
    unsigned char BinaryToDecimal( unsigned char *x ) {
        unsigned char z = 0;
    
        for( int i = 0; i < 8; ++i ) {
            z <<= 1;
    
            z |= ( x[i] == '1' ? 1 : 0 );
        }
        
        return z;
    }
    
    Para quê complicar o que é simples? :p
     
  15. naoliveira

    naoliveira Power Member


    simplificando ainda mais, porque é que não mudas esta linha :
    z |= ( x == '1' ? 1 : 0 );
    apenas para esta?
    z |= x;
     
  16. CoolMaster

    CoolMaster Power Member



    '1' == 49
    logo
    '1' != 1
     


  17. pois, ehehe

    o meu problema é que eu estava a fazer uma coisa mal, é que estava a fazer o shift para a esquerda depois da adição do caracter, daí que após o ciclo no último bit ficava tudo mal, não me lembrei de colocar essa função antes (z<<=1) do que pretendia, axo que já era do sono. de qq forma, obrigado pelo reply pessoal.

    cumps.
     
  18. Consu

    Consu Power Member

    Já agora isso realmente pode ser ligeiramente melhorado:

    Código:
    z |= ( x[i] & 0x0F );
    
    É uma comparação que se poupa... :p
     
  19. naoliveira

    naoliveira Power Member

    mas x == a um bit => só pode ser 0 ou 1, não é? (Não percebo muito de C mas acho que é assim)

    em alternativa convertes o char para int ou bit :)


    Esta não percebi, o quê e ondes é que poupas?
     
  20. Consu

    Consu Power Member

    Aí tens apenas um & lógico, desta forma evitas comparar. O que está guardado num char é o seu código ASCII, assim sendo ao converteres para int ficas com o valor do código ASCII e não com 0 ou 1.
    Como em hexadecimal 1 é 0x31 e 0 é 0x30 com isso ficas como 0 ou 1. Neste caso como é sempre 0 ou 1 até podes fazer:
    Código:
     z |= (x[i] & 0x01 ); 
    Isto porque apenas nos interessa o último bit. Em binário 0 = 00000000 e 1 = 00000001.
     

Partilhar esta Página