Reputation: 36289
I am working on implementing some low-level file writing, where the file format is specific down to each bit. I need to copy a string from an NSString
into null-terminated string with length 16 (which is not assignable, according to Xcode). I am a total n00b when it comes to c
, and want to be sure I understand this correctly. This is what I am currently doing:
//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);
This has not yet been tested, but I want to be sure this will work. Will this provide the behavior I am expecting? Or should I be copying the string a different way (such as strcpy
)?
Upvotes: 3
Views: 9295
Reputation: 3571
//I have a non-null NSString called _friendly_name.
const char *string = [_friendly_name UTF8String];
//profile.friendly is a utf-8 null-terminated string : char [17] ??
memcpy(profile.friendly_name, string, 16);
profile.friendly_name[16]='\0';
EDIT:
Yes, exactly. Adding a NULL
at ende. Actually it could be better to initialize to all 0
before copying. strcpy
will not work if _friendly_name
don't have a '\0'
before position 16. strncpy
will be fine.
EDIT2:
Some problem arised why we dont have all the needed information:
1- You need an NULL-terminated string of length 16 (16 character+0 as in char var[17];
) or you need a 16 byte field terminated witch NULL as in char var[16];
?
2- what is the desred "error" management: if the original string is larged than "16" we just truncate it, or we trow an error?
Assuming you need a field of 16 bytes and a truncate string you can use:
strncpy(profile.friendly_name, string, 15);
profile.friendly_name[15]='\0';
EDIT3:
Also... to truncate have to be made carefully: we dont want to truncate a multibyte character...
Upvotes: 0
Reputation: 213338
You can use memcpy()
or strcpy()
, but you'll have to do the bounds checking yourself and there are other errors in your code.
So, I take it you want to copy an NSString into a char[16]
array. You can use an NSString
builtin method to do this, and you don't have to use memcpy()
yourself:
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';
If you want to use memcpy()
, then you'll have to do it this way:
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';
This code has two errors in it!
memcpy(&profile.friendly_name, &string, 16); // Wrong!
First of all, &string
is wrong. It should be string
, because string
is a pointer to the string data you want to copy. If you copy &string
, you will get a pointer and some random bits of stack data copied instead. In other words, you'll get garbage.
Secondly, 16 is wrong. You can only copy 16 bytes if you know that string
points to at least 16 bytes of data. This will cause a segmentation fault (crash your program, hard) if string
is less than 16 bytes the following data in memory is not readable. It might not crash today, but maybe it will crash next week, and you'll have forgotten all about it?
It's wrong, don't pass 16 unless you know the source is at least 16 bytes long.
Upvotes: 5
Reputation: 9579
Have you read the doc? memcpy will work, but you pass in the number of bytes to copy. It will copy the number of bytes you specify, irrelevant of a NULL. strcpy you don't pass the length, it will copy bytes up to and including the first NULL.
http://www.cplusplus.com/reference/cstring/memcpy/
http://www.cplusplus.com/reference/cstring/strcpy/
Upvotes: 2
Reputation: 5964
memcpy() should work fine, but strcpy() will work fine too. You just need to make sure that profile.friendly_name is big enough to hold what you're copying into it.
Upvotes: 3