Vous êtes sur la page 1sur 13

Guía de Estilo para lenguaje C.

Propósito.

Este documento define un estilo de codificación en el lenguaje


de programación C a través de un conjunto de normas y recomendaciones. Se
pretende que este estilo ayude a construir programas correctos, entendibles y
fáciles de mantener.

En este documento, una "norma" es una regla que debe cumplirse


obligatoriamente; una "recomendación" es una regla válida en general, pero que
puede admitir o requerir excepciones.

2. Alcance.

Este documento trata exclisivamente del estilo de programación en lenguaje C en


cuanto a codificación. No trata cuestiones de diseño, organización funcional ni
otras que hacen a la buena construcción de los programas.

3. Organización de archivos.

Convención de nombres.

Se usarán las siguientes convenciones de nombres de archivos:

 código fuente en C: *.c


 archivos de encabezados: *.h
 archivos de prototipos de funciones: *.fp
 archivos Ingres: *.sc
 archivos de "make": Makefile
 surbrutina externa en C: *.xs
 biblioteca compartida: *.so

Archivos de código fuente.

Norma: Todos los archivos tendrán leyenda de derechos de autor.


Todos los archivos de código fuente tendrán la siguiene leyenda de derechos de
autor:
/* Copyright, 1998, Instituto de Ingenieria Electrica */
Recomendación: una función no ocupará más de 2 páginas.
Cuando una función ocupe más de dos páginas, debe considerarse su separación
en varias funciones, o colocar las subfunciones en módulos separados. Funciones
cortas y relacionadas pueden estar en un mismo archivo.

Norma: largo de línea <= 80 caracteres.


Las líneas de código no deben exceder de 80 caracteres. Las líneas largas deben
ser separadas en varios renglones, de modo que al imprimir el código resulte
legible. Se recomienda que las líneas de continuación sean indentadas. El largo
de línea incluye espacios al principio y comentarios en la misma línea del código.

Norma: Orden de las secciones.


El orden de las secciones de un programa es el siguiente:

Prólogo.
Debe indicar lo que hay en el archivo: propósito de los objetos contenidos,
sean éstos funciones, declaraciones de datos externos, definiciones u otros.
La descripción debe ser breve y específica; no debe tomar más trabalo
leerla que la revisión del código.

Inclusiones.
Archivos de encabezados incluídos. Si la inclusión no es obvia, debe
indicarse la razón con un comentario. Los archivos de
inclusión del sistema, como stdio.h, deben preceder los archivos de
inclusióndel usuario.

Definiciones.
Todas las definiciones que afectan todo el archivo.

Definiciones globales.
Declaraciones de datos globales (externos).

Funciones.
Las funciones se colocan al final en el orden más significativo posible.

Archivos de encabezados.

Recomendación: organización de archivos de encabezado.


Todas las funciones en un mismo archivo de encabezado deben estar
relacionadas a una misma función general. Dentro de un archivo de encabezado,
la funciones que realicen tareas relacionadas deben estar agrupadas en una misma
sección.
Recomendación: nombres de los archivos de encabezado.
Evitar nombres de archivos privados de encabezado que coincidan con nombres
de archivos públicos de encabezado. No usar nombes absolutos para archivos de
encabezado; colocarlos en su ubicación estándar o en el directorio corriente. La
opción de compilación relativa a inclusión de bibliotecas ("include-path") es la
mejor forma de manejar bibliotecas privadas extensas.

Norma: archivo de encabezado en el archivo de definición de la función.


Los archivos de encabezado que declaran funciones o variables externas deben
incluírse en el archivo que define la función o la variable para permitir
verificación de tipos.

Recomendación: no anidar archivos de encabezado.


Los archivos de encabezado no deben anidarse. El prólogo de cada archivo de
encabezado debe describir que otros archivos de encabezado deben incluírse para
que el actual archivode encabezado funcione. En casos extremos pueden incluírse
todas las sentencias de inclusión comunes en un nuevo archivo de inclusión.

4. Declaraciones de variables.

Norma: nombres de variables.


Todas las variables deben comenzar con letra minúscula. En los nombres
compuestos por varias palabras, cada palabra excepto la primera deben comenzar
com nayúscula, así: una_Variable.
Los nombres de punteros deben empezar con "p_", así: p_UnaVariable.
Los nombres de variables globales deben comenzar por "g_", así:
g_UnaVariable.
Los nombres definidos deben ir en mayúsculas separados por subrraya, así:
#define DIAS_SEMANA 7

Recomendación: no usar variables globales.


Se recomienda enfáticamente no usar variables globales. Excepcionalmente, se
admite el uso de variables globales para descargar las invocaciones a funciones.
Todo uso de variable global dentro de una función debe ser indicado en el
prólogo.

Norma: variables globales declaradas al principio del archivo.


