C Sintaxis básica

C es un lenguaje de programación de propósito general, ampliamente utilizado en áreas como la programación de sistemas, el desarrollo embebido y la computación de alto rendimiento.

C se caracteriza por ser eficiente, flexible y altamente portátil; es la base de muchos otros lenguajes de programación (como C++, Java y Go), y sigue siendo la opción principal para el desarrollo de sistemas operativos, controladores y bibliotecas de bajo nivel.

En C, los tokens son las unidades básicas que componen un programa. El compilador analiza léxicamente el código fuente y lo descompone en tokens. Un token es la unidad mínima con significado que el compilador puede reconocer; todo programa C está formado por estos tokens.

Los tokens en C incluyen principalmente los siguientes tipos:

  • Palabras clave (Keywords): son palabras reservadas por el lenguaje con un significado especial, comoint、if、return。
  • Identificadores (Identifiers): son nombres definidos por el programador, utilizados para variables, funciones, arreglos, etc.
  • Constantes (Constants): son valores fijos e inmutables en el programa, como enteros42, números de coma flotante3.14。
  • Literales de cadena (String Literals): son secuencias de caracteres encerradas entre comillas dobles, como"Hello"。
  • Operadores (Operators): son símbolos utilizados para realizar operaciones, como+、==、&&。
  • Separadores (Separators): son símbolos utilizados para separar sentencias y bloques de código, como;、{}。

Estructura básica de un programa C

Este es un programa sencillo en C que puede imprimir "Hello, World!":

Ejemplo

#include <stdio.h>

int main() {
    printf("Hello, World!\n");
    return 0;
}

El código anterior se compone de la siguiente manera:

  • Directiva de preprocesador: como#includey#define, se procesa mediante el preprocesador antes de la compilación.
  • Función principal: cada programa C tiene una y solo unamain()función, que es el punto de entrada del programa.
  • Declaración de variables: declara las variables utilizadas en el programa; C89 exige que las declaraciones estén al comienzo del bloque de código.
  • Definición de funciones: define las funciones utilizadas en el programa y describe la lógica de implementación específica de cada función.

A continuación se explica una estructura de programa C un poco más compleja (los capítulos posteriores ampliarán cada punto):

Ejemplo

#include <stdio.h> // Inclusión de archivo de cabecera

#define PI 3.14159 // Definición de macro

// Declaración de la función
int add(int a, int b);

int main() {         // Función principal
    // Declaración de variables
    int num1, num2, sum;

    // Entrada del usuario
    printf("Enter two integers: ");
    scanf("%d %d", &num1, &num2);

    // Llamada a la función
    sum = add(num1, num2);

    // Salida del resultado
    printf("Sum: %d\n", sum);

    return 0;        // Devuelve 0 para indicar que el programa se ejecutó correctamente
}

// Definición de la función
int add(int a, int b) {
    return a + b;
}

Inclusión de archivos de cabecera

  • Los archivos de cabecera generalmente se usan al comienzo del programa mediante la#includedirectiva de inclusión. Los archivos de cabecera proporcionan declaraciones de funciones y bibliotecas, como la biblioteca estándar de entrada/salida<stdio.h>, la biblioteca estándar<stdlib.h>, etc. Definen funciones, macros, constantes, etc., para que el programa pueda utilizar funciones de biblioteca predefinidas.
  • Los archivos de cabecera del sistema se incluyen con corchetes angulares<>, y los archivos de cabecera definidos por el usuario se incluyen con comillas dobles"", la ruta de búsqueda de ambos es diferente.
  • Ejemplo:#include <stdio.h>(archivo de cabecera del sistema),#include "myheader.h"(archivo de cabecera definido por el usuario)

Definición de macros

  • Las macros se definen mediante la#definedirectiva, como constantes simbólicas o fragmentos de código. El preprocesador reemplaza el texto de las macros antes de la compilación; estas no ocupan memoria en tiempo de ejecución y se usan comúnmente para definir constantes o lógica de código en línea simple.
  • Las macros no tienen verificación de tipos, por lo que deben usarse con precaución; para constantes que requieren tipos, se recomienda usarconstvariables en su lugar.
  • Ejemplo:#define PI 3.14159、#define MAX(a, b) ((a) > (b) ? (a) : (b))

