繁体   English   中英

指针差异和size_t

[英]Pointer difference and size_t

我想分配内存来保存从给定字符串中提取的字段。 字段的大小由两个指针的差异决定,请参阅以下最小示例:

#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编译此代码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。

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组合。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM