Oh sí, se usa. Yo trabajo en el campo del procesamiento de paquetes de red. He estado en dos compañías diferentes donde procesamos paquetes de red. Por lo tanto, estamos operando a nivel Ethernet o IP, no al nivel por encima de TCP.
Curiosamente, en ambas compañías se eligió C sobre C ++. En una de las compañías, uno de los dos productos se construyó sobre el kernel de Linux, mientras que el otro se construyó en el espacio de usuario de Linux. El producto del kernel obviamente usó C como el kernel de Linux está programado en C, pero eligieron usar C para el producto del espacio de usuario también. Ambos productos se desarrollaron a partir del año 2000 (el producto del núcleo un poco antes del 2000 y el producto del espacio del usuario un poco después del 2000).
En la empresa a la que fui después de eso, el producto se creó en C, no en C ++. En realidad, es una continuación de un proyecto desde mediados de la década de 1990, aunque debido a las recientes demandas de mejora del rendimiento, se decidió que básicamente todo se reescribirá. Tuvimos la opción de seleccionar C ++ debido a esta reescritura, pero no lo hicimos.
En el campo del procesamiento de paquetes de red, el rendimiento cuenta mucho. Por lo tanto, quiero implementar mi propia tabla hash con mayor rendimiento que las tablas hash existentes. Yo, no el autor de la tabla hash, soy quien selecciona qué función hash se va a utilizar. Tal vez quiera rendimiento e ir a MurMurHash3 . Tal vez quiera seguridad y vaya a SipHash . Los asignadores de memoria son obviamente personalizados. De hecho, todas las estructuras de datos importantes que utilizamos se han implementado de forma personalizada para obtener el mayor rendimiento posible.
Si bien no hay nada que impida el uso de C ++, generalmente es una mala idea. ¡Una sola excepción lanzada por paquete reducirá la tasa de procesamiento de paquetes a niveles inaceptables! Por lo tanto, no podemos usar las excepciones de C ++. Demasiado lento Ya estamos utilizando un tipo de código C orientado a objetos implementando estructuras de datos como estructuras y luego implementando funciones que operan en esas estructuras. C ++ permitiría tener funciones virtuales, pero nuevamente, las llamadas a funciones virtuales anularían el rendimiento si se usan en todas partes. Por lo tanto, es mejor ser explícito y tener un puntero a la función si se necesitan llamadas a funciones virtuales.
C ++ hará muchas cosas detrás de tu espalda: asignación de memoria, etc. Por otro lado, en C eso no suele ocurrir. Puede escribir una función que asigna memoria, pero generalmente es evidente desde la interfaz de la función que está ocurriendo la asignación.
Como ejemplo del tipo de microoptimizaciones que puede hacer al programar en C, eche un vistazo a la macro container_of en el kernel de Linux. Claro, podrías usar container_of en el código C ++, pero ¿quién hace eso? Quiero decir, es totalmente aceptable en la mayoría de los programas de C, pero los programadores de C ++ típicos propondrían de inmediato algo más, como una lista enlazada que asigna los nodos de enlace como bloques separados. No queremos eso porque cada bloque de memoria asignado es malo para el rendimiento.
Quizás lo único que nos beneficiaría en C ++ es que C ++ permite la metaprogramación de la plantilla, lo que significa que a veces se pueden evitar las llamadas a funciones virtuales sin dejar de tener un parámetro de función, y permitir que el compilador integre las funciones. Pero la metaprogramación de plantillas es complicada, y hemos logrado cumplir todos los requisitos en C, por lo que el beneficio de esta característica en C ++ no es tan importante.
En una de las compañías, en realidad teníamos un lenguaje compilado personalizado donde se implementaron parte de las características. ¿Adivina cuál era el idioma de destino del compilador? ¿Montaje? No, tuvimos que admitir arquitecturas de 32 y 64 bits. C ++? Seguramente usted bromea. Obviamente, era C con goto computarizado de GCC . Por lo tanto, el lenguaje personalizado se compiló en C (o en realidad la variante gcc de C que admite goto computado), y el compilador C produjo el ensamblado.