Declaración de funciones

  • En C, la declaración de una función (también llamada prototipo) debe aparecer antes de la definición o llamada de la función. La declaración proporciona el tipo de retorno, el nombre de la función y la lista de parámetros, de modo que el compilador pueda realizar la verificación de tipos en el punto de la llamada.
  • Las declaraciones de funciones pueden colocarse en archivos de cabecera para que múltiples archivos fuente las compartan.
  • Ejemplo:int add(int a, int b);

Función principal

  • main()La función `main` es el punto de entrada de un programa C; cada programa C debe contener unamain()función. El programamain()comienza a ejecutarse; el valor de retorno normalmente es0indica que el programa se ejecutó correctamente; un valor distinto de cero indica que se produjo un error.
  • main()La función `main` también puede recibir parámetros de línea de comandos:int main(int argc, char *argv[]), dondeargces el número de argumentos,argves la matriz de cadenas de argumentos.
  • Ejemplo:int main() { ... }

Declaración de variables

  • En un programa C, todas las variables deben declarar su tipo antes de usarse. Las variables pueden declararsemain()dentro de una función (variables locales) o globalmente fuera de una función (variables globales).
  • Al declarar una variable, se puede inicializar al mismo tiempo. Las variables locales no inicializadas contienen valores indeterminados (valores basura), mientras que las variables globales y estáticas se inicializan automáticamente a0。
  • Ejemplo:int count = 0;、float price = 9.99;、char grade = 'A';

Sentencias y expresiones

  • Una sentencia es la unidad básica de ejecución de un programa C; normalmente es una llamada a función, una asignación, una sentencia de control (comoif、foretc.) o una expresión. Una expresión es un fragmento de código compuesto por variables, operadores y constantes, que puede evaluarse para obtener un valor.
  • En C, la asignación en sí misma también es una expresión que tiene un valor (el valor asignado), por lo que se puede escribira = b = c = 0;asignaciones en cadena como esa.
  • Ejemplo:
    printf("Enter two integers: ");
    sum = add(num1, num2);

Sentencias de control de flujo

  • Las sentencias de control de flujo se utilizan para controlar el orden de ejecución de un programa, e incluyen la toma de decisiones condicional (if/else、switch) y los bucles (for、while、do-while). También están las sentencias de saltobreak、continue、gotoyreturn。
  • Usar adecuadamente las sentencias de control de flujo es clave para escribir programas con lógica clara; se debe evitar el abuso degotopara mantener la legibilidad del código.
  • Ejemplo:
    if (num1 > num2) {
        printf("num1 is greater than num2");
    }

Definición de funciones

  • La definición de una función incluye el cuerpo completo de la función y describe su implementación concreta. Una función se compone de tipo de retorno, nombre de función, lista de parámetros y cuerpo de función. Un buen diseño de funciones debe seguir el principio de "responsabilidad única": cada función debe hacer una sola cosa.
  • Las funciones en C no admiten sobrecarga; cada nombre de función debe ser único en el mismo ámbito. Las funciones pueden llamarse a sí mismas de forma recursiva.
  • Ejemplo:
    int add(int a, int b) {
        return a + b;
    }

Sentencia de retorno

  • returnLa sentencia `return` se utiliza para terminar la ejecución de una función y devolver el control, junto con el valor de retorno, al llamador.voidLas funciones de tipo `void` pueden usar un `return` sin valorreturn;para salir anticipadamente; también se puede omitirreturnla sentencia.
  • main()El valor de retorno de la función se pasa al sistema operativo,0normalmente indica éxito; se puede usar la macro estándarEXIT_SUCCESSyEXIT_FAILURE(definida en<stdlib.h>)。
  • Ejemplo:return 0;、return EXIT_SUCCESS;

Separadores

Los separadores se utilizan para delimitar sentencias, expresiones y bloques de código, ayudando al compilador a entender la estructura del programa. Los separadores comunes incluyen:

  • Coma,: se utiliza para separar múltiples elementos en declaraciones de variables, parámetros de funciones o listas de inicialización.
  • Punto y coma;: se utiliza para terminar una sentencia; es el separador más común en C.
  • Paréntesis:
    • Paréntesis redondos(): se utilizan para la lista de parámetros en llamadas a funciones, las condiciones en sentencias de control de flujo y para forzar el orden de evaluación de expresiones.
    • Llaves{}: se utilizan para definir el cuerpo de una función, bloques de código de control de flujo, y la inicialización de literales compuestos y arreglos/estructuras.
    • Corchetes[]: se utilizan para declarar arreglos y acceder a sus elementos (operación de subíndice).