Las variables globales deben declararse al principio del archivo, antes de las
declaraciones de funciones. Las variables que son globales sólo para las
funciones de un mismo archivo deben ser declaradas estáticas.
Norma: variables globales al principio de la función.
Las variables dentro de una función deben declararse al comienzo de la función

Norma: usar #define para constantes simbólicas.


Todas las cantidades que permanezcan constantes deben nombrarse con #define
y escribirse en mayúsculas, así:
#define MAX_CANALES 4096
Las constantes simbólicas que se usen en una única unidad de compilación deben
definirse al principio de esa unidad de compilación. Las constantes simbólicas de
alcance más general deben definirse y documentarse en archivos de encabezado
de alcance adecuado.

Norma: declaración explícita de +1 en largo de cadenas para '\0'.


El largo de arreglos de caracteres usados como cadenas y terminados por un
caracter nulo, deben definir su largo indicando explícitamente el "+1" para el
carater nulo de terminación.
#define LARGO_NOMBRE 20 + 1

Norma: declaración de estructuras.


Cada campo de una estructura debe declararse en un renglón separado. La
estructura debe tener un nombre en mayúsculas. La asignacion de una estructura
a una variable debe hacerse en una sentencia separada, así:
struct LIBRO {
char nombre[LARGO_NOMBRE];
char autor[LARGO_AUTOR];
long numero;
}

Recomendación: macros.
Los nombres de macros deben escribirse en mayúsculas. Incluír un comentario en
el mismo renglón de declaración de la macro. Las definiciones de macros deben
estar al principio del archivo, o en un archivo de encabezado. Colocar paréntesis
en torno a los parámetros en el texto de reemplazo, y en torno a todo el texto si es
posible, así:
#define SIGUIENTE(p) ((p)->_next)

5. Funciones.

Declaración de funciones.

Norma: valor de retorno declarados explícitamente.


La función debe devolver "void" si no se devuelve ningún valor.
Norma: lista de parámetros.
Si la lista de parámetros no cabe en un renglón, los renglones de continuación
deben estar indentados hasta el lugar donde comienza la lista de parámetros en el
primer renglón.
Una función que devuelve información por vía de sus parámetros debe devolver
en su nombre solamente información de estado.
Cada parámetro pasado a una función debe ocupar un renglón separado en la
declaración de la función, seguido de un corto comentario que describa su
función.

Norma: función estática.


Toda función que sólo sea llamada desde otras funciones en el mismo archivo
debe ser declarada estática.

Patrón para declaración de funciones.


