manipulación de un solo bit

¿Es posible obtener solo un bit de int en C y luego voltearlo sin leer todo el int y escribirlo en la memoria?

contexto: tratando de evitar demasiados lockings / deslockings en pthread.

No puede leer un solo bit de la memoria, en realidad no puede obligar a la CPU a leer solo un byte. Siempre está leyendo una línea de caché completa, que podría tener diferentes tamaños para diferentes CPU.

Pero desde el punto de vista del idioma, puede usar los campos de bits http://publications.gbdirect.co.uk/c_book/chapter6/bitfields.html

Que yo sepa, la unidad de operación más baja es el byte. Quizás pueda dividir el int en bytes y leer el byte requerido de la palabra y cambiar solo ese.

No. Por qué, incluso si pudieras leer un bit de la memoria, necesitarás un locking para asegurarte de que sea seguro.

Utilice el tipo más pequeño al que se puede dirigir de forma atómica (el char está bien en cualquier architecture sana, pero algunos elementos no deseados de RISC no pueden funcionar atómicamente en bytes individuales) y acepta que perderá espacio, utilizará un locking o usará el atómico correcto primitivas (en asm, gcc builtins o C1x _Atomic atómicos) para la aritmética atómica en bits individuales.

Aquí es cómo lo hace 50 veces más rápido que el abuelo mutex (hicimos pruebas en este tipo de cosas). Usa las operaciones atómicas de gcc. También puede utilizar las operaciones atómicas de Linux si su lanzamiento los incluyera.

 typedef union _foo { struct { unsigned int a:1, b:6, q:2; } Data; unsigned int n32; } TFoo; TFoo _GlobalFoo; SomeFuncThatChangesFoo_A(int fNewA) { TFoo Old, New; while(1) { // get a copy of the current state Old.n32 = _GlobalFoo.n32; New.n32 = Old.n32; New.Data.a = fNewA; // compare and swap is the atomic operation. // if _GlobalFoo hasn't changed since we copied it to "Old", then change _GlobalFoo to "New". // __sync_bool_compare_and_swap works on basic types (8 bit, 16 bit, 32 bit, 64 bit, 128 bit // depending upon architecture), which is why there is a union overlaying the 32 bit n32 over // the actual data that the program uses, Data. if (__sync_bool_compare_and_swap(_GlobalFoo.n32, Old.n32, New.n32)) break; // successfully changed // if we get here, the global was changed by another thread, so we just loop back, get the new value // and try again. } // concurrency loop } 

Los threaders astutos pueden pensar que la línea “Old.n32 = _GlobalFoo.n32;” podría copiar la basura en una carrera si el comstackdor eligió una forma no atómica para realizar la copia. Sin embargo, __sync_bool_compare_and_swap simplemente fallará debido a una copia incorrecta del estado actual, por lo que no se haría ningún daño.

aclamaciones.

Esto podría ser posible, pero solo de manera no portátil, no estándar y solo si su plataforma lo admite. Algunas CPU ARM (Cortex-M3 y M4, por ejemplo) implementan ‘bandas de bits’ que proporcionan direccionamiento a nivel de bits a regiones del espacio de direcciones.

Pero en general, la unidad más pequeña para lectura / escritura (o, de manera equivalente, la unidad más pequeña direccionable) es un char .