En un programa C, el punto y coma;es el terminador de sentencias; cada sentencia debe terminar con un punto y coma, que indica el final de una entidad lógica. La falta de punto y coma es uno de los errores de sintaxis más comunes entre principiantes.

Por ejemplo, las siguientes son dos sentencias diferentes:

printf("Hello, World! \n");
return 0;

Un punto y coma por sí solo también puede actuar como una sentencia vacía, que no hace nada; se usa a menudo en ciertas estructuras de bucle:

while (condition);  // 空循环体,等待条件变化

Comentarios

C tiene dos formas de comentarios:

// comentario de una sola línea

con//El comentario de una línea que comienza con `//` (introducido en C99) va desde//hasta el final de la línea; puede ocupar una línea completa o colocarse al final de una línea de código.

/* comentario de una sola línea */

/* */Este tipo de comentario puede ser de una o varias líneas, y es adecuado para comentarios más largos, como la documentación de funciones o cabeceras de módulos.

Ejemplo

// Este es un comentario de una línea

/*
Esto es un comentario de varias líneas
Puede abarcar varias líneas
*/


int main() {
    // Imprimir un mensaje
    printf("Hello, World!\n");
    return 0;
}

Al usar comentarios, se deben tener en cuenta los siguientes puntos:

  • No se pueden anidar comentarios dentro de comentarios (/* /* */ */es ilegal).
  • Los comentarios no pueden aparecer dentro de literales de cadena o constantes de carácter.
  • Los comentarios están escritos para las personas; deben ser concisos y claros, explicando principalmente el “porqué” en lugar de “qué se hace”, ya que el código mismo debería expresar “qué se hace”.
  • Un buen hábito de comentar es una parte importante de la programación profesional, y facilita el mantenimiento del código y el trabajo en equipo.

Identificadores

Los identificadores son los nombres de variables, funciones, arreglos, tipos, etc., en un programa, definidos por el programador. Los identificadores se componen de letras (mayúsculas o minúsculas), dígitos y guiones bajos, pero el primer carácter debe ser una letra o un guion bajo, no puede ser un dígito.

Un identificador comienza con una letra A-Z o a-z o un guion bajo _, seguido de cero o más letras, guiones bajos y dígitos (0-9).

No se permiten caracteres de puntuación como @, $ y % dentro de los identificadores de C. C essensible a mayúsculas y minúsculasde programación. Por lo tanto, en C,Manpowerymanpowerson dos identificadores diferentes. A continuación se enumeran varios identificadores válidos:

mohd       zara    abc   move_name  a_123
myname50   _temp   j     a23b9      retVal

A continuación se presentan algunos ejemplos de identificadores inválidos y sus razones:

2abc        // 错误:以数字开头
my-name     // 错误:包含连字符 -
float       // 错误:与关键字重名
my name     // 错误:包含空格

Sugerencia de nomenclatura: los identificadores deben ser descriptivos y expresar claramente su propósito. Los estilos de nomenclatura comunes incluyen la notación con guiones bajos (my_variable) y la notación camelCase (myVariable), y en el mismo proyecto basta con mantener la coherencia. Los identificadores que comienzan con doble guion bajo__suelen estar reservados por el compilador o la biblioteca estándar, y deben evitarse en el código de usuario.

Constantes

Las constantes son valores fijos que no cambian durante la ejecución del programa. En C, hay principalmente dos formas de definir constantes: usandoconstla palabra clave o usando#definela definición de macro.

Las constantes pueden ser constantes enteras, constantes de punto flotante, constantes de carácter, constantes de enumeración, etc.:

const int MAX = 100;          // 整型常量
const float PI = 3.14159;    // 浮点型常量
const char NEWLINE = '\n';   // 字符常量(转义字符)

Los caracteres de escape de uso común en las constantes de carácter incluyen:

  • \n: salto de línea
  • \t: tabulación horizontal
  • \\: barra invertida
  • \': comilla simple
  • \0: carácter nulo (marca de fin de cadena)

Usandoconstlas constantes definidas tienen información de tipo, el compilador puede realizar la comprobación de tipos; en comparación con las#definemacros, es más seguro y es la forma recomendada a partir de C99.

Literales de cadena

Los literales de cadena son secuencias de caracteres entre comillas dobles, utilizados para representar datos de texto.

