134 votos

¿Cuál es tu truco favorito de programación de C?

Por ejemplo, recientemente me encontré con este en el kernel de linux:

/* La fuerza de un error de compilación si la condición es verdadera */
#define BUILD_BUG_ON(condición) ((void)sizeof(char[1 - 2*!!(condición)]))

Así, en el código, si usted tiene algún tipo de estructura que debe ser, es decir un múltiplo de 8 bytes de tamaño, tal vez porque de algunas de las limitaciones de hardware, usted puede hacer:

BUILD_BUG_ON((sizeof(struct mystruct) % 8) != 0);

y no va a compilar menos que el tamaño de la estructura mystruct es un múltiplo de 8, y si es un múltiplo de 8, no en tiempo de ejecución se genera el código.

Otro truco que yo conozco es de el libro de Gráficos "Gemas" que permite a un único archivo de encabezado para declarar e inicializar variables en un módulo, mientras que en otros módulos con el módulo que, simplemente declaran como externos.

#ifdef DEFINE_MYHEADER_GLOBALS
#define MUNDIAL
#define INIT(x, y) (x) = (y)
#else
#define MUNDIAL extern
#define INIT(x, y)
#endif

GLOBAL int INIT(x, 0);
GLOBAL int somefunc(int a, int b);

Con eso, el código que define x y somefunc:

#define DEFINE_MYHEADER_GLOBALS
#include "the_above_header_file.h"

mientras que el código que simplemente el uso de x y somefunc ():

#include "the_above_header_file.h"

Así se obtiene un archivo de encabezado que declara ambas instancias globales y prototipos de funciones donde se necesitan, y las correspondientes declaraciones extern.

Así que, ¿cuáles son tus favoritos de programación C trucos a lo largo de esas líneas?

81voto

Evan Teran Puntos 42370

C99 ofrece cosas geniales usando matrices anónimas:

Eliminación de variables sin sentido

{
    int yes=1;
    setsockopt(yourSocket, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int));
}

se convierte en

setsockopt(yourSocket, SOL_SOCKET, SO_REUSEADDR, (int[]){1}, sizeof(int));

Pasando una cantidad Variable de argumentos

void func(type* values) {
    while(*values) {
        x = *values++;
        /* do whatever with x */
    }
}

func((type[]){val1,val2,val3,val4,0});

Listas enlazadas estáticas

int main() {
    struct llist { int a; struct llist* next;};
    #define cons(x,y) (struct llist[]){{x,y}}
    struct llist *list=cons(1, cons(2, cons(3, cons(4, NULL))));
    struct llist *p = list;
    while(p != 0) {
    	printf("%d\n", p->a);
    	p = p->next;
    }
}

Cualquier estoy seguro que muchas otras cool técnicas que no he pensado.

68voto

fortran Puntos 26495

Al leer el código fuente de Quake 2 subí con algo como esto:

double normals[][] = {
  #include "normals.txt"
};

(más o menos, no tengo el código práctico para comprobarlo ahora).

Desde entonces, un nuevo mundo de uso creativo del preprocesador abrió delante de mis ojos. Ya no incluir sólo las cabeceras, pero enteros trozos de código y ahora (mejora la reutilización mucho):-p

Gracias John Carmack. xD

50voto

therefromhere Puntos 21329

Me gusta usar = {0}; para inicializar las estructuras sin necesidad de llamar a memset.

struct something X = {0};

Esto se inicialice todos los miembros de la estructura (o array) a cero (pero no cualquier bytes de relleno - uso memset si necesitas así como ésos cero).

Pero usted debe ser consciente de que hay algunos problemas con esto para estructuras grandes, asignadas dinámicamente.

45voto

Jackson Puntos 3828

Si estamos hablando de trucos c mi favorito tiene que ser dispositivo de Duff de bucle abocinar! Estoy esperando la oportunidad adecuada para venir por mí para usarla en ira...

42voto

Pierre Puntos 15256

usando __FILE__ y __LINE__ para la depuración

#define WHERE fprintf(stderr,"[LOG]%s:%d\n",__FILE__,__LINE__);

Iteramos.com

Iteramos es una comunidad de desarrolladores que busca expandir el conocimiento de la programación mas allá del inglés.
Tenemos una gran cantidad de contenido, y también puedes hacer tus propias preguntas o resolver las de los demás.

Powered by:

X