我想分配内存来保存从给定字符串中提取的字段。字段的大小由两个指针的差异决定,请参见以下最小示例:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int
main(int argc, char *argv[])
{
const char line[] = "foo,bar,baz";
char *field_start = line;
char *field_end;
char *field;
field_end = strchr(line, ',');
field = malloc(field_end - field_start + 1);
memcpy(field, field_start, field_end - field_start);
*(field + (field_end - field_start)) = '\0';
printf("field=\"%s\"\n", field);
/* ... */
return (0);
}
使用clang -Weverything -o ex ex.c
编译此代码会产生以下警告:
ex.c:14:41: warning: implicit conversion changes signedness: 'long' to 'unsigned long'
[-Wsign-conversion]
field = malloc(field_end - field_start + 1);
~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~^~~
ex.c:15:39: warning: implicit conversion changes signedness: 'long' to 'unsigned long'
[-Wsign-conversion]
memcpy(field, field_start, field_end - field_start);
~~~~~~ ~~~~~~~~~~^~~~~~~~~~~~~
据我了解,指针差异的结果是ptrdiff_t类型,而malloc / memcpy期望一个类型为size_t的参数。
所以我的问题是如何解决这个问题并消除警告?如
field_end >= field_start
区别不能变为负面,所以也可能
以上安全地投放到size_t
field = malloc(size_t(field_end - field_start + 1));
memcpy(field, size_t(field_start, field_end - field_start));
或者我正在忽视的任何问题?
注意:
为简单起见,上面没有检查返回值。 field_start和_end当然应该是const。
答案 0 :(得分:4)
field_end >= field_start
仅在strchr
不返回NULL
的情况下成立,即类型系统中没有任何内容告诉编译器这确实总是成立。因此警告是有道理的。但是,如果您确定不是这种情况,那么(size_t)(field_end - field_start)
应该没问题。为了不重复这一点,我添加
size_t field_len;
/* memchr & null-check go here */
field_len = (size_t)(field_end - field_start);
...然后全部使用field_len
。
话虽如此,您可能希望通过拨打strndup
来替换malloc
/ memcpy
组合。