Los literales de cadena se almacenan en memoria como arreglos de caracteres, y al final se agrega automáticamente un carácter nulo\0(es decir, el terminador nulo), que marca el final de la cadena.

char greeting[] = "Hello, World!";  // 编译器自动计算长度(包含 \0)

A continuación se presentan algunos puntos importantes sobre los literales de cadena:

  • El literal "Hello" en realidad ocupa 6 bytes en memoria:'H'、'e'、'l'、'l'、'o'、'\0'。
  • Los literales de cadena se almacenan en un área de memoria de solo lectura y no se pueden modificar; si se necesita modificarlos, se deben copiar a un arreglo de caracteres.
  • Dos literales de cadena adyacentes son concatenados automáticamente por el compilador:"Hello, " "World!"es equivalente a"Hello, World!"。
  • El carácter'A'(constante de carácter) y la cadena"A"(literal de cadena) son diferentes; esta última contiene'A'y'\0'dos caracteres.

Operadores (Operators)

Los operadores se utilizan para realizar diversas operaciones, como operaciones aritméticas, lógicas, de comparación, etc. Los operadores actúan sobre operandos, forman expresiones y producen un resultado.

En C hay una gran variedad de operadores; los más comunes incluyen:

  • Operadores aritméticos:+, -, *, /, %(donde/realiza división entera para enteros,%obtiene el residuo).
  • Operadores relacionales:==, !=, >, <, >=, <=(devuelven 1 para verdadero y 0 para falso)
  • Operadores lógicos:&&(Y),||(O),!(NO), con evaluación de cortocircuito
  • Operadores de bits:&(Y a nivel de bits),|(O a nivel de bits),^(XOR a nivel de bits),~(complemento a nivel de bits),<<(desplazamiento a la izquierda),>>(desplazamiento a la derecha)
  • Operadores de asignación:=, +=, -=, *=, /=, %=(asignación compuesta, comoa += bes equivalente aa = a + b)
  • Operadores de incremento/decremento:++(incremento),--(decremento), con dos formas: prefijo (primero realiza la operación y luego toma el valor) y sufijo (primero toma el valor y luego realiza la operación).
  • Otros operadores:sizeof(calcula el tamaño en bytes de un tipo o variable),?:(operador ternario),&(obtener dirección),*(desreferenciar),->(acceder a miembro a través de puntero),.(acceder a miembro directamente)
int a = 5, b = 10;
int sum = a + b;           // 算术运算符 +,sum = 15
int isEqual = (a == b);   // 关系运算符 ==,isEqual = 0(假)
int result = a << 1;      // 位运算左移,result = 10(相当于 a * 2)
a++;                       // 后缀自增,a 变为 6
int max = (a > b) ? a : b; // 三目运算符,max = b = 10

Los operadores tienen precedencia y asociatividad: la precedencia determina el orden de las operaciones, y la asociatividad determina la dirección de evaluación de los operadores del mismo nivel. Cuando no esté seguro de la precedencia, se recomienda usar paréntesis para agrupar explícitamente y mejorar la legibilidad del código.

Palabras clave

La siguiente tabla enumera las palabras reservadas de C. Estas palabras reservadas no pueden usarse como nombres de constantes, variables u otros identificadores; tienen un significado sintáctico específico en el lenguaje C.

