#include <iostream>
using namespace std;
struct Packet {
int a;
char b[17];
int c;
};
// char* dest has form char dest[n], src has length <= n and is null-terminated
// After the function, dest should satisfy:
// - If strlen(src)==n, dest is not null terminated
// - If strlen(src) < n, dest[n-1] = dest[strlen(src)] = '\0'
static void strncpy_faster(char* dest, const char* src, size_t n) {
size_t i;
for (i = 0; i < n; i++) {
dest[i] = src[i];
if (src[i] == '\0')
break;
}
//while (i < n) {dest[i] = '\0'; i++;} // C standard strncpy do this
if (i < n)
dest[n - 1] = '\0';
}
string charArrayToString(const char* a, size_t n) {
size_t len = 0;
while (len < n && a[len]!='\0') len++;
return std::string(a, a+len);
}
int main()
{
string s = "12341234123412345";
Packet packet;
strncpy_faster(packet.b, s.c_str(), 17);
cout << charArrayToString(packet.b, sizeof(packet.b)) << "\n";
s = "12345";
strncpy_faster(packet.b, s.c_str(), 17);
cout << charArrayToString(packet.b, sizeof(packet.b));
return 0;
}
我正在处理具有固定大小字符数组的结构。假设我真的非常想保持结构的大小很小(或者我需要通过网络发送它们),所以std::string
在我的结构中没有使用(它花费 32 个字节,而我有多个大小为 4-20 的小字符数组)。我对 strncpy 有 2 个问题:
strncpy
具有相同长度的 2 个字符数组将发出有关“可能没有以空字符结尾的字符”的警告,这是有意的,但我不需要该警告。strncpy
用 .填充所有剩余字符(来自dest[strlen(src) -> n-1]
)'\0'
。这在我的程序中浪费了处理。
所以,我strncpy_faster
最多只能为 '\0' 分配 2 个位置:数组的最后一个元素,以及strlen(src)
. 由于std::string()
需要一个以空字符结尾的字符数组 (NTCA),因此我使用charArrayToString()
将非 NTCA 转换为字符串。
这个版本strncpy
安全吗?是否有任何 C/C++ 函数需要strncpy
用 填充所有剩余字节'\0'
,或者它们只需要一个空终止符?我不知道为什么标准要求strncpy
将剩余字节清零。