Last updated:2026-10-12
libcurl C++ Development Notes¶
A unified code style helps team collaboration and code review. The industry mostly uses Google's style; this section offers something different — let's see what the code conventions of the curl team look like, a tool most of us use a lot.
To say a few words about curl: it is very useful for transferring data on the command line or in scripts, and you have surely used it. Its source implementation can be viewed on GitHub:
Below let's look at curl's C language development conventions from several aspects.
Naming¶
New function and variable names should be logical, understandable, and named according to their purpose.
File-local functions should be declared static; lowercase names are recommended.
Indentation¶
Use only spaces for indentation, never tabs. Use two spaces for each new open brace.
Comments¶
Since C89 code is being written, // comments are not allowed. They were not introduced until the C99 standard. Use only /* comments */.
Long Lines¶
Source code in curl should never exceed 79 columns. Even in this age of modern large screens and high resolutions, there are still two reasons to keep this:
- Narrow columns are easier to read than wide ones. There is a reason newspapers have used columns for decades and even centuries.
- Narrower columns make it easier for developers to display multiple code snippets side by side in different windows. It allows two or three source code windows to be shown side by side on the same screen — along with multiple terminal and debug windows.
Braces¶
In if/while/do/for expressions, we write the open brace on the same line as the keyword, and then put the closing brace on a line at the same indentation level as the initial keyword. Like this:
If they contain only a single one-line statement, the braces can be omitted:
For functions, the open brace should be written on its own line:
'else' on the Next Line¶
When adding an else clause to a conditional expression using braces, we add it on a new line after the closing brace. Like this:
No Space Before Parentheses¶
When using if/while/do/for expressions, there should be no space between the keyword and the open parenthesis. Like this:
Use Boolean Conditions¶
In if/while conditions we prefer testing the condition's value — booleans against TRUE or FALSE, pointers against NULL or != NULL, and integers against zero or non-zero — rather than:
No Assignments in Conditions¶
For readability and to reduce the complexity of conditions, avoid assigning variables inside if/while conditions. This style is frowned upon:
Instead, expressing it more clearly is encouraged:
New Block on a New Line¶
Multiple statements are never written on the same line — not even short if() conditions are an exception.
Never like this:
Spaces Around Operators¶
Please use spaces on both sides of operators in C expressions. Exceptions are the postfix (), [], ->, ., ++, -- and unary +, -, !, ~, & operators, which should have no spaces.
Examples:
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;
No Parentheses Around Return Values¶
Do not add extra parentheses in 'return' statements:
Parenthesize the sizeof Argument¶
When using the sizeof operator in code, we prefer parentheses around its argument:
Column Alignment¶
Some statements cannot be completed on a single line — because the line is too long, the statement is too hard to read, or because of the other style guidelines above. In such cases the statement spans multiple lines.
If a continuation line is part of an expression or sub-expression, you should align it at the appropriate column so it is clear which part of the statement it belongs to. Operators should not start continuation lines. In other cases, follow the 2-space indentation guideline. Here are some examples from 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;
Without parentheses, use the default indentation:
data->set.http_disable_hostname_check_before_authentication =
(0 != va_arg(param, long)) ? TRUE : FALSE;
For function calls, use the open parenthesis:
if(option) {
result = parse_login_details(option, strlen(option),
(userp ? &user : NULL),
(passwdp ? &passwd : NULL),
NULL);
}
Aligned with the "currently open" parenthesis:
DEBUGF(infof(data, "Curl_pp_readresp_ %d bytes of trailing "
"server response left\n",
(int)clipamount));
Platform-Specific Code¶
Use #ifdef HAVE_FEATURE for conditional code. We avoid checking for specific operating systems or hardware in #ifdef lines. HAVE_FEATURE should be generated by the configure script for Unix-like systems, and they are hardcoded in the config-[system].h files on other systems.
We also encourage using macros/functions that may be empty or defined as constants when libcurl is built, to make the code seamless. Like this example, where the magic() function works differently depending on build-time conditions:
#ifdef HAVE_MAGIC
void magic(int a)
{
return a + 2;
}
#else
#define magic(x) 1
#endif
int content = magic(3);
Do Not typedef Structs¶
Although structs can be used, do not typedef them. Refer to them using the struct name form:
Not like this:
This article is translated from: https://curl.se/dev/code-style.html
Note
This article is a development memo; it is recommended to consult the official libcurl documentation together with your project's specific error codes for troubleshooting.
Related Topics¶
- Six Ways to Split Strings in C++ | C++那些事
- CPython Extension Development Notes | C++那些事
- How to Read Open Source C++ Code | C++那些事
- An Interesting Piece of C++ Code | C++那些事
- Printing 1-100 in C++ Without Loops | C++那些事