tour site plusplus oficial documentacion c++ c language-lawyer c-standard-library

plusplus - c++ website



¿Cuál es el significado de "reservado para cualquier uso"? (5)

NOTA: esta es una pregunta c , aunque agregué c ++ en caso de que algún experto en C ++ pueda proporcionar una razón lógica o histórica por la cual C ++ utiliza una redacción diferente a la C.

En la especificación de la biblioteca estándar de C, tenemos este texto normativo, C17 7.1.3 Identificadores reservados (el énfasis es mío):

  • Todos los identificadores que comienzan con un guión bajo y una letra mayúscula u otro guión bajo están siempre reservados para cualquier uso .
  • Todos los identificadores que comienzan con un guión bajo siempre se reservan para su uso como identificadores con alcance de archivo en los espacios de nombre ordinario y de etiqueta.

Ahora sigo leyendo las respuestas en SO de varios expertos en C estimados, donde afirman que está bien que un compilador o biblioteca estándar use identificadores con subrayado + mayúsculas o doble guión bajo.

¿"Reservado para cualquier uso" no significa reservado para nadie, excepto futuras extensiones del lenguaje C en sí? Lo que significa que la implementación no está permitida para usarlos.

¿Mientras que la segunda frase anterior, con respecto al guión bajo principal, parece estar dirigida a la implementación?

En general, el estándar C está escrito de manera que los proveedores de compiladores / implementadores de bibliotecas sean el lector típico, no tanto los programadores de aplicaciones.

En particular, C ++ tiene una redacción muy diferente:

  • Cada nombre que contiene un doble guión bajo ( __ ) o comienza con un guión bajo seguido de una letra mayúscula (2.11) está reservado a la implementación para cualquier uso .

(Consulte ¿Cuáles son las reglas sobre el uso de un guión bajo en un identificador de C ++? )

¿Es esto quizás una mezcla entre C y C ++ y los lenguajes son diferentes aquí?


C tiene múltiples contextos en los que un símbolo puede tener una definición:

  • El espacio de los nombres de macro,
  • El espacio de los nombres formales de los argumentos de una macro (este espacio es específico de cada macro similar a una función),
  • El espacio de identificadores ordinarios,
  • El espacio de nombres de etiquetas,
  • El espacio de etiquetas (este espacio es específico para cada función), y
  • El espacio de estructura / miembros de la unión (este espacio es específico para cada estructura / unión).

Lo que "reservado para cualquier uso" significa que el código de usuario en un programa compatible no puede usar 1 símbolos que comiencen con un guión bajo seguido de una letra mayúscula u otro guión bajo en cualquiera de los contextos anteriores. Compare con los identificadores que comienzan con un solo guión bajo pero que van seguidos de un número en minúscula o un dígito. Esto cae en la segunda clase de identificadores que comienzan con un guión bajo. El código de usuario puede usarse estos identificadores como nombres de argumentos de macro, como etiquetas o como nombres de miembros de estructura / unión.

"Reservado para cualquier uso" no significa que la implementación no pueda usar dichos símbolos. El propósito de la reserva es proporcionar un espacio de nombre que las implementaciones puedan usar libremente sin preocuparse de que los nombres definidos por la implementación entren en conflicto con los nombres definidos por el código de usuario en un programa compatible.

1 El estándar no significa "no se puede usar". El estándar fomenta el uso programático de una pequeña cantidad de nombres que comienzan con un subrayado doble. Por ejemplo, se requiere una implementación compatible para definir __STDC_VERSION__ , __FILE__ , __LINE__ y __func__ . La versión 2011 de la norma incluso da un ejemplo de un programa supuestamente compatible que hace referencia a __func__ .


Con respecto a la diferencia en la redacción en C versus C ++, estoy publicando mi pequeña investigación aquí como referencia:

  • La primera edición de K&R C 1 tiene este texto:

    ... los nombres que están destinados a ser utilizados únicamente por las funciones de la biblioteca comienzan con un guión bajo, por lo que es menos probable que coincidan con los nombres en el programa de un usuario.

  • La segunda edición de K&R agregó un Apéndice B que trata sobre la biblioteca estándar, donde podemos leer

    Los identificadores externos que comienzan con un guión bajo están reservados para el uso de la biblioteca, al igual que todos los demás identificadores que comienzan con un guión bajo y una letra mayúscula u otro guión bajo.

  • Los primeros borradores de ANSI C, así como "C90" ISO 9899: 1990, tienen el mismo texto que en la norma ISO actual.

  • Los primeros borradores de C ++, sin embargo, tienen un texto diferente, como se indica en @hvd, posiblemente una aclaración del estándar C. Del proyecto : 20 de septiembre de 1994 :

    17.3.3.1.2 Nombres globales
    ...
    Cada nombre que comienza con un guión bajo y una letra mayúscula u otro guión bajo (2.8) está reservado a la implementación para cualquier uso

Entonces, aparentemente, el comité ANSI / ISO C90 inventó el texto "reservado para cualquier uso", mientras que el comité C ++ algunos años más tarde utilizó un texto más claro, similar al del libro de K&R anterior a la norma.

El razonamiento C99 V5.10 dice esto a continuación 7.1.3:

