C: Expand documentation of strncpy, strncat
Also fixes the description of strncat.
This commit is contained in:
parent
78ee39cce1
commit
587753aceb
5 changed files with 131 additions and 11 deletions
|
@ -249,26 +249,103 @@
|
|||
</example>
|
||||
</section>
|
||||
<section id="sect-Defensive_Coding-C-Libc-strncpy">
|
||||
<title><function>strncpy</function> and related functions</title>
|
||||
<title><function>strncpy</function></title>
|
||||
<para>
|
||||
There are other functions which operator on NUL-terminated
|
||||
strings and take a length argument which affects the number of
|
||||
bytes written to the destination: <function>strncpy</function>,
|
||||
<function>strncat</function>, and <function>stpncpy</function>.
|
||||
These functions do not ensure that the result string is
|
||||
NUL-terminated. For <function>strncpy</function>,
|
||||
NUL termination can be added this way:
|
||||
The <function>strncpy</function> function does not ensure that
|
||||
the target buffer is NUL-terminated. A common idiom for
|
||||
ensuring NUL termination is:
|
||||
</para>
|
||||
<informalexample>
|
||||
<xi:include href="snippets/String-Functions-strncpy.xml"
|
||||
xmlns:xi="http://www.w3.org/2001/XInclude" />
|
||||
</informalexample>
|
||||
<para>
|
||||
Another approach uses the <function>strncat</function>
|
||||
function for this purpose:
|
||||
</para>
|
||||
<informalexample>
|
||||
<xi:include href="snippets/String-Functions-strncat-as-strncpy.xml"
|
||||
xmlns:xi="http://www.w3.org/2001/XInclude" />
|
||||
</informalexample>
|
||||
</section>
|
||||
<section id="sect-Defensive_Coding-C-Libc-strncat">
|
||||
<title><function>strncat</function></title>
|
||||
<para>
|
||||
The length argument of the <function>strncat</function>
|
||||
function specifies the maximum number of characters copied
|
||||
from the source buffer, excluding the terminating NUL
|
||||
character. This means that the required number of bytes in
|
||||
the destination buffer is the length of the original string,
|
||||
plus the length argument in the <function>strncat</function>
|
||||
call, plus one. Consequently, this function is rarely
|
||||
appropriate for performing a length-checked string operation,
|
||||
with the notable exception of the <function>strcpy</function>
|
||||
emulation described in <xref
|
||||
linkend="sect-Defensive_Coding-C-Libc-strncpy"/>.
|
||||
</para>
|
||||
<para>
|
||||
To implement a length-checked string append, you can use an
|
||||
approach similar to <xref
|
||||
linkend="ex-Defensive_Coding-C-String-Functions-snprintf-incremental"/>:
|
||||
</para>
|
||||
<informalexample>
|
||||
<xi:include href="snippets/String-Functions-strncat-emulation.xml"
|
||||
xmlns:xi="http://www.w3.org/2001/XInclude" />
|
||||
</informalexample>
|
||||
<para>
|
||||
In many cases, including this one, the string concatenation
|
||||
can be avoided by combining everything into a single format
|
||||
string:
|
||||
</para>
|
||||
<informalexample>
|
||||
<xi:include href="snippets/String-Functions-strncat-merged.xml"
|
||||
xmlns:xi="http://www.w3.org/2001/XInclude" />
|
||||
</informalexample>
|
||||
<para>
|
||||
But you should must not dynamically construct format strings
|
||||
to avoid concatenation because this would prevent GCC from
|
||||
type-checking the argument lists.
|
||||
</para>
|
||||
<para>
|
||||
It is not possible to use format strings like
|
||||
<literal>"%s%s"</literal> to implement concatenation, unless
|
||||
you use separate buffers. <function>snprintf</function> does
|
||||
not support overlapping source and target strings.
|
||||
</para>
|
||||
</section>
|
||||
<section>
|
||||
<title><function>strlcpy</function> and
|
||||
<function>strlcat</function></title>
|
||||
<para>
|
||||
Some systems support <function>strlcpy</function> and
|
||||
<function>strlcat</function> functions which behave this way,
|
||||
but these functions are not part of GNU libc. Using
|
||||
<function>snprintf</function> with a suitable format string is a
|
||||
simple (albeit slightly slower) replacement.
|
||||
but these functions are not part of GNU libc.
|
||||
<function>strlcpy</function> is often replaced with
|
||||
<function>snprintf</function> with a <literal>"%s"</literal>
|
||||
format string. See <xref
|
||||
linkend="sect-Defensive_Coding-C-Libc-strncpy"/> for a caveat
|
||||
related to the <function>snprintf</function> return value.
|
||||
</para>
|
||||
<para>
|
||||
To emulate <function>strlcat</function>, use the approach
|
||||
described in <xref
|
||||
linkend="sect-Defensive_Coding-C-Libc-strncat"/>.
|
||||
</para>
|
||||
</section>
|
||||
<section>
|
||||
<title>ISO C11 Annex K *<function>_s</function> functions</title>
|
||||
<para>
|
||||
ISO C11 adds another set of length-checking functions, but GNU
|
||||
libc currently does not implement them.
|
||||
</para>
|
||||
</section>
|
||||
<section>
|
||||
<title>Other <function>strn</function>* and
|
||||
<function>stpn</function>* functions</title>
|
||||
<para>
|
||||
GNU libc contains additional functions with different variants
|
||||
of length checking. Consult the documentation before using
|
||||
them to find out what the length actually means.
|
||||
</para>
|
||||
</section>
|
||||
</section>
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
<?xml version='1.0' encoding='utf-8' ?>
|
||||
<!DOCTYPE programlisting PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
|
||||
]>
|
||||
<!-- Automatically generated file. Do not edit. -->
|
||||
<programlisting language="C">
|
||||
buf[0] = '\0';
|
||||
strncpy(buf, data, sizeof(buf) - 1);
|
||||
</programlisting>
|
|
@ -0,0 +1,9 @@
|
|||
<?xml version='1.0' encoding='utf-8' ?>
|
||||
<!DOCTYPE programlisting PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
|
||||
]>
|
||||
<!-- Automatically generated file. Do not edit. -->
|
||||
<programlisting language="C">
|
||||
char buf[10];
|
||||
snprintf(buf, sizeof(buf), "%s", prefix);
|
||||
snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "%s", data);
|
||||
</programlisting>
|
|
@ -0,0 +1,7 @@
|
|||
<?xml version='1.0' encoding='utf-8' ?>
|
||||
<!DOCTYPE programlisting PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
|
||||
]>
|
||||
<!-- Automatically generated file. Do not edit. -->
|
||||
<programlisting language="C">
|
||||
snprintf(buf, sizeof(buf), "%s%s", prefix, data);
|
||||
</programlisting>
|
|
@ -68,5 +68,24 @@ main(void)
|
|||
//-
|
||||
assert(strlen(buf) == 9);
|
||||
assert(strncmp(buf, data, 9) == 0);
|
||||
//+ C String-Functions-strncat-as-strncpy
|
||||
buf[0] = '\0';
|
||||
strncpy(buf, data, sizeof(buf) - 1);
|
||||
//-
|
||||
}
|
||||
{
|
||||
const char *const prefix = "prefix";
|
||||
const char *const data = " suffix";
|
||||
|
||||
//+ C String-Functions-strncat-emulation
|
||||
char buf[10];
|
||||
snprintf(buf, sizeof(buf), "%s", prefix);
|
||||
snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "%s", data);
|
||||
//-
|
||||
puts(buf);
|
||||
//+ C String-Functions-strncat-merged
|
||||
snprintf(buf, sizeof(buf), "%s%s", prefix, data);
|
||||
//-
|
||||
puts(buf);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue