int main() { i/*nt*/a = 10; return 0; }Si tengo el código anterior y quiero contar las fichas, ¿serán 14 o 13 fichas?
¿Es válido escribir un comentario dentro de un nombre de variable? Puede suponer que int i , int a , int ia están definidos globalmente.
El resultado será como si hubieras escrito:
ia = 10;NO:
ia = 10;Desde un punto de vista léxico, un comentario es lo mismo que un espacio en blanco.
La sección 6.4p3 del estándar C con respecto a los elementos léxicos establece:
... Los tokens de preprocesamiento pueden estar separados por espacios en blanco ; esto consiste en comentarios (descritos más adelante) o caracteres de espacio en blanco (espacio, tabulador horizontal, nueva línea, tabulador vertical y salto de página), o ambos. ...
Más específicamente, un comentario se traduce en un solo espacio. Esto se especifica en la sección 5.1.1.2p3:
El archivo de origen se descompone en tokens de preprocesamiento y secuencias de caracteres de espacio en blanco (incluidos los comentarios). Un archivo fuente no debe terminar en un token de preprocesamiento parcial o en un comentario parcial. Cada comentario se reemplaza por un carácter de espacio. Los caracteres de nueva línea se conservan. La implementación define si cada secuencia no vacía de caracteres de espacio en blanco que no sean de nueva línea se retiene o reemplaza por un carácter de espacio.
Para ilustrar esto, si pasa su código a través del preprocesador, obtendrá:
int main() { ia = 10; return 0; }Entonces, los comentarios, como los espacios en blanco, sirven para separar tokens.
Esto significa que el código contendrá 14 fichas, no 13.
Los comentarios se eliminan durante la fase 3 de la traducción del programa 1 : cada comentario se reemplaza por un carácter de espacio. entonces el comentario /*nt*/ definitivamente no es un token.
Si ninguno de int , main , i , a o return están definidos como macros de preprocesamiento, analizar el programa produce 14 tokens (no 13):
int main ( ) { i a = 10 ; return 0 ; }
A menos que i se defina como un tipo con una declaración typedef , hay un error de sintaxis ya que ia no coincide con una regla en la gramática C.
Por lo tanto, no puede escribir comentarios dentro de nombres de variables, el comentario divide el identificador en 2 tokens separados. Esto es cierto para cualquier preprocesamiento y token de lenguaje C 2 .
Sin embargo, tenga en cuenta que puede insertar comentarios en lugares inusuales, como entre operadores unarios y su operando o entre # y la directiva de preprocesamiento y sus argumentos:
/**/#/**/include/**/<stdio.h>/**/////////////////////// /**/#/**/define/**/STAT/**/(/**/a/**/)/**/-/**/1/**//// /**/#/**/ifdef/**/STAT/**////////////////////////////// /**/int/**/main/**/(/**/)/**/{/**////////////////////// /**/int/**/a/**/=/**/+/**/1/**/;/**//////////////////// /**/printf/**/(/**/"Hello "/**/"world!\n"/**/)/**/;/**/ /**/return/**/STAT/**/;/**///////////////////////////// /**/}/**/////////////////////////////////////////////// /**/#/**/endif/**////////////////////////////////////// Pero la definición de macro anterior no define una macro similar a una función, sino una macro STAT regular que se expande a ( a ) - 1 .
Los nombres de variables, como cualquier otro token, se pueden dividir mediante saltos de línea con escape. Los saltos de línea escapados son secuencias o \ seguidas inmediatamente por un salto de línea. Estas secuencias se eliminan del código fuente durante la fase 2 de la traducción del programa. Su objetivo principal es dividir definiciones de macros largas en varias líneas.
A continuación se muestra un fragmento de código 3 que produce los mismos 14 tokens:
\ i\ nt\ ma\ in() {\ i/\ *nt\ */a \ = 10; r\ et\ urn\ 0;}Observe cómo el colorizador de código perdió las palabras clave cortadas y cortadas en cubitos y comente :)
1) Este comportamiento se especificó en ANSI-C, también conocido como C89. Algunos compiladores antiguos tenían un comportamiento sutilmente diferente que resultaba en el pegado de tokens, pero tales peculiaridades son solo de interés histórico.
2) Casi puedes insertar un comentario dentro de una constante de cadena aprovechando el hecho de que las constantes de cadena adyacentes se concatenan en la fase 6 de la traducción del programa: printf("Hello "/* my name is Luca */"world!\n");
3) Este estilo de presentación del Árbol de Navidad no está destinado a ser utilizado en programas reales, ilustra cómo abusar de las capacidades de manejo de entrada de C. Trucos más elaborados han ganado el Concurso Internacional de Código C Ofuscado
simplemente verifique qué forma su pieza de código
int main() { int i/*nt*/a = 10; return 0; }tendrá después del preprocesamiento. Simplemente agregue el indicador "-E" a su compilador, gcc -E myscript.c y obtendrá el resultado:
e.sharaborin@landau:~$ gcc -E myscript.c # 1 "myscript.c" # 1 "<built-in>" # 1 "<command-line>" # 31 "<command-line>" # 1 "/usr/include/stdc-predef.h" 1 3 4 # 32 "<command-line>" 2 # 1 "myscript.c" int main() { int ia = 10; return 0; }Y obviamente, puedes concluir que hay un error.