También están reservados para el implementador todos los identificadores externos que comienzan con un guión bajo, y todos los demás identificadores que comienzan con un guión bajo seguido de una letra mayúscula o un guión bajo. Esto proporciona un espacio de nombre para escribir las numerosas macros no externas detrás de escena y las funciones que una biblioteca necesita para hacer su trabajo correctamente.

Esto deja muy clara la intención del comité: "reservado para cualquier uso" significa "reservado para el implementador".

También es de destacar que el estándar C actual tiene el siguiente texto normativo en otra parte, en 6.2.5:

También puede haber tipos enteros con signo extendido definidos por la implementación. 38)

donde la nota informativa del pie 38 dice:

38) Las palabras clave definidas por la implementación deben tener la forma de un identificador reservado para cualquier uso como se describe en 7.1.3.


El estándar C permite a las implementaciones adjuntar cualquier significado que consideren adecuado a los identificadores reservados. La mayoría de las implementaciones tratarán los identificadores no reconocidos de las formas reservadas de la misma manera que cualquier otro identificador reconocido cuando no haya razón para hacerlo de otra manera, permitiendo así algo como:

#ifdef __ACME_COMPILER #define near __near #else #define near #endif int near foo;

para declarar un identificador foo utilizando un calificador __near si el código se está procesando en un compilador Acme (que probablemente sería compatible con tal cosa), pero también es compatible con otros compiladores que no requerirían o no se beneficiarían del uso de dicha directiva. Nada prohibiría que una implementación conforme definiera __ACME_COMPILER e interpretara __near de significar "lanzar misiles nucleares", pero una implementación de calidad no debería salirse de su camino para romper el código como el anterior. Si una implementación no sabe lo que se supone que significa __ACME_COMPILER , tratarla como cualquier otro identificador desconocido le permitiría soportar construcciones útiles como la anterior.


En el estándar C, el significado del término "reservado" se define en 7.1.3p2, inmediatamente debajo de la lista de viñetas que está citando:

No hay otros identificadores reservados. Si el programa declara o define un identificador en un contexto en el que está reservado (distinto a lo permitido por 7.1.4), o define un identificador reservado como un nombre de macro, el comportamiento no está definido.

Énfasis mío: los identificadores reservados ponen una restricción en el programa , no en la implementación. Por lo tanto, la interpretación común (los identificadores reservados pueden ser utilizados por la implementación para cualquier propósito) es correcta para C.

No me he mantenido al día con el estándar C ++ y ya no me siento calificado para interpretarlo.


Mientras que el Estándar está escrito principalmente para guiar a los implementadores, está escrito como una descripción de lo que hace que un programa esté bien formado y cuál es su efecto. Esto se debe a que la definición básica de un compilador que cumple con los estándares es la que hace lo correcto para cualquier programa que cumpla con los estándares:

Un programa estrictamente conforme utilizará solo las características del idioma y la biblioteca especificados en esta Norma Internacional ... Una implementación alojada conforme aceptará cualquier programa estrictamente conforme.

Leído por separado, esto restringe enormemente las extensiones de un compilador. Por ejemplo, basándose únicamente en esa cláusula, un compilador no debería definir ninguna de sus propias palabras reservadas. Después de todo, cualquier palabra que un compilador en particular quiera reservar puede, sin embargo, aparecer en un programa estrictamente conforme, forzando la mano del compilador.

La norma continúa, sin embargo:

Una implementación conforme puede tener extensiones (incluidas funciones de biblioteca adicionales), siempre que no alteren el comportamiento de ningún programa estrictamente conforme.

Esa es la pieza clave. Las extensiones del compilador deben escribirse de tal manera que afecten a los programas no conformes (los que contienen un comportamiento indefinido, o que no deberían compilarse en absoluto), lo que les permite compilar y hacer cosas extra divertidas.

Por lo tanto, el propósito de definir "identificadores reservados", cuando el lenguaje no necesita realmente esos identificadores para nada, es dar a las implementaciones un margen de maniobra adicional al proporcionarles algunas cosas que hacen que un programa no se ajuste. La razón por la que un compilador puede reconocer, por ejemplo, __declspec como parte de una declaración es porque poner a __declspec en una declaración es ilegal, por lo que el compilador puede hacer lo que quiera.

La importancia de "reservado para cualquier uso", por lo tanto, es que no deja ninguna duda sobre el poder de un compilador para tratar tales identificadores como si tuvieran algún significado que le importe. La compatibilidad futura es una preocupación relativamente lejana.

El estándar de C ++ funciona de manera similar, aunque es un poco más explícito acerca de la táctica:

Una implementación conforme puede tener extensiones (incluidas funciones de biblioteca adicionales), siempre que no alteren el comportamiento de ningún programa bien formado. Las implementaciones son necesarias para diagnosticar programas que utilizan dichas extensiones que están mal formadas de acuerdo con esta Norma Internacional. Sin embargo, habiendo hecho esto, pueden compilar y ejecutar tales programas.

Sospecho que la diferencia en la redacción se debe al estándar C ++, ya que es más claro sobre cómo deben funcionar las extensiones. Sin embargo, nada en el estándar C impide que una implementación haga lo mismo. (Y todos, básicamente, ignoramos el requisito de que el compilador le avise cada vez que use __declspec ).