https://en.cppreference.com/w/cpp/string/byte/strncat
https://en.cppreference.com/w/cpp/string/byte/strncpy
这是一个 C++(哈哈哈)示例,说明了区别:
https://wandbox.org/permlink/igKe0CtdyuMw1JHL
#include <iostream>
#include <cstring>
#include <cassert>
//////////////////////////////////////////////////////////
// using strncat
// https://en.cppreference.com/w/cpp/string/byte/strncat
template <std::size_t N>
inline void safestrcpy1(char *dest, const char *src)
{
constexpr std::size_t count = N-1;
dest[0] = '\0';
strncat(dest, src, count); // at most count characters are copied from string src;
// and then a terminating null character '\0' is written if it was not yet encountered
}
template <std::size_t N>
inline void safestrcpy1(char (&dest)[N], const char *src)
{
safestrcpy1<N>(&dest[0], src);
}
//////////////////////////////////////////////////////////
// using strncpy
// https://en.cppreference.com/w/cpp/string/byte/strncpy
template <std::size_t N>
inline void safestrcpy2(char *dest, const char *src)
{
constexpr std::size_t count = N-1;
strncpy(dest, src, count); // null termination '\0' is only written if it occurs somewhere within src[0] .. src[count-1]
// if it occurs at src[i] and i < count, then dest[i+1], dest[i+2], ... dest[count-1] are also set to '\0'.
dest[count] = '\0'; // ensure null termination
}
template <std::size_t N>
inline void safestrcpy2(char (&dest)[N], const char *src)
{
safestrcpy2<N>(&dest[0], src);
}
//////////////////////////////////////////////////////////
// main
//
int main()
{
{
char dest1[4] = "xyz";
char dest2[4] = "xyz";
safestrcpy1(dest1, "");
safestrcpy2(dest2, "");
#define RES1A "\0yz"
#define RES2A "\0\0\0"
assert(memcmp(dest1, RES1A, sizeof(RES1A)) == 0);
assert(memcmp(dest2, RES2A, sizeof(RES2A)) == 0);
std::cout << dest1 << std::endl;
}
{
char dest1[4] = "xyz";
char dest2[4] = "xyz";
safestrcpy1(dest1, "1");
safestrcpy2(dest2, "1");
#define RES1B "1\0z"
#define RES2B "1\0\0"
assert(memcmp(dest1, RES1B, sizeof(RES1B)) == 0);
assert(memcmp(dest2, RES2B, sizeof(RES2B)) == 0);
std::cout << dest1 << std::endl;
}
{
char dest1[4] = "xyz";
char dest2[4] = "xyz";
safestrcpy1(dest1, "12");
safestrcpy2(dest2, "12");
#define RES1C "12\0"
#define RES2C "12\0"
assert(memcmp(dest1, RES1C, sizeof(RES1C)) == 0);
assert(memcmp(dest2, RES2C, sizeof(RES2C)) == 0);
std::cout << dest1 << std::endl;
}
{
char dest1[4] = "xyz";
char dest2[4] = "xyz";
safestrcpy1(dest1, "123");
safestrcpy2(dest2, "123");
#define RES1D "123"
#define RES2D "123"
assert(memcmp(dest1, RES1D, sizeof(RES1D)) == 0);
assert(memcmp(dest2, RES2D, sizeof(RES2D)) == 0);
std::cout << dest1 << std::endl;
}
{
char dest1[4] = "xyz";
char dest2[4] = "xyz";
safestrcpy1(dest1, "1234");
safestrcpy2(dest2, "1234");
#define RES1E "123"
#define RES2E "123"
assert(memcmp(dest1, RES1E, sizeof(RES1E)) == 0);
assert(memcmp(dest2, RES2E, sizeof(RES2E)) == 0);
std::cout << dest1 << std::endl;
}
}