memcpy 能否正确复制字符串?

Phi*_*hil 3 c objective-c memcpy nsstring strcpy

我正在努力实现一些低级文件写入,其中文件格式具体到每一位。我需要将一个字符串从一个NSString长度为 16 的空终止字符串复制(根据 Xcode,这是不可分配的)。说到 ,我完全是个菜鸟c,并且想确保我正确理解这一点。这就是我目前正在做的事情:

//I have a non-null NSString called _friendly_name.
const char *string = [_friendly_name UTF8String];
//profile.friendly is a utf-8 null-terminated string
memcpy(&profile.friendly_name, &string, 16);
Run Code Online (Sandbox Code Playgroud)

这尚未经过测试,但我想确保这会起作用。这会提供我期望的行为吗?或者我应该以不同的方式复制字符串(例如strcpy)?

Die*_*Epp 5

您可以使用memcpy()or strcpy(),但您必须自己进行边界检查,并且代码中还存在其他错误。

所以,我认为您想将 NSString 复制到char[16]数组中。您可以使用NSString内置方法来执行此操作,而不必memcpy()自己使用:

NSString *src;
char dest[16];
NSUinteger destlen;
[src getBytes:dest
    maxLength:sizeof(dest) - 1
    usedLength:&destlen
    encoding:NSUTF8StringEncoding
    options:0
    range:NSMakeRange(0, [src length])
    remainingRange:NULL];
dest[destlen] = '\0';
Run Code Online (Sandbox Code Playgroud)

如果你想使用memcpy(),那么你必须这样做:

NSString *src;
char dest[16], *srcUtf8;
size_t len;

srcUtf8 = [src UTF8String];
len = strlen(srcUtf8);
if (len >= sizeof(dest))
    len = sizeof(dest) - 1;
memcpy(dest, srcUtf8, len);
dest[len] = '\0';
Run Code Online (Sandbox Code Playgroud)

您的代码中的错误

这段代码有两个错误!

memcpy(&profile.friendly_name, &string, 16); // Wrong!
Run Code Online (Sandbox Code Playgroud)

首先,&string是错误的。它应该是string,因为string是指向要复制的字符串数据的指针。如果您进行复制&string,您将获得一个指针和复制的一些堆栈数据的随机位。换句话说,你会得到垃圾。

其次,16是错误的。string如果您知道指向至少 16 字节的数据,则只能复制 16字节。string如果内存中的以下数据小于 16 个字节,这将导致分段错误(使程序严重崩溃) 。它今天可能不会崩溃,但也许下周就会崩溃,你就会忘记这一切?

这是错误的,除非您知道源至少有 16 个字节长,否则不要传递 16。