1

sds 関数の使用方法を学習しようとしています。プロジェクト フォルダーにコード sds.h および sds.c コード ファイルがあり、私が作成した小さな探索プログラムはコンパイルして正常に実行されます。しかし、sds.h および sds.c ファイルのコードに表示されている内容を理解するのに苦労しています。なぜそれが動作するどころか、コンパイルできるのかわかりません。

問題のコードは次のとおりです。

typedef char *sds;

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

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

sdslen() 関数は sds.c ファイルで何度も呼び出されており、sds.h をインクルードした後で自分のプログラムで使用することもできます。typedef が sds を単なる char ポインターの型にすることを知っています。static キーワードは、関数の範囲を制限します。インラインとは、スタックおよび関数呼び出しメカニズムを使用するのではなく、関数が呼び出されたときにコンパイラによって関数がコードに貼り付けられることを意味します。sdslen() 関数の *sh ポインターには、s に格納されたアドレスの前に sizeof(struct sdshdr) メモリ アドレスが割り当てられ、構造体の変数を初期化せずに len メンバー変数が返されるように見えます。 . これ、実際に何が起こっているのかを理解するための助けをいただければ幸いです。

4

1 に答える 1

2

私はそれを理解したと思います。sds.c答えは、ファイルの別の関数にあります。

sds sdsnewlen(const void *init, size_t initlen) {
  struct sdshdr *sh;

  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;
}

newsdsが作成され、sdsnewlen()関数によって初期化されると、構造体全体と c-string に対してメモリが動的に割り当てられますが、c-string のアドレスが返されます。関数を使用せずに使用して割り当てられsdslen()た変数で呼び出されると、問題が発生します。提供された関数を使用して変数が初期化されている限り、メモリは有効であり、メンバー変数は初期化されており、変数はc-string と同じように使用できます。sdsmallocsdsnewlen()sdssdsprintf()

于 2013-11-06T18:47:47.443 に答える