& es un bit-wise AND
Es decir es una AND bit a bit.
&& es una AND logica!.
La diferencia radica en cuando lo usas. Si vos queres hacer bit a bit usas &, si vos queres comparar true/false usas && ..
Un ejemplo para ver si queda mas claro.
a=0x30
b=0x45
if ( a==0x30 && b==0x90 )
{
}
En ese ejemplo ese if comienza a evaluarse. Supongamos que se evalua primero el a==0x30 , esto es un operador de igualdad y el '==' significa 'igual a', ¿ A es igual a 0x30 ? Eso me devuelve un TRUE , luego pregunta por b , pero b no es igual a 0x90, asi que me da FALSE, reemplazando me queda asi:
true AND false = false
Por lo tanto no va a entrar al if().
Que hubiera ocurrido si ponia solo '&', podria haber funcionado. Pero no es correcto hacerlo. Ya que son 2 usos distintos. Un caso que se pueda ver eso es:
a=0b0101 0101
b=0b1010 1010
if ( a & b )
{
// Aca NO entra
}
if ( a && b )
{
// Aca SI entra
}
En el primer caso si haces a AND b, te vas a encontrar que es 0. if(0) no entra. los if consideran cualquier valor distinto de 0 como verdaderos, el unico que representa el false es el 0
En el segundo caso, se evaluan primero si son verdaderos o falso ( a y b ), a tiene un valor distinto de 0, por lo tanto se evalua como True, b ocurre lo mismo y se evalua como True. Entonces True AND True = True, if (True) entra al if.
Espero que quede claro la diferencia. Hay muchos mas operandos.
Comparacion logica:
== igual , != no igual , < menor que, <= menor e igual que , > mayor que, >= mayor o igual que
= asignacion, ej: a = 10;
Luego tenes mas operandos que se forman con los de suma/multiplicacion/division/shift etc, y son para asignar:
+= , Ej a+=2; es lo mismo que poner a = a + 2;
/= , Ej a /= 2; igual que antes a = a / 2;
&= , a &= 2; , a = a & 2; AND bit a bit
|= , a |= 2; , a = a | 2; OR bit a bit
etc hay varios
https://en.wikipedia.org/wiki/Operators_in_C_and_C%2B%2B ¿Cómo sacas esos hex ? yo lo estoy haciendo con la calculadora de windows y 0xFF= 1111 1111, 0xC3=1100 0011 o el valor que escribiste es arbitrario para el ejemplo?
Los saco mentalmente xD, estoy tan acostumbrado a ver el binario y pasarlo a hex que es simple, por eso lo divido en 4 bits. y se que 0xC es 1100 , y 0x3 es 0011.
Respecto a si los valores son arbitrarios no los son. Tienen un por que.
Como te explique antes La idea es cambiar unicamente los bits de PUERTOC de RC2 a RC5, pero no cambiar los otros. Al usar una AND solo pongo en 0 los bits que corresponden a RC2 a RC5 ( son los que tienen un 0 en 0xC3 y que vos pedias como salida ) y los que quiero que queden iguales como RC0,Rc1,RC6,RC7 tienen un 1.
Por que ponerlos a 0 y no ir cambiando uno por uno?, Cuestion de gusto, Yo los puse a 0 a esos bits de esa forma los if que le siguen solo deberian ponerlo a 1 si es necesario, Si no hubiera hecho esto, deberia haber realizado un if..else como lo habias hecho vos por que ademas de ponerlo a 1 tendria que ponerlos a 0, Aca directamente solo tengo que ponerlos a 1 por que ya estan en 0.
Otro ejemplo. Supongamos que esta ves querias sacar el dato por el PUERTOC pero por RC0 Rc2 RC4 Rc7, ademas de cambiar los numeros de los bits en los bit_set(), deberia hacer una AND con:
0b0110 1010 = 0x6A
------------------------------------------------------------
PD:
Respecto al & , como veras sirve para indicar la direccion de una variable. Esto tiene que ver mas con los "punteros" de C. es un poco complejo el tema y que por ahora siento que deberias dejarlo pasar, pero punteros es lo mejor de C.