void nom_func (int param1, /* comentario parámetro 1 */
long param2, /* comentario parámetro 2 */
double param3, /* comentario parámetro 3 */
char param4, /* comentario parámetro 4 */
{
printf("%d %ld %f %c\n", param1, param2, param3, param4);
return;
}

Norma: cuerpo de la función.


La llave de apertura "{" del cuerpo de la función debe estar a la izquierda en un
renglón separado o al final del renglón que introduce el bloque. El resto de la
función hasta la llave de cierre "}" debe estar indentada un paso.Un paso de
indentación es 2 o 3 espacios; no usar tabuladores.
En la función debe haber una única sentencia return con un parámetro si la
función no es void. Aún si la función no devuelve ningún valor, es buena práctica
incluir una sentencia return.
La llave de cierre "}" debe estar a la izquierda y en un renglón separado.

Norma: prototipo de la función.


Deben crearse prototipos para todas las funciones. Si los prototipos de las
funciones residen en un archivo separado, este archivo debe tener extensión ".fp".

6. Comentarios.

Recomendación: patrón para encabezado de archivos y funciones.


Si el archivo contiene funciones relacionadas de tal modo que la modificación de
una requerirá probablemente la modificación de varias de las otras, se colocará al
principio del archivo el siguiente encabezado, y al principio de cada función un
comentario breve que la describa.
/*=================================================================
| Archivo: nombre de archivo
| Propósito:
| Documentación: (si corresponde)
|
| Revisiones:
| Fecha Nombre Revisión
| -------- --------------- ----------------------------------------
| 02-03-98 Juan Perez Creado
|
===================================================================*/

Si las funciones del archivo no están particularmente relacionadas, se colocará el


siguiente encabezado al principio de cada función.
/*=================================================================
| Función: nombre de función
| Propósito:
| Método: (si corresponde)
|
| Revisiones:
| Fecha Nombre Revisión
| -------- --------------- ----------------------------------------
| 02-03-98 Juan Perez Creado
|
===================================================================*/

Recomendación: comentarios en las funciones.


Los comentarios dentro del cuerpo de las funciones deben restringirse a bloques
de comentario que precedan bloques cohesivos. Describirán los propósitos del
bloque en el cumplimiento de una tarea cohesiva. El uso de nombres
significativos en variables y funciones minimizan la necesidad de comentarios.

Norma: bloques de comentario.


Los bloques de comentario deben estar precedidos y seguidos por un renglón en
blanco. En bloques de comentario de varios renglones, los renglones siguientes al
primero deben tener un caracter barra vertical "|" al comienzo del renglón. Tal
como es requerido, el primer renglón comenzará con "/*" y el último finalizará
con "/*". El bloque de comentario debe indentarse al mismo nivel que el bloque
de código que comenta.
/*===================================================================
| Este es un ejemplo de bloque de comentario. Nótense las líneas de
| guiones en el primer y último renglón y las barras verticales al
| principio de cada línea de texto. Recuérdese además que deba haber
| un renglón en blanco antes y otro después del bloque de comentario.
=====================================================================*/
7. Sentencias.

Norma: una sentencia por renglón.


Cada sentencia debe ocupar un renglón. "a = 2; b =3;" no es permitido.

Recomendación: no usar sentencias goto ni continue.


Se recomienda enfáticamente no usar sentencias goto ni continue. El uso
de break debe limitarse a las sentencias switch, cuando se requiera. Se prefiere el
siguiente código
estado = EXITO;
i = 0;
while ((cadena[i] != NULL && (estado == EXITO)) {
transmitCar(cadena[i], &estado);
}

en lugar de
estado = EXITO;
i = 0;
while (cadena[i] != NULL) {
transmitCar(cadena[i], &estado);
if (estado != EXITO) break;
}

Recomendación: evitar la sentencia exit.


Se recomienda evitar el uso de la sentencia exit, excepto para el manejo de
errores.

Recomendación: máximo 4 niveles de anidamiento en estructuras de control.


El anidamiento de sentencias if, for, while, etc., no debe superar los 4 niveles. Si
se requieren más deberá considerarse el uso de una función en alguno de los
niveles superiores.

Norma: sentencias nulas.


Las sentencias nulas requieren comentario.Por ejemplo, si el caso default de una
sentencia case no hace nada, colocar igualmente el rótulo default y un
comentario tal como
/* no hay acción */
seguido de la sentencia break.
El cuerpo nulo de un for o un while debe estar en un renglón separado y contener
un comentario que asegure que el cuerpo es intencionalmente nulo, así
while (*destino++, *origen++)
; /* vacío */
Norma: comentario para falta de break en switch.
Cuando se pretende que un caso de una sentencia case caiga en el siguiente caso,
la falta de break en la sentencia anterior debe ser notada con un comentario.
switch (queIsotopo) {
case PU239: /* misma acción que PU240, sin break */
case PU240:
procesoPlutonio();
break;
default:
break; /* si no es PU239 ni PU240 no hay acción */
}

Norma: bloques de sentencias.


La llave de apertura "{" de los bloques de código debe estar al final de la
sentencia de control del bloque o a renglón seguido alineado con la primera letra
de la setnencia de control. El cuerpo del bloque debe estar indentado un paso
desde la sentencia de control. La llave de cierre "}" debe estar en renglón aparte
con la misma indentación que la sentencia de contro. Por ejemplo:
if(primero < ultimo) {
resultUno = primero / 2;
resultDos = ultimo / 2;
}
else {
resultUno = ultimo / 2;
resultDos = primero /2;
}
do
{
estado = haceAlgo();
} while (estado == EXITO);

Recomendación: bloque con sentencia única.


Se aconseja encerrar entre llaves "{...}" aún las sentencias únicas de las
sentencias de control:

if (unaCondicion == CIERTO) {

variable Uno = variableDOS;

Norma: operadores decremento e incremento sólo en sufijo.


Usar los operadores de incremento "++" y decremento "--" sólo como sufijo, y no
como parte de otra sentencia. Se prefiere esta forma
while (cadena[i] != NULL) {
haceAlgo();
i++;
}

en lugar de
while (cadena[i++] != NULL) {
haceAlgo();
}

Norma: desvío en llamado a función.


Cuando un desvío se base en el resultado de un llamado a función, el llamado a
función debe estar un renglón aparte. La forma
p_FileHandle = fopen("unArchivo", READ_ONLY);
if (p_FileHandle == NULL) {
printf("No pudo abrirse archivo; fin de programa");
terminaAplicacion()
}
else {
haceAlgo();
}

resulta más fácil de entender que


if ((fileHandle = open("unArchivo", READ_ONLY)) == NULL) {
printf("No pudo abrirse archivo; fin de programa");
terminaAplicacion()
}
else {
haceAlgo();
}

Norma: evitar efectos secundarios.


Las expresiones no deben producir internamente efectos secundarios. Evitar
sentencias tales como while (cadena[i++] != 0).

Norma: no usar el valor verdadero por defecto en las pruebas.


No usar el valo no nulo por defecto. Usar comparaciones explícitas aún si el
valor de comparación no cambia nunca. La forma
if (func() != FALSO)

es preferible a
if (func())

8. Operadores.
Norma: usar espacios entre operadores binarios.
Todos los operadores que tomen dos parámetros deben tener un espacio antes y
otro después del operador.

Norma: no poner espacio después de un operador unario.


No debe haber espacio que separe un operador unario del objeto afectado.

Recomendación: evitar el uso del operador de comparación condicional.


Se recomienda evitar el uso del comparador condicional ternario "?"; se lo
permite en macros.
if (abc > xyz) {
zUno = abc;
}
else {
zUno = xyz;
}

es más fácil de leer que


zUno = (abc > xyz) ? abc : xyz

Norma: usar paréntesis para evitar ambigüedades de precedencia.


Deben usarse paréntesis para eliminar ambigüedades que puedan surgir por
desconocimiento de la precedencia de operadores. Por ejemplo, al incrementar la
variable apuntada por el puntero p_NumVeces, escribir (*p_NumVeces)++
asegura que se está incrementando el contenido de la dirección y no el puntero.

9. Espacios en blanco.

Recomendación: uso de espacios en blanco para mejorar la legilibilidad.


Usar a discreción los espacios en blanco horizontales y verticales para hacer más
legible el código. Los renglones en blanco y la indentación deben reflejar la
estructura de bloques del código.

Norma: operadores condicionales en renglones separados.


Una lista de varios operadores condicionales debe separarse en renglones
diferentes. El código
if (nodo->sigte == NULL && totalCuenta < pedido
&& pedido <= MAXLOTE && servActivo(esteIngreso)) {
...

se escribe mejor así:


if (nodo->sigte == NULL
&& totalCuenta < pedido
&& pedido <= MAXLOTE
&& servActivo(esteIngreso))
{
...

Análogamene, los lazos for complicados deben separarse en líneas diferentes:


for (corr = *listp, rastro = pList;
corr != NULL;
rastro = &(corr->sigte), corr = corr->sigte) {
haceAlgo();
haceOtraCosa();
}

Norma: espaciado de paréntesis.


Las palabras claves seguidas de expresiones entre paréntesis no deben quedar
separadas del paréntesis izquierdo de la expresión. Debe colocarse un espacio
después de la coma en las listas de argumentos.

10. Constantes.

Norma: nombres de constantes simbólicas en mayúscula.


Las constantes simbólicas deben escribirse en mayúscula. Por ejemplo, CIERTO.

Recomendación: consistencia en la definición de constantes.


Las constantes deben definirse en forma consistente con su uso; por ejemplo,
escribir 540.0 en lugar de asumir una conversión forzada de 540.

11. Compilación condicional.

La compilación condicional sólo debe usarse para controlar la compilación de


código dependiente de máquina, fijando opciones de tiempo de compilación, o
para depuración.

Norma: compilación condicional por defecto.


La compilación condicional de código dependiente de máquina debe llevar, por
defecto, a error. La compilación condicional de código destinado a optimización
debe llevar, por defecto, a código no optimizado.

Recomendación: compilación condicional.


Siempre que sea posible, colocar el código de compilación condicional en un
archivo de encabezado en lugar de en el programa principal. Las unidades de
compilación condicional deben encerrarse entre llaves de a una característica.
12. Portabilidad.

Norma: código de máquina en un archivo separado.


Colocar todo el código de máquina en un archivo separado del código
independiente de máquina. El código dependiente de máquina debe estar puesto
con #ifdef para que salga un mensaje de error significativo si el código es
compilado en una máquina diferente.

Recomendación: uso del código de máquina.


El código de máquina debe usarse solamente cuando sea estrictamente necesario.
Intentar escribir como independientes de máquina todas las rutinas que soporten
código dependiente de máquina.

Recomendaciones generales para la portabilidad.


Recordar que los largos de los tipos nativos puede variar entre plataformas,
especialmente punteros y enteros. La presición y formato de almacenamiento del
tipo float también puede variar entre plataformas.
No asumir que el programa será siempre ejecutado en la máquina para la cual fue
diseñado originalmente.

13. ANSI C.

Norma: código compatible ANSI.


Todo el código debe conformar el estándar de ANSI para lenguaje C.

14. Varios.

Norma: verificar siempre el valor de retorno de las funciones.


Verificar siempre el valor de retorno de las funciones que devuelven valores
especiales en caso de error.

Recomendación: usar funciones de biblioteca siempre que sea posible.


Usar funciones de biblioteca siempre que sea posible. No reinventar la rueda.

15. Conclusión.

Las recomendaciones y normas expuestas en esta guía deben seguirse de buena


fé, recordando que siempre se está trabajando, aunque sea potencialmente, en un
grupo de trabajo.

16. Referencias.
 "C Style and Coding Standards for the SDM Project", Los Alamos
National Laboratory, Univesity of California, 1996.