Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

String-handling practices in C [closed]

Tags:

I'm starting a new project in plain C (c99) that is going to work primarily with text. Because of external project constraints, this code has to be extremely simple and compact, consisting of a single source-code file without external dependencies or libraries except for libc and similar ubiquitous system libraries.

With that understanding, what are some best-practices, gotchas, tricks, or other techniques that can help make the string handling of the project more robust and secure?

like image 560
tylerl Avatar asked Jan 02 '11 20:01

tylerl


People also ask

How are strings handled in C?

Strings in C language are an array of characters ended with null characters ('\0'). The null character at the end of a string indicates its end and the strings are always enclosed by double quotes. In C language characters are enclosed by single quotes.

How many string functions are there in C?

The nine most commonly used functions in the string library are: strcat - concatenate two strings. strchr - string scanning operation. strcmp - compare two strings.

What is string in C with example?

In C programming, a string is a sequence of characters terminated with a null character \0 . For example: char c[] = "c string"; When the compiler encounters a sequence of characters enclosed in the double quotation marks, it appends a null character \0 at the end by default.


1 Answers

Without any additional information about what your code is doing, I would recommend designing all your interfaces like this:

size_t foobar(char *dest, size_t buf_size, /* operands here */) 

with semantics like snprintf:

  • dest points to a buffer of size at least buf_size.
  • If buf_size is zero, null/invalid pointers are acceptable for dest and nothing will be written.
  • If buf_size is non-zero, dest is always null-terminated.
  • Each function foobar returns the length of the full non-truncated output; the output has been truncated if buf_size is less than or equal to the return value.

This way, when the caller can easily know the destination buffer size that's required, a sufficiently large buffer can be obtained in advance. If the caller cannot easily know, it can call the function once with either a zero argument for buf_size, or with a buffer that's "probably big enough" and only retry if you ran out of space.

You can also make a wrapped version of such calls analogous to the GNU asprintf function, but if you want your code to be as flexible as possible I would avoid doing any allocation in the actual string functions. Handling the possibility of failure is always easier at the caller level, and many callers can ensure that failure is never a possibility by using a local buffer or a buffer that was obtained much earlier in the program so that the success or failure of a larger operation is atomic (which greatly simplifies error handling).

like image 114
R.. GitHub STOP HELPING ICE Avatar answered Sep 20 '22 15:09

R.. GitHub STOP HELPING ICE