Saltar a contenido

Última actualización:2026-10-12

Chuleta de desarrollo con libcurl en C++

Unificar el estilo de código ayuda a la colaboración en equipo y a la revisión de código; en la industria se usa mucho el estilo de google. En esta sección algo distinto: veamos cómo es la guía de estilo del equipo de curl, una herramienta que usamos a menudo.

Sobre curl, en pocas palabras: es muy útil para transferir datos en la línea de comandos o en scripts; seguro que la habéis usado, y su código fuente puede consultarse en github

https://github.com/curl/curl

A continuación veamos la guía de desarrollo en C de curl desde varios ángulos.

Nomenclatura

Los nombres de funciones y variables nuevas deben ser lógicos, comprensibles y nombrados según su propósito.

Las funciones locales a un archivo deben declararse estáticas y se recomiendan nombres en minúsculas.

Sangría

Usa solo espacios para la sangría, nunca tabuladores. Usa dos espacios por cada nueva llave de apertura.

if(something_is_true) {
  while(second_statement == fine) {
    moo();
  }
}

Comentarios

Como se escribe código C89, no se permiten comentarios //. No se introdujeron hasta el estándar C99. Usa solo /* comentarios */.

/* 这是一个注释 */

Líneas largas

El código fuente de curl nunca debe superar las 79 columnas; incluso en la era de las pantallas grandes y de alta resolución siguen existiendo dos razones para mantenerlo:

  1. Las columnas más estrechas se leen más fácilmente que las anchas. Hay una razón por la que los periódicos llevan décadas, incluso siglos, usando columnas.
  2. Las columnas más estrechas permiten a los desarrolladores mostrar más fácilmente varios fragmentos de código en paralelo en distintas ventanas. Permiten mostrar dos o tres ventanas de código fuente lado a lado en la misma pantalla, además de varias terminales y ventanas de depuración.

Llaves

En las expresiones if/while/do/for escribimos la llave de apertura en la misma línea que la palabra clave, y la llave de cierre al mismo nivel de sangría que la palabra clave inicial. Así:

if(age < 40) {
  /* 显然是年轻人 */
}

Si solo contienen una sentencia de una línea, pueden omitirse las llaves:

if(!x)
  continue;

Para las funciones, la llave de apertura debe escribirse en una línea aparte:

int main(int argc, char **argv)
{
  return 1;
}

'else' en la línea siguiente

Al añadir una cláusula else a una expresión condicional usando llaves, la añadimos en una nueva línea tras la llave de cierre. Así:

if(age < 40) {
  /* 显然是年轻人 */
}
else {
  /* 可能是脾气暴躁的 */
}

Sin espacio antes del paréntesis

Al usar expresiones if/while/do/for, no debe haber espacio entre la palabra clave y el paréntesis de apertura. Así:

while(1) {
  /* 永远循环 */
}

Usar condiciones booleanas

En las condiciones de if/while preferimos comprobar el valor de la condición, como booleanos contra TRUE o FALSE, punteros contra NULL o != NULL, y enteros contra cero o distinto de cero, en lugar de:

result = do_something();
if(!result) {
  /* 出现了问题 */
  return result;
}

No asignar dentro de las condiciones

Para aumentar la legibilidad y reducir la complejidad de las condiciones, evita asignar variables en condiciones de if/while. Se desaconseja este estilo:

if((ptr = malloc(100)) == NULL)
  return NULL;

En su lugar se favorece una expresión más clara:

ptr = malloc(100);
if(!ptr)
  return NULL;

Cada bloque en una línea nueva

Nunca se escriben varias sentencias en la misma línea, ni siquiera en condiciones if() cortas.

if(a)
  return TRUE;
else if(b)
  return FALSE;

Nunca así:

if(a) return TRUE;
else if(b) return FALSE;

Espacios alrededor de los operadores

Usa espacios a ambos lados de los operadores en las expresiones C. Se exceptúan los operadores de sufijo (), [], ->, ., ++, -- y los unarios +, -, !, ~, &, que no deben llevar espacio.

Ejemplo:

bla = func();
who = name[0];
age += 1;
true = !false;
size += -2 + 3 *

 (a + b);
ptr->member = a++;
struct.field = b--;
ptr = &address;
contents = *pointer;
complement = ~bits;
empty = (!*string) ? TRUE : FALSE;

Sin paréntesis en el valor de retorno

No se añaden paréntesis extra en la sentencia 'return':

int works(void)
{
  return TRUE;
}

Paréntesis en el argumento de sizeof

Al usar el operador sizeof en el código, preferimos poner paréntesis alrededor de su argumento:

int size = sizeof(int);

Alineación de columnas

Algunas sentencias no pueden completarse en una sola línea: porque la línea es demasiado larga, porque la sentencia es difícil de leer o por otras guías de estilo de las anteriores. En esos casos, la sentencia ocupa varias líneas.

Si una línea de continuación forma parte de una expresión o subexpresión, debes alinearla en la columna adecuada para que se vea con claridad de qué parte de la sentencia se trata. Los operadores no deben iniciar una línea de continuación. En los demás casos, sigue la guía de sangría de 2 espacios. A continuación, algunos ejemplos de libcurl:

if(Curl_pipeline_wanted(handle->multi, CURLPIPE_HTTP1) &&
   (handle->set.httpversion != CURL_HTTP_VERSION_1_0) &&
   (handle->set.httpreq == HTTPREQ_GET ||
    handle->set.httpreq == HTTPREQ_HEAD))
  /* 没有要求 HTTP/1.0 并且是 GET 或 HEAD 请求 */
  return TRUE;

Si no hay paréntesis, usa la sangría por defecto:

data->set.http_disable_hostname_check_before_authentication =
  (0 != va_arg(param, long)) ? TRUE : FALSE;

En las llamadas a función, usa el paréntesis de apertura:

if(option) {
  result = parse_login_details(option, strlen(option),
                               (userp ? &user : NULL),
                               (passwdp ? &passwd : NULL),
                               NULL);
}

Alineado con el paréntesis "abierto en curso":

DEBUGF(infof(data, "Curl_pp_readresp_ %d bytes of trailing "
             "server response left\n",
             (int)clipamount));

Código dependiente de la plataforma

Usa #ifdef HAVE_FEATURE para el código condicional. Evitamos comprobar sistemas operativos o hardware concretos en líneas #ifdef. HAVE_FEATURE lo debe generar el script configure en sistemas tipo Unix, y en otros sistemas van fijados en sus archivos config-[system].h.

También animamos a usar, al compilar libcurl, macros o funciones que puedan estar vacías o definidas como constantes, para que el código sea transparente. Como en este ejemplo, donde la función magic() funciona de un modo u otro según las condiciones de la compilación:

#ifdef HAVE_MAGIC
void magic(int a)
{
  return a + 2;
}
#else
#define magic(x) 1
#endif

int content = magic(3);

No hacer typedef de estructuras

Aunque pueden usarse estructuras, no les hagas typedef. Identifícalas con la forma struct name:

struct something {
   void *valid;
   size_t way_to_write;
};
struct something instance;

No así:

typedef struct {
   void *wrong;
   size_t way_to_write;
} something;
something instance;

Este artículo está traducido de: https://curl.se/dev/code-style.html

Nota

Este artículo es una chuleta de desarrollo; se recomienda combinarlo con la documentación oficial de libcurl y con la investigación de códigos de error de proyectos concretos.

Temas relacionados

Comentarios