Palabra clave Descripción
autoDeclara variables automáticas (tipo de almacenamiento predeterminado para variables locales; rara vez se usa explícitamente en el C moderno)
breakSale del bucle o la sentencia switch actuales
caseEtiqueta de caso en una sentencia switch
charDeclara variables de tipo carácter o el tipo de retorno de una función (normalmente ocupa 1 byte)
constDefine constantes de solo lectura; el valor de una variable modificada por const no puede cambiarse
continueTermina la iteración actual del bucle y pasa directamente a la siguiente iteración
defaultRama predeterminada en una sentencia switch (se ejecuta cuando ningún case coincide)
doCuerpo del bucle do-while; el cuerpo del bucle se ejecuta al menos una vez
doubleDeclara variables de tipo punto flotante de doble precisión o el tipo de retorno de una función (normalmente ocupa 8 bytes)
elseRama negativa de una sentencia condicional (se usa junto con if)
enumDeclara un tipo de enumeración, utilizado para definir un conjunto de constantes enteras con nombre
externDeclara que una variable o función está definida en otro archivo o en otra parte de este archivo
floatDeclara variables de tipo punto flotante de precisión simple o el tipo de retorno de una función (normalmente ocupa 4 bytes)
forSentencia de bucle for, adecuada para situaciones donde se conoce el número de iteraciones
gotoSentencia de salto incondicional (debe usarse con cautela, puede reducir la legibilidad del código)
ifSentencia de condición
intDeclara variables de tipo entero o el tipo de retorno de una función (normalmente ocupa 4 bytes)
longDeclara variables de tipo entero largo o el tipo de retorno de una función
registerSugiere al compilador almacenar la variable en un registro para acelerar el acceso (los compiladores modernos suelen optimizarlo automáticamente)
returnSentencia de retorno de función, puede incluir un valor de retorno o no (funciones void)
shortDeclara variables de tipo entero corto o el tipo de retorno de una función (normalmente ocupa 2 bytes)
signedDeclara variables de tipo con signo (pueden representar números negativos; los enteros tienen signo por defecto)
sizeofCalcula el número de bytes que ocupa un tipo de datos o una variable (operador en tiempo de compilación)
staticDeclara variables estáticas (las variables estáticas locales extienden su vida útil hasta el final del programa; las variables estáticas globales se limitan al ámbito del archivo)
structDeclara un tipo de estructura, que combina datos de diferentes tipos en una sola entidad
switchSentencia de selección múltiple que salta al case correspondiente según el valor de una expresión
typedefDefine un nuevo alias para un tipo de datos existente, mejorando la legibilidad del código
unsignedDeclara variables de tipo sin signo (solo pueden representar números no negativos, con un rango mayor)
unionDeclara un tipo de unión, donde todos los miembros comparten el mismo espacio de memoria
voidDeclara que una función no tiene valor de retorno o no tiene parámetros; también se usa para declarar punteros sin tipovoid*
volatileDeclara que una variable puede ser modificada por factores externos al programa (como hardware o interrupciones); prohíbe al compilador optimizar las lecturas y escrituras de esa variable
whileSentencia de bucle while, adecuada para situaciones donde el número de iteraciones es desconocido pero la condición de terminación está clara

Palabras clave nuevas en C99

_Bool _Complex _Imaginary inline restrict

Las palabras clave nuevas de C99 se utilizan principalmente para: soporte de tipo booleano (_Bool), soporte de números complejos (_Complex、_Imaginary), optimización de funciones inline (inline), optimización de restricción de alias de punteros (restrict)。

Palabras clave nuevas en C11

_Alignas _Alignof _Atomic _Generic _Noreturn
_Static_assert _Thread_local      

Las palabras clave añadidas en C11 se utilizan principalmente para: control de alineación de memoria (_Alignas、_Alignof), soporte de operaciones atómicas y multihilo (_Atomic、_Thread_local), selección genérica (_Generic), aserción estática (_Static_assert) y para marcar funciones sin valor de retorno (_Noreturn)。


Espacios en blanco en C

Una línea que contiene solo espacios se denomina línea en blanco, y puede llevar comentarios; el compilador de C la ignora por completo.

En C, el espacio se usa para describir caracteres de espacio en blanco (tecla de espacio), tabulaciones (Tab), saltos de línea y comentarios. Los espacios separan las distintas partes de una sentencia, permitiendo que el compilador reconozca dónde termina un elemento de la sentencia (por ejemplo,int), dónde termina y dónde comienza el siguiente elemento. Por lo tanto, en la siguiente sentencia:

int age;

intyageDebe haber al menos un carácter de espacio entre ellos (normalmente un espacio en blanco), para que el compilador pueda distinguirlos. Por otro lado, en la siguiente sentencia:

fruit = apples + oranges;   // 获取水果的总数

fruity=, o=yapplesel carácter de espacio entre ellos no es necesario, pero para mejorar la legibilidad, puede agregar algunos espacios según sea necesario.

Los buenos hábitos de espaciado e indentación son una parte importante del código de alta calidad; se recomienda seguir las siguientes normas:

  • Use una indentación consistente (normalmente 4 espacios o 1 tabulación) para representar la jerarquía de los bloques de código.
  • Agregue espacios a ambos lados de los operadores (por ejemplo,a + b), para que las expresiones sean más legibles.
  • Agregue un espacio después de las comas (por ejemplo,int a, b, c;), distingue múltiples elementos.
  • Usa líneas en blanco apropiadamente para separar bloques de código lógicamente relacionados, mejorando la legibilidad general.
Otras extensiones