C99 ha existido durante más de 10 años, pero su soporte ha sido lento, por lo que la mayoría de los desarrolladores se han quedado con C89. Incluso hoy en día, a veces me sorprende un poco cuando me encuentro con las funciones de C99 en el código C.
Ahora que la mayoría de los principales compiladores admiten C99 (MSVC es una excepción notable y algunos compiladores integrados también se quedan atrás), creo que los desarrolladores que trabajan con C probablemente deberían saber qué características de C99 están disponibles para ellos. Algunas de las características son solo características comunes que nunca se estandarizaron antes ( snprintf
por ejemplo), o son familiares de C ++ (ubicación de declaración de variable flexible o //
comentarios de una sola línea ), pero algunas de las características nuevas se introdujeron por primera vez en C99 y son desconocido para muchos programadores.
¿Cuáles le parecen las nuevas funciones más útiles de C99?
Como referencia, el estándar C99 (etiquetado como borrador, pero idéntico al estándar actualizado, hasta donde yo sé), la lista de nuevas características y el estado de implementación de GCC C99 .
Una función por respuesta, por favor; no dude en dejar varias respuestas. Se recomiendan ejemplos de código corto que demuestren nuevas características.
Respuestas:
Estoy tan acostumbrado a escribir
for (int i = 0; i < n; ++i) { ... }
en C ++ que es una molestia usar un compilador que no sea C99 donde me veo obligado a decir
int i; for (i = 0; i < n; ++i ) { ... }
fuente
sub esp, 4
yadd esp, 4
se eliminan! </sarcasm>stdint.h
, Que defineint8_t
,uint8_t
etc. Ya no tendrá que hacer suposiciones no portátiles sobre el ancho de sus números enteros son.uint32_t truth = 0xDECAFBAD;
fuente
Creo que los nuevos mecanismos de inicialización son extremadamente importantes.
struct { int x, y; } a[10] = { [3] = { .y = 12, .x = 1 } };
Bien, no es un ejemplo convincente, pero la notación es precisa. Puede inicializar elementos específicos de una matriz y miembros específicos de una estructura.
Quizás un mejor ejemplo sería este, aunque admito que no es muy convincente:
enum { Iron = 26, Aluminium = 13, Beryllium = 4, ... }; const char *element_names[] = { [Iron] = "Iron", [Aluminium] = "Aluminium", [Beryllium] = "Beryllium", ... };
fuente
Matrices de longitud variable:
int x; scanf("%d", &x); int a[x]; for (int i = 0; i < x; ++i) a[i] = i * i; for (int i = 0; i < x; ++i) printf("%d\n", a[i]);
fuente
if (x < 0) x = 0; else if (x > 1024) x = 1024;
Soporte para comentarios de una línea comenzando por
//
.fuente
Poder declarar variables en ubicaciones distintas al inicio de un bloque.
fuente
int a; int b; a = f(); b = g();
aint a = f(); int b = g();
? declarar una variable cerca de donde se inicializa es enorme para reducir errores./* this block is just for scoping */ {
} /* scope */
:)if(1) /* Scoping block */ {
}
es un poco mejor, pero un problema mayor es que el alcance y el control son conceptos ortogonales. Si bien hay ocasiones en las que tiene sentido establecer el alcance de las cosas dentro de un bucle, a menudo es útil tener las cosas dentro del alcance alrededor del bucle, y también hay muchas ocasiones en las que el código creará objetos para mantener valores que serán necesarios en la creación de objetos de vida más larga, pero nunca después de eso (por ejemplo,float dx=x2-x1, dy=y2-y1; float distance = sqrt(dx*dx+dy*dy);
no hay razón dx y debería necesitar ser mantenido en su alcance dy..Macros variadic. Facilita la generación de código repetitivo con un número ilimitado de argumentos.
fuente
snprintf()
- En serio, vale mucho la pena poder hacer cadenas formateadas seguras.fuente
Literales compuestos. Establecer estructuras miembro por miembro es tan '89;)
También puede usarlos para obtener punteros a objetos con duración de almacenamiento automático sin declarar variables innecesarias, por ejemplo
foo(&(int){ 4 });
en el lugar de
int tmp = 4; foo(&tmp);
fuente
Miembros de matriz flexibles.
Ejemplo:
typedef struct { int len; char buf[]; } buffer; int bufsize = 100; buffer *b = malloc(sizeof(buffer) + sizeof(int[bufsize]));
fuente
El tipo bool.
Ahora puedes hacer algo como eso:
bool v = 5; printf("v=%u\n", v);
imprimirá
1
fuente
bool
en C99 coacciona el valor asignado a la variable para que sea siempre 1 o 0. Por eso hay que tener cuidado si tiene código que se ejecuta en un compilador C99 y en uno más antiguo con tipo "simulado"bool
. El uso!!
lo hará portátil.v = !!5;
tiene la misma semántica, pero no es tan legible.Soporte para
inline
funciones.fuente
inline
todavía ayuda, porque le permite definir la función en más de una unidad de traducción, por lo que puede colocarla en un archivo de encabezado, lo que brinda oportunidades de inserción entre módulos.inline __attribute__((force_inline))
Literales compuestos, ya mencionados, pero aquí está mi ejemplo convincente:
struct A *a = malloc(sizeof(*a)); *a = (struct A){0}; /* full zero-initialization */ /* or */ *a = (struct A){.bufsiz=1024, .fd=2}; /* rest are zero-initialized. */
Es una forma clara de inicializar datos incluso si están en el montón. No hay forma de olvidarse de inicializar a cero algo.
fuente
La
restrict
palabra clave. Especialmente cuando haces números ...fuente
Soporte de secuencia de escape Unicode:
printf("It's all \u03B5\u03BB\u03BB\u03B7\u03BD\u03B9\u03BA\u03AC to me.\n");
O incluso, caracteres Unicode literales:
printf("日本語\n");
(nota: es posible que no funcione según su ubicación; el soporte portátil para diferentes codificaciones requerirá más trabajo que esto)
fuente
Constantes hexadecimales de coma flotante (
0x1.8p0f
) y especificadores de conversión (%a
,%A
). Si trabaja con detalles numéricos de bajo nivel con frecuencia, estos son una mejora enorme con respecto a las conversiones y literales decimales.Le ahorran las preocupaciones sobre el redondeo al especificar constantes para un algoritmo y son inmensamente útiles para depurar código de punto flotante de bajo nivel.
fuente
Personalmente, me gusta el reconocimiento de IEC 60559: 1989 (aritmética de punto flotante binario para sistemas de microprocesador) y mucho mejor soporte de punto flotante.
De manera similar, configurar y consultar el modo de redondeo de punto flotante, verificar números Nan / Infinity / subnormales, etc., es excelente.
fuente