Reputation: 492
I have a C SDK I need to use in an iPhone project, and the example code was written for use with Visual Studio. It includes use of strcpy_s, which is a Microsoft-only string function.
file_header.header_size = FIT_FILE_HDR_SIZE;
strcpy_s((FIT_UINT8 *)&file_header.data_type, sizeof(".FIT"), ".FIT"); << problem!
I've tried changing to strcpy and strncpy like so
strncpy((FIT_UINT8 *)&file_header.data_type, ".FIT", sizeof(".FIT"));
But I get this warning:
warning: pointer targets in passing argument 1 of 'builtin_strncpy_chk' differ in signedness
warning: pointer targets in passing argument 1 of '__inline_strncpy_chk' differ in signedness
warning: call to builtin_strncpy_chk will always overflow destination buffer
The struct file_header is this:
typedef struct
{
FIT_UINT8 header_size; // FIT_FILE_HDR_SIZE (size of this structure)
FIT_UINT8 protocol_version; // FIT_PROTOCOL_VERSION
FIT_UINT16 profile_version; // FIT_PROFILE_VERSION
FIT_UINT32 data_size; // Does not include file header or crc. Little endian format.
FIT_UINT8 data_type[4]; // ".FIT"
} FIT_FILE_HDR;
FIT_UINT8 is typedef Unsigned char.
So we can see that it is given an length of 4 in the typedef, and the strcpy_s takes the data_type by reference and copys ".FIT" to it. Where am I going wrong with strncpy? If you haven't guessed by now I'm not much of a C programmer :)
Edit: this does not give me an error, but it is correct?
strncpy((void *)&file_header.data_type, ".FIT", sizeof(file_header.data_type));
Upvotes: 0
Views: 2312
Reputation: 106247
With any "safe string" operations, the size should almost always be the size of the destination buffer; if you use the size of the source string, you might as well call memcpy
.
If you want C99 conformance:
strncpy(file_header.data_type, ".FIT", sizeof file_header.data_type);
However, strlcpy
(a BSDism, available in iOS) is preferred by many, because it guarantees that the destination will be nul-terminated:
strlcpy(file_header.data_type, ".FIT", sizeof file_header.data_type);
Note, however that the nul-terminated string ".FIT" doesn't actually fit in the allotted space, as it requires 5 characters (1 for the trailing nul). If you use strlcpy
, you will see that the resulting string is just ".FI" because strlcpy
guarantees nul-termination, and truncates your string if necessary.
If you require nul-termination then, you probably want to increase the size of the data_type
array to 5. As caf correctly points out, this looks like a file header, in which case nul-termination is probably not required; in that case strncpy
is preferred; I might even use memcpy
, and avoid giving a future developer the idea that the field is a string.
Upvotes: 1