c++ naming conventions
¿Qué constituye un identificador C "válido"? (4)
6.4.2 Identificadores
6.4.2.1 General
...
3 Cada nombre de carácter universal en un identificador debe designar un carácter cuya codificación en ISO / CEI 10646 se encuentre en uno de los rangos especificados en D.1. 71) El carácter inicial no será un nombre de carácter universal que designe a un personaje cuya codificación se encuentre en uno de los intervalos especificados en D.2. Una implementación puede permitir que los caracteres multibyte que no son parte del juego de caracteres básicos de origen aparezcan en los identificadores; qué caracteres y su correspondencia con los nombres de caracteres universales está definido por la implementación.
... 71) En los sistemas en los que los vinculadores no pueden aceptar caracteres extendidos, se puede usar una codificación del nombre del carácter universal para formar identificadores externos válidos. Por ejemplo, algunos caracteres o secuencias de caracteres que no se usen se pueden usar para codificar el / u en un nombre de carácter universal. Los caracteres extendidos pueden producir un identificador externo largo.
...Anexo D
(normativo)
Nombres de caracteres universales para identificadores
1 Esta cláusula enumera los valores de código hexadecimal que son válidos en los nombres de caracteres universales en los identificadores.
D.1 Rangos de caracteres permitidos
1 00A8, 00AA, 00AD, 00AF, 00B2-00B5, 00B7-00BA, 00BC-00BE, 00C0-00D6, 00D8-00F6, 00F8-00FF
2 0100-167F, 1681-180D, 180F-1FFF
3 200B-200D, 202A-202E, 203F-2040, 2054, 2060-206F
4 2070-218F, 2460-24FF, 2776-2793, 2C00-2DFF, 2E80-2FFF
5 3004-3007, 3021-302F, 3031-303F
6 3040-D7FF
7 F900-FD3D, FD40-FDCF, FDF0-FE44, FE47-FFFD
8 10000-1FFFD, 20000-2FFFD, 30000-3FFFD, 40000-4FFFD, 50000-5FFFD, 60000-6FFFD, 70000-7FFFD, 80000-8FFFD, 90000-9FFFD, A0000-AFFFD, B0000-BFFFD, C0000-CFFFD, D0000 -DFFFD, E0000-EFFFD
D.2 Rangos de caracteres no permitidos inicialmente
1 0300-036F, 1DC0-1DFF, 20D0-20FF, FE20-FE2F
En la sugerencia de @Zaibis (y relacionado con mi propia respuesta a ¿Cuáles son los caracteres válidos para los nombres de macro?, Así como 😃 (y otros caracteres Unicode) en identificadores no permitidos por g ++ )) ...
el clang permite un montón de personajes "locos" ... aunque he tenido problemas para encontrar mucha rima o razón, en cuanto a por qué algunos están permitidos (🔴 ϟ © © ©) y otros no (▶ ︎ ∀ © ©).
Por ejemplo, todos los siguientes compilan A-OK ( clang-700.1.76
)
#define 💩 ?: // OK (Pile of poo)
#define ■ @end // OK (HALFWIDTH BLACK SQUARE)
#define 🅺 @interface // OK (NEGATIVE SQUARED LATIN CAPITAL LETTER K)
#define P @protocol // OK (FULLWIDTH LATIN CAPITAL LETTER P)
sin embargo, todos los siguientes resultan en el mismo error de compilación ...
Macro name must be an identifier.
#define ☎ TEL
#define ❌ NO
#define ⇧ UP
#define 〓 ==
#define 🍎 APPLE
Los documentos de clang
refieren al problema , indicando solo ...
... soporte para identificadores extendidos en C99 y C ++. Esta característica permite que los identificadores contengan ciertos caracteres Unicode, según lo especificado por el estándar de idioma activo; estos caracteres se pueden escribir directamente en el archivo de origen utilizando la codificación UTF-8, o se pueden usar nombres de caracteres universales (/ u00E0, / U000000E0).
Entonces, supongo que estoy preguntando ... ¿cuál es el "estándar de lenguaje activo", y cómo puedo encontrar una fuente autorizada para qué identificadores son legales?
Creé el siguiente código solo para ver qué haría clang
con él. De aproximadamente 63488 posibles identificadores probados, 23 emitieron advertencias y 9506 generaron errores. Eso deja casi 54,000 caracteres válidos para usar en identificadores. Ciertamente, pero ¿quién se cortó? ¿Y por qué?
La sintaxis para identificadores, que incluye nombres de macros, se presenta en la sección 6.4.2 de la norma C2011, tal como se interpreta a la luz del apéndice D.1. Estas disposiciones sostienen que cada identificador puede contener caracteres de subrayado, letras latinas en mayúsculas y minúsculas, dígitos decimales, secuencias de caracteres que constituyen "nombres universales de caracteres" (sujetos a limitaciones) y cualquier otro carácter definido por la implementación .
Los nombres de caracteres universales (UCN) son secuencias de escape Unicode similares a las proporcionadas por Java, Python y algunos otros lenguajes: comienzan con una barra inclinada invertida ( /
), seguida de una u
o U
, y cuatro u ocho dígitos hexadecimales, respectivamente. Existen algunas limitaciones en las secuencias de dígitos hexadecimales específicas que se pueden usar, algunas generales, otras específicas al contexto del identificador. Sin embargo, tenga en cuenta que sintácticamente , el único carácter adicional que la disposición para UCNs permite que aparezca en los identificadores es la barra diagonal inversa; todos los demás personajes que pueden aparecer en un UCN también están permitidos en identificadores fuera del contexto de UCN.
Por lo tanto, al hablar sintácticamente y restringir la discusión a los caracteres que requiere el estándar para ser admitidos en los identificadores, el guión bajo, las letras latinas (sin acentos), los dígitos decimales y la barra invertida son los únicos caracteres que C requiere deben ser compatibles con los identificadores. El soporte para la barra diagonal inversa solo se requiere en el contexto de los UCN, y no todos los UCN válidos están permitidos en los identificadores. Además, el estándar no requiere soporte para dígitos como los primeros caracteres de los identificadores.
Por otro lado, el estándar es bastante liberal al permitir "otros caracteres definidos por la implementación" en los identificadores, incluido el primer carácter. Incluso los dígitos decimales, que de otro modo no podrían ser el primer carácter de un identificador, podrían, en principio, permitirse en esa posición según esta disposición, a discreción de la implementación. Si desea que su código sea portátil entre las implementaciones, evitará confiar en esta disposición en cualquier lugar. Si desea saber qué caracteres permite su implementación particular, debe consultar su documentación.
Toda implementación conforme al estándar debe documentar su comportamiento con respecto a cada detalle que el estándar declara como implementación definida. Por ejemplo, la documentación de GCC especifica que el signo de dólar ( $
) está permitido en identificadores en la mayoría de las arquitecturas de destino. Usted mismo ha vinculado y citado la documentación de Clang del mismo detalle definido por la implementación, que es más liberal: permite que todos los caracteres que pueden representarse en los identificadores a través de UCN también puedan ser representados por secuencias de bytes UTF-8. En muchos casos, si visualiza o imprime un código fuente que contenga tales secuencias de bytes, se representarán como un único carácter de visualización.
Como ya se mencionó, el estándar C11 define varios rangos permitidos de caracteres Unicode.
- 00A8, 00AA, 00AD, 00AF, 00B2-00B5, 00B7-00BA, 00BC-00BE, 00C0-00D6, 00D8-00F6, 00F8-00FF
- 0100-167F, 1681-180D, 180F-1FFF
- 200B-200D, 202A-202E, 203F-2040, 2054, 2060-206F
- 2070-218F, 2460-24FF, 2776-2793, 2C00-2DFF, 2E80-2FFF
- 3004-3007, 3021-302F, 3031-303F
- 3040-D7FF
- F900-FD3D, FD40-FDCF, FDF0-FE44, FE47-FFFD
- 10000-1FFFD, 20000-2FFFD, 30000-3FFFD, 40000-4FFFD, 50000-5FFFD, 60000-6FFFD, 70000-7FFFD, 80000-8FFFD, 90000-9FFFD, A0000-AFFFD, B0000-BFFFD, C0000-CFFFD, D0000- DFFFD, E0000-EFFFD
Esto también significa que hay varios rangos de caracteres excluidos del uso.
De tus ejemplos:
- ☎ es
260E
y del bloque "Símbolos misceláneos":2600-26FF
que significa que te estás perdiendo de todos estos - ❌ es
274C
y del bloque "Dingbats":2700-27BF
que es todo esto, pero algunos están permitidos (2776−2793
) - ⇧ es
21E7
y desde el bloque "Flechas":2190-21FF
que significa que estás perdiendo todos estos - 〓 es
3013
y del bloque "Símbolos y signos de puntuación CJK":3000-303F
que es todo esto, pero algunos de ellos están permitidos. - 🍎 es
1F34E
y del bloque "Símbolos y pictografías misceláneos":1F300-1F5FF
que es todo esto y que realmente debería funcionar
(¿Tal vez un problema declang
? Por cierto, esto no se muestra en la computadora de mi casa (Ubuntu) pero en mi PC de trabajo (Win7))
Como han mencionado otros, el Anexo D de ISO / IEC 9899: 2011 enumera los valores hexadecimales de los caracteres válidos para los nombres de caracteres universales en C11. (No me molestaré en repetirlo aquí.) He estado buscando una respuesta en cuanto al "por qué" esta lista fue elegida.
Conjunto de caracteres estándares
Primero, hay dos estándares relevantes que definen un conjunto de caracteres: ISO / IEC 10646 (que define UCS ) y Unicode . Para confundir (o simplificar) las cosas, ambos definen los mismos caracteres, ya que ISO y Unicode los mantienen sincronizados . UCS es esencialmente solo un mapa de caracteres que asocia valores a un conjunto de caracteres ("repertorio"), mientras que Unicode también proporciona definiciones adicionales sobre cómo comparar cadenas en orden alfabético ( clasificación ), cuyos puntos de código representan caracteres "canónicamente equivalentes" ( normalización ), y un algoritmo bidireccional de cómo procesar caracteres en idiomas escritos de derecha a izquierda, y más.
Nombres de personajes universales en C
Los nombres de caracteres universales (UCN) fueron una característica recientemente agregada en C99 (ISO / IEC 9899: 1999). En el "Fundamento del estándar internacional --- Lenguajes de programación --- C" ( Rev. 2, octubre de 1999 ), el propósito era "permitir el uso de cualquier carácter ''nativo'' en identificadores, literales de cadenas y constantes de caracteres, conservando el objetivo de portabilidad de C "(sección 5.2.1). Esta sección continúa sobre los problemas de cómo codificar estos caracteres en C (las formas /U
y /u
frente a los caracteres multibyte o las codificaciones nativas) y los modelos de políticas sobre cómo manejarlo (p.14, ver PDF página 22).
Razón fundamental
Esperaba que el mismo documento de "justificación" de 1999 diera una razón de por qué cada rango de caracteres extendidos fue seleccionado como aceptable para los UCN de C99. La totalidad del Anexo I de la justificación es:
Anexo I Nombres de caracteres universales para identificadores (normativos)
Una nueva característica de C9X.
Esto no es una gran justificación. Ni siquiera sabían en qué año se publicaría el estándar C, por lo que simplemente se llama "C9X". Un documento racional posterior de 2003 es un poco más esclarecedor:
Anexo D Nombres de caracteres universales para identificadores (normativos)
Nueva función para C99.
La intención es mantenerse al día con ISO / IEC TR 10176.
ISO / IEC TR 10176 es "Pautas para la preparación de estándares de lenguaje de programación". Es básicamente una guía para personas que escriben estándares de lenguaje de programación. Incluye pautas para el uso de juegos de caracteres en lenguajes de programación, así como un "repertorio extendido recomendado para identificadores definidos por el usuario" (Anexo A). Pero esta cita del documento de justificación del 2003 es solo una "intención de mantenerse al día", no una promesa de adhesión estricta al TR 10176.
Hay una tabla de caracteres ISO / IEC TR 10176: 2003 públicamente disponible. Los valores de los caracteres se refieren a ISO 10646. La tabla clasifica los rangos de caracteres de numerosos idiomas como Lu
"mayúscula"; "minúsculas" Ll
; "número, dígito decimal" Nd
, "puntuación, conector" Pc
; etc. Debería quedar claro qué uso tienen tales clasificaciones para un lenguaje de programación.
Un recordatorio importante es que TR 10176 es un Informe Técnico, y no un estándar. He encontrado varias referencias que lo pasan en foros y documentos relacionados con otros lenguajes de programación, como Ada, COBOL y D. Gran parte de la discusión fue acerca de cuán estrechamente deben seguir los estándares de esos idiomas TR 10176 (que no es un estándar) y las quejas de que TR 10176 iba a la zaga de las actualizaciones de ISO 10646.
Quizás lo más esclarecedor es el documento WG21 / N3146 : "Recomendaciones para caracteres de identificación ampliados para C y C ++". Comienza con un comentario en 2010 al cuerpo de normas que recomienda restricciones sobre los caracteres iniciales de los identificadores. Menciona quejas similares sobre C referenciando TR 10176, y hace sugerencias sobre qué caracteres deberían permitirse como caracteres iniciales de un identificador basado en las restricciones del identificador y la sintaxis de patrones de Unicode y los constructos sintácticos comunes de XML . WG21 / N3146 proporciona la redacción propuesta que más tarde apareció en el estándar C11 ISO / IEC 9899: 2011 . Hay una tabla al final del documento que ayuda a arrojar luz sobre los rangos de caracteres seleccionados.
Caracteres permitidos y no permitidos en C11
A continuación se muestra una lista compilada de rangos para caracteres de identificación extendidos . Los rangos en negrita son los que figuran en C11 ( ISO / IEC 9899: 2011 Anexo D ). Se agregan algunos comentarios sobre los rangos en cursiva que no figuran en C11 (es decir, no está permitido). Están marcados en WG21 / N3146 como no permitido por UAX # 31 de Unicode o por construcciones sintácticas comunes de XML , o están prohibidos por algún otro comentario.
00A8, 00AA, 00AD, 00AF, 00B2-00B5, 00C0-00D6, 00D8-00F6, 00F8-00FF : (Varios caracteres, como femenino ª y masculino º indicadores ordinales, vocales con signos diacríticos, caracteres numéricos como números superíndices, fracciones , etc.)
(huecos previos) : Todo no permitido por UAX31 y / o XML . (Generalmente, el tipo de puntuación marca como «», símbolos monetarios ¥ £, operadores matemáticos × ÷, etc.)
0100-167F : (latín, griego, cirílico, árabe, tailandés, etíope, etc.-- muchos otros)
1680 : "El bloque Ogham contiene un espacio específico de script:"
1681-180D : (Ogham, tagalo, mongol, etc.)
180E : "El bloque de Mongolia contiene un espacio específico de script"
180F-1FFF : (Más idiomas ... fonética, latín extendido y griego, etc.)
2000 : comienza el bloque "Puntuación general", pero algunos están permitidos:
200B-200D, 202A-202E, 203F-2040, 2054, 2060-206F : (selecciones del bloque "Puntuación general")
2070-218F : "Superíndices y subíndices , símbolos de moneda, combinación de marcas diacríticas para símbolos, símbolos en forma de letra, formas numéricas"
2190-245F : "Flechas, operadores matemáticos, técnica técnica variada , imágenes de control, reconocimiento óptico de caracteres"
2460-24FF : "Alfanuméricos incluidos"
2500 : inicia "Dibujo de caja, elementos de bloque, formas geométricas", etc.
2776-2793 : (algunos dingbats y dingbats circulados)
2794-2BFF : (un conjunto diferente de dingbat, símbolos matemáticos, flechas, patrones de Braille, etc.)
2C00-2DFF, 2E80-2FFF : "Glagolitic, Latin Extended-C, Coptic, Georgian Supplement, Tifinagh, Ethiopic Extended, Cyrillic Extended-A" (también suplemento radical CJK)
3000 : (inicio de "Símbolos y signos de puntuación CJK", algunas selecciones permitidas)
3004-3007, 3021-302F, 3031-303F : (permitido "CJK Symbols and Punctuation")
3040-D7FF : "Hiragana, Katakana", más ideogramas CJK, radicales, etc.
D800-F8FF : (Esto inicia las áreas sustitutas alta y baja (espacio de número necesario para codificaciones) y uso privado )
F900-FD3D, FD40-FDCF, FDF0-FE44, FE47-FFFD : selecciones de "Ideogramas de compatibilidad CJK", "Formularios de presentación en árabe", etc. 10000-1FFFD, 20000-2FFFD, 30000-3FFFD, 40000-4FFFD, 50000- 5FFFD, 60000-6FFFD, 70000-7FFFD, 80000-8FFFD, 90000-9FFFD, A0000-AFFFD, B0000-BFFFD, C0000-CFFFD, D0000-DFFFD, E0000-EFFFD : WG21 / N3146 da la razón de estos rangos finales:
El Área de Uso Privado Suplementario se extiende desde F0000 hasta 10FFFF; tanto [AltId] como [XML2008] no permiten caracteres en ese rango.
Además, [AltId] no permite, como no caracteres, las dos últimas posiciones de código de cada plano, es decir, cada posición de la forma P FFFE o P FFFF, para cualquier valor de P.
Los "Rangos de caracteres anulados inicialmente" del anexo D.2 del C11 son 0300-036F, 1DC0-1DFF, 20D0-20FF, FE20-FE2F .
Con este WG21 / N3146 colocado junto al Anexo D del estándar C11 , se puede inferir mucho acerca de cómo se alinean. Por ejemplo, los operadores matemáticos y la puntuación parecen no estar permitidos. Espero que esto arroje algo de luz sobre "por qué" o "cómo" fueron elegidos los personajes permitidos.
TLDR; versión
- La fuente autorizada para los caracteres del identificador legal es el estándar C11 ISO / IEC 9899: 2011 (Ver Anexo D).
- Esta lista se basa en un informe técnico, ISO / IEC TR 10176 , pero con modificaciones .