Oh sí, se usa. 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 en el nivel de Ethernet o IP, no en el nivel por encima de TCP.
Curiosamente, en ambas compañías C fue elegido sobre C ++. En una de las compañías, uno de los dos productos se creó sobre el núcleo de Linux, mientras que el otro producto se creó en el espacio de usuario de Linux. El producto del kernel obviamente usó C ya que el kernel de Linux está programado en C, pero también eligieron usar C para el producto del espacio de usuario. Ambos productos se desarrollaron a partir del año 2000 aproximadamente (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 compañía 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 de mediados de la década de 1990, aunque debido a las recientes demandas de mejora del rendimiento, se decidió que esencialmente todo se reescribirá. Teníamos una opción para 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 que tenga un 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 quiero rendimiento e ir a MurMurHash3 . Quizás quiero seguridad y voy por SipHash . Los asignadores de memoria son obviamente personalizados. De hecho, todas las estructuras de datos importantes que utilizamos se han implementado a medida 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 velocidad de procesamiento de paquetes a niveles inaceptables! Por lo tanto, no podemos usar las excepciones de C ++. Demasiado lento. Ya estamos utilizando una especie 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 matarían el rendimiento si se usaran en todas partes. Por lo tanto, es mejor ser explícito y tener un puntero de función si se necesitan llamadas a funciones virtuales.
C ++ hará muchas cosas a sus espaldas: asignación de memoria, etc. Por otro lado, en C eso generalmente no sucede. Puede escribir una función que asigne memoria, pero por lo general se deduce de 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ía usar container_of en código C ++, pero ¿quién lo hace? Quiero decir, es totalmente aceptable en la mayoría de los programas de C, pero los programadores típicos de C ++ propondrán inmediatamente otra cosa, como una lista vinculada 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 plantillas, lo que significa que a veces puede evitar las llamadas a funciones virtuales mientras todavía tiene un parámetro de función, y permitir que el compilador incorpore las funciones. Pero la metaprogramación de plantillas es complicada y hemos logrado cumplir con todos los requisitos en C, por lo que el beneficio de esta función en C ++ no es tan crítico.
En una de las compañías, en realidad teníamos un lenguaje compilado personalizado en el que se implementaron parte de las características. ¿Adivinen cuál era el idioma de destino del compilador? ¿Montaje? No, tuvimos que admitir arquitecturas de 32 bits y de 64 bits. C ++? Seguramente bromeas. Obviamente, era C con el goto calculado de GCC . Por lo tanto, el lenguaje personalizado se compiló en C (o en realidad la variante gcc de C que admitía goto calculado), y el compilador de C produjo el ensamblado.