Manipulação de bist em C

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:
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 ;)
 
char -> 1 bit
int -> 2 bits
short int -> 2 bits
long int - >4 bits

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:
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.
 
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??!!!
 
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.

O teu primeiro post estaria certo, se em vez de Bits, tivesses dito Bytes.
 
O teu primeiro post estaria certo, se em vez de Bits, tivesses dito Bytes.
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:
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.

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??!!!
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:
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.
 
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.

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


simplificando ainda mais, porque é que não mudas esta linha :
z |= ( x == '1' ? 1 : 0 );
apenas para esta?
z |= x;
 
Para quê complicar o que é simples? :p



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.
 
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.
 
Back
Topo