Convertir una cadena decimal de máscara IP en un entero sin signo con ceros finales.
Obtengo una máscara como una cadena que recupero usando strtol
y strtok
y que quiero guardar en un unsigned int x
, seguido de ceros, y &
con una IP representada también como unsigned int
para mantener solo los MSBs (al final voy a comparar esa IP con otra).
Mi idea era establecer todos los bits de x
y luego apagar todos los bits colocados después del tamaño de la máscara:
#define IPV4_LENGTH 32
// subent es "123.34.45.66/31"
curr_IP->address = malloc(sizeof(struct in_addr));
token = strtok(subnet, "/");
inet_aton(token, curr_IP->address);
long mask = strtol(strtok(NULL, "/"), NULL, 10);
curr_IP->x = -1;
for (long i = mask; i <= IPV4_LENGTH; i++) {
curr_IP->x &= ~(1U << i);
}
Ejemplo: si la máscara es 31, quiero terminar con 11111111111111111111111111111110 representado en unsigned int
-> FFFFFFFE en HEX.
P.D. La máscara no puede ser 0.
ACTUALIZACIÓN:
Vista de memoria después de curr_IP->x = -1;
Podemos ver que de hecho establece todos los bits.
Vista de memoria después de curr_IP->x &= ~(1U << i);
cuando i = 31
Se espera fffffffe
.
davy.ai
Para lograr el resultado deseado, el código configura todos los bits de
curr_IP->x
en 1 utilizando la expresióncurr_IP->x = -1;
, lo cual establece todos los bits en 1 en la representación de complemento a dos.A continuación, el código establece en 0 todos los bits después de la posición de la máscara utilizando una operación bitwise AND entre el complemento del valor de la máscara desplazado a la izquierda por 1 y
curr_IP->x
. Esto tiene el efecto de apagar todos los bits encurr_IP->x
que están después de la posición de la máscara.El código debería funcionar como se espera si
máscara
es un número válido entre 1 y 32 inclusive. Simáscara
es 0 o mayor que 32, es posible que el valor resultante decurr_IP->x
no sea el que se pretendía.En general, el código parece aplicar correctamente una máscara de bits a una IP representada como un
unsigned int
.