sizeof在C中的用法

sizeof在C中的用法,c,redis,C,Redis,我正在阅读redis的源代码。 代码如下: typedef char *sds; struct sdshdr { unsigned int len; unsigned int free; char buf[]; }; static inline size_t sdslen(const sds s) { struct sdshdr *sh = (void*)(s-(sizeof(struct sdshdr))); return sh->len; }

我正在阅读redis的源代码。 代码如下:

typedef char *sds;

struct sdshdr {
    unsigned int len;
    unsigned int free;
    char buf[];
};

static inline size_t sdslen(const sds s) {
    struct sdshdr *sh = (void*)(s-(sizeof(struct sdshdr)));
    return sh->len;
}

static inline size_t sdsavail(const sds s) {
    struct sdshdr *sh = (void*)(s-(sizeof(struct sdshdr)));
    return sh->free;
}
关于此代码,我有一些问题:

  • 为什么
    sizeof(struct sdshdr)
    8的输出?为什么不包括
    char buf[]
  • 我无法理解函数
    size\u t sdslen
    sdsavail
    。为什么
    structsdshdr*sh=(void*)(s-(sizeof(structsdshdr))
  • 大小为0的数组没有大小,它声明的长度为0。这是一个灵活的数组成员;它只能出现在结构的末尾
  • 该初始化将
    sh
    设置为指向通过取
    s
    的值、一个
    char*
    并减去sds报头的大小而计算的内存。换句话说,从指向字符串的第一个字符(灵活数组成员)的指针开始,我们计算指向头本身的指针,这样就可以得到长度

  • char buf[]未分配任何内存,因此不占用空间,因此充当灵活的数组,因此2 int数据类型最终占用4+4=8字节

  • size\u t
    中,传递的变量是属于
    *sds
    s
    ,它是
    字符的类型定义

    这将导致在内存中实现此代码

    if (init) {
        sh = zmalloc(sizeof(struct sdshdr)+initlen+1);
      } else {
        sh = zcalloc(sizeof(struct sdshdr)+initlen+1);
      }
      if (sh == NULL) return NULL;
      sh->len = initlen;
      sh->free = 0;
      if (initlen && init)
        memcpy(sh->buf, init, initlen);
      sh->buf[initlen] = '\0';
      return (char*)sh->buf;
    }
    

    它存储的内存空间等于sh-sdshdr结构。

    这是一个强制转换,没有意义。无法安全地将字符指针转换为结构指针,这违反了严格的别名。此外,在typedefs后面隐藏指针是非常糟糕的做法。@Lundin这就是
    (void*)
    所要解决的问题,对吗?传入的指针是
    char*s
    ,您可以从中减去。然后将结果强制转换为
    void*
    ,这会将fine转换为
    struct shdr*
    (但更短更一般)。@Lundin我很确定这里没有字符串别名问题,因为指针的值已更改,并且在减法后指向实际的结构对象。例如,如果字符串本身将被重新解释为一个结构,但它不是。Struct被解释为使用兼容类型的Struct。(char*也可以指向任何对象。)你能给我一个关于
    struct-sdshdr*sh=(void*)(s-(sizeof(struct-sdshdr)))的详细解释吗?我不明白。
    s
    是内存中的一个指针,它似乎指向一个
    struct-sdshdr
    ,然后
    s-(sizeof(…)
    在struct之前计算这个的地址。这可以写成
    ((struct-sdshdr*)s)-1
    @BlackMamba:此行的作用是,为sh=malloc/calloc创建一个内存空间,然后检查该字符是否为初始len,并在末尾添加1。然后设置其完整长度,并检查该行的内存是否可用于初始化,初始化后在*s结尾添加“\0”,然后将缓冲区返回到程序必须是“sds”的一种类型,它是char,因此return语句的结果是return char*sh->buf。希望这一点很清楚,如果你的问题解决了,请投票:)@DanyalImran我找到了这个链接,我现在很清楚:@BlackMamba太棒了:D