2016-11-19 22 views
0

プロトタイプC言語で入力するには:size_t offsetof(type, member);変換文字列は

私は私が文字列でないタイプに名前だけを持っているものならば、最初のパラメータはタイプである知っています。 offsetofを文字列リテラルのメンバにしたい

私はコミュニティからの助けが必要です。

例:

#include <stdio.h> 
#include <stddef.h> 

typedef struct example_ { 
    void *member1; 
    void *member2; 
} example; 

unsigned int 
offset_gen(char *ds, char *member) 
{ 
    return (offsetof(ds, member)); 
} 

void 
main() 
{ 
    printf ("\n %d", offset_gen("example", "member1")); 
    printf ("\n %d", offset_gen("example", "member2")); 
} 
+0

このアプローチは不可能です。ソースコード以外の型情報ファイルのようなものが必要だと思います。 – BLUEPIXY

+1

'offsetof'はコンパイル時に機能します。実行時に構造体メンバに名前でアクセスできるようにするために文字列定数を使用しようとすると、コンパイラはそれを実行しません。 (あなたはCが持っていない*イントロスペクション*を探しています。)それは迷惑ですが、あなた自身のディクショナリをオフセットにマッピングし、その名前で物事を調べることができます。 –

+0

なぜ型を使用しないのですか?あなたの機能はとにかく大変です。 Cは統計的に型付けされているので、コンパイル時には常にオブジェクトの型を知ることができます。 – Olaf

答えて

1

私はあなたが間違った方法でoffsetofを使用していると思います。構造体型とメンバ名はマクロに渡す必要があり、名前を含む文字列は渡さないでください。あなたがようmember1のオフセットを計算することができ、その後

typedef struct example_ { 
    void *member1; 
    void *member2; 
}example; 

は、例えば、あなたの構造体である場合は

offsetof(example, member1) 

しかし、あなたはまだあなたが持っているように文字列リテラルを使用したい場合は、 offset_genmemberパラメータを構造体メンバ名と手動で比較し、対応するマクロを呼び出す必要があります。

例:(あなたは自分の限界をテストしたい場合は!)

unsigned int 
offset_gen(char *ds, char *member) 
{ 
    if(!strcmp(ds,"example")) 
    { 
     if(!strcmp(member,"member1")) 
      return (offsetof(example, member1)); 
     else if(!strcmp(member,"member2")) 
      return (offsetof(example, member2)); 
    } 
    return -1;  // if no match for input paramters is found 
} 

あなたもthis、あるいはthisような何かを試すことができます。

+0

'member'を' member1'または 'member2'に変更したり、両方の例を表示することができます。それ以外にも、 'offsetof'がどのように動作しているのか、コンパイルと実行時の計算の違いなどについては説明していません。 –

+0

悪い、編集中です。 – skrtbhtngr

+0

すべての謙虚さと、私はoffsetofマクロを使用する方法を知っていますが、私は必要なのは、char配列または文字列の形でそこに名前を持つ構造体のメンバのオフセットを得ることができるソリューションです –

2

ここでは、これをどのように実装することができるかに関する実際の例があります。

注:これはアプリケーション対応のコードではありません。私はこれを最初から書きました。そのようなものは、概念の証明としてのみ考えるべきです。開発チームの議論の基礎として使用されるもの。このバージョンでは、適切なCパーサは使用されませんが、Cソースで使用されている特定の規則が適用されます。

この投稿に含まれるすべてのファイルは、CC0、つまりパブリックドメイン専用です。しかし、保証がないことを覚えておいてください:もし何かを壊したり破損したりするなら、私を責めないでください。

本質的に、私たちは、コンパイルして実行すると、あらかじめ計算されたデータを持つハッシュテーブルを生成するCプログラムを生成するためにBash + Awkスクリプトを使用し、member_offset()関数は構造体のメンバオフセット型とメンバ名は文字列として与えられます。

説明のため、これは完全な実例で、Makefileを含みます。

ファイルmytypes.hは、我々が興味を持っているタイプが含まれています

#include <stdlib.h> 

struct type1 { 
    char   one, two[2]; 
    float  three; 
    int  (*callback)(const char *, void *, size_t); 
} __attribute__((__packed__)); 

struct type2 { 
    char   four; 
    struct type1 five; 
    int   six, seven[3]; 
}; 

あなたは1つのヘッダーファイルにタイプを詰め込むする必要はありません。ファイルが異なる場合は、Makefileを編集するだけです。ただし、すべてのタイプがヘッダーファイルに含まれています。これは、中間のCジェネレーターファイルの#include 'になり、ビルド時にのみコンパイルされて実行されます。説明のため

、我々はオフセット標準出力に出力して、ユーザは、コマンドライン上の構造体の型とメンバー名を指定することができますmain.cを持っている:

#include <stdlib.h> 
#include <string.h> 
#include <stdio.h> 
#include <errno.h> 

extern size_t member_offset(const char *type, const char *name, const size_t not_found); 

int main(int argc, char *argv[]) 
{ 
    int arg; 
    size_t offset; 

    if (argc < 3 || !(argc & 1) || !strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")) { 
     fprintf(stderr, "\n"); 
     fprintf(stderr, "Usage: %s [ -h | --help ]\n", argv[0]); 
     fprintf(stderr, "  %s TYPE NAME [ TYPE NAME ... ]\n", argv[0]); 
     fprintf(stderr, "\n"); 
     return EXIT_SUCCESS; 
    } 

    for (arg = 1; arg < argc - 1; arg += 2) { 
     offset = member_offset(argv[arg], argv[arg + 1], ~(size_t)0); 
     if (errno) { 
      fprintf(stderr, "struct %s unknown, or has no member %s.\n", argv[arg], argv[arg + 1]); 
      return EXIT_FAILURE; 
     } 

     printf("struct %s has member %s at offset %zu.\n", argv[arg], argv[arg + 1], offset); 
     fflush(stdout); 
    } 

    return EXIT_SUCCESS; 
} 

プロジェクトをビルドするために、我々はMakefileを使用しています。インデントはタブで、スペースではないことに注意してください。 makeはそんなに厄介です。

CC  := gcc 
CFLAGS := -Wall -O2 
LDFLAGS := 

.PHONY: all clean 

all: clean example 

clean: 
    rm -f *.o example member-offset.c member-offset-generator.c member-offset-generator 

member-offset.c: mytypes.h 
    rm -f [email protected] member-offset-generator member-offset-generator.c 
    ./member-offset-generator.bash mytypes.h:type1 mytypes.h:type2 > member-offset-generator.c 
    $(CC) $(CFLAGS) member-offset-generator.c $(LDFLAGS) -o member-offset-generator 
    ./member-offset-generator > [email protected] 
    rm -f member-offset-generator member-offset-generator.c 

%.o: %.c 
    $(CC) $(CFLAGS) -c $^ 

example: member-offset.o main.c 
    $(CC) $(CFLAGS) $^ $(LDFLAGS) -o [email protected] 

上記のmember-offset.cルールに注意してください。それはmember_offset()関数を含む自動生成されたCソースファイルを参照します。それがまだ存在しない場合、またmytypes.hが変更されたときに再コンパイルされます。

コマンド./member-offset-generator.bash mytypes.h:type1 mytypes.h:type2 > member-offset-generator.cmytypes.hを調べるために、(さらに以下を参照のこと)はまだ示されていない第4のファイルを使用し、型データベースハッシュテーブルにstruct type1struct type2が挙げられます。出力はmember-offset-generator.cです。これは、コンパイルして実行すると実際に必要なCコードを生成するCプログラムです。このルールを別々のルールに分割するほうが良いかもしれませんが、今のところ、自動的にmember-offset-generator.cをコンパイルして実行し、削除します(これはmember-offset.cを一度だけ出力する必要があるためです)。

その中間のCプログラム、member-offset-generator.bashを生成するシェル・スクリプトは、かなり複雑である:

#!/bin/bash 
export LANG=C LC_ALL=C 

[ -n "$CC"  ] || export CC="gcc" 
[ -n "$CFLAGS" ] || export CFLAGS="-Wall -O2" 

if [ $# -lt 1 ] || [ "$1" = "-h" ] || [ "$1" = "--help" ]; then 
    exec >&2 
    printf '\n' 
    printf 'Usage: %s [ -h | --help ]\n' "$0" 
    printf '  %s HEADER[:TYPE] ...\n' "$0" 
    printf '\n' 
    printf 'This script autogenerates a C program, that when run,\n' 
    printf 'emits a C implementation of function member_offset()\n' 
    printf 'which returns the offset of "member" within type "struct type".\n' 
    printf '\n' 
    printf 'The generated C program includes all HEADER files,\n' 
    printf 'but each one only once. Only the specified struct types\n' 
    printf 'will be supported by the final function.\n' 
    printf '\n' 
    exit 1 
fi 

function hash_of_function() { 
    sed -e 's|  ||' << END 
     /* DJB2 xor hash, http://www.cse.yorku.ca/~oz/hash.html */ 
     size_t hash_of(const void *data, const size_t size) 
     { 
      const unsigned char  *p = (const unsigned char *)data; 
      const unsigned char *const q = (const unsigned char *)data + size; 
      size_t      h = 5381; 
      while (p < q) 
       h = ((h << 5) + h)^(*(p++)); 
      return h; 
     } 
END 
} 

# Emit all headers as includes, but each one only once. 
printf '%s\n' "[email protected]" | awk \ 
    'BEGIN { 
     RS="\n" 
     FS=":" 
     split("", seen) 

     printf "#include <stdlib.h>\n" 
     printf "#include <stddef.h>\n" 
     printf "#include <string.h>\n" 
     printf "#include <stdio.h>\n" 
     seen["stdlib.h"] = 1 
     seen["stddef.h"] = 1 
     seen["string.h"] = 1 
     seen["stdio.h"] = 1 
    } 
    { 
     header = $1 
     sub(/^[<"]/, "", header) 
     sub(/[>"]$/, "", header) 
     if (length(header) > 0 && !(header in seen)) { 
      seen[header] = 1 
      if (substr($1, 1, 1) == "<") 
       printf "#include <%s>\n", header 
      else 
       printf "#include \"%s\"\n", header 
     } 
    }' 

# emit the hash function as a string. 
printf '\nstatic const char hash_of_def[] =\n' 
hash_of_function | sed -e 's|\\|\\\\|g; s|"|\\"|g; s|^| "|g; s|[\t\v\f ]*$|\\n"|g' 
printf ' ;\n\n' 
# and the hash function itself. 
hash_of_function 

# emit structures and code used by the generator itself. 
sed -e 's|^ ||' <<END 

    struct type_member_list { 
     struct type_member_list *next; 
     size_t     offset; 
     size_t     hash; 
     size_t     namelen; 
     char      name[]; 
    }; 

    struct type_list { 
     struct type_list  *next; 
     struct type_member_list *members; 
     size_t     hash; 
     size_t     slots; 
     size_t     typelen; 
     char      type[]; 
    }; 

    static size_t type_list_size(const struct type_list *list) 
    { 
     size_t result = 0; 
     while (list) { 
      ++result; 
      list = list->next; 
     } 
     return result; 
    } 

    static size_t type_member_list_size(const struct type_member_list *list) 
    { 
     size_t result = 0; 
     while (list) { 
      ++result; 
      list = list->next; 
     } 
     return result; 
    } 


    static struct type_list *types = NULL; 


    static void add_type_member(const char *type, const char *name, const size_t offset) 
    { 
     const size_t typelen = (type) ? strlen(type) : 0; 
     const size_t namelen = (name) ? strlen(name) : 0; 

     struct type_list  *list = NULL, *temp; 
     struct type_member_list *member; 

     if (!typelen || !namelen) { 
      if (!typelen) 
       fprintf(stderr, "Error: add_type_member() called with empty type.\n"); 
      if (!namelen) 
       fprintf(stderr, "Error: add_type_member() called with empty name.\n"); 
      exit(EXIT_FAILURE); 
     } 

     /* Find the list for the specified type. */ 
     for (temp = types; temp != NULL; temp = temp->next) 
      if (temp->typelen == typelen && !strcmp(temp->type, type)) { 
       list = temp; 
       break; 
      } 

     /* If this is a new type, create a new list. */ 
     if (!list) { 
      list = malloc(sizeof (struct type_list) + typelen + 1); 
      if (!list) { 
       fprintf(stderr, "Error: Out of memory.\n"); 
       exit(EXIT_FAILURE); 
      } 
      memcpy(list->type, type, typelen); 
      list->type[typelen] = '\0'; 
      list->typelen = typelen; 
      list->hash = hash_of(type, typelen); 
      list->slots = 0; 
      list->members = NULL; 

      /* Prepend to global types list. */ 
      list->next = types; 
      types = list; 
     } 

     /* Create a new member. */ 
     member = malloc(sizeof (struct type_member_list) + namelen + 1); 
     if (!member) { 
      fprintf(stderr, "Error: Out of memory.\n"); 
      exit(EXIT_FAILURE); 
     } 
     memcpy(member->name, name, namelen); 
     member->name[namelen] = '\0'; 
     member->namelen = namelen; 
     member->hash = hash_of(name, namelen); 
     member->offset = offset; 

     /* Prepend to member list. */ 
     member->next = list->members; 
     list->members = member; 
    } 

    void add_types_and_members(void) 
    { 
END 

ignorefirst=$'<"' 
ignorelast=$'>"' 

# Extract the member names from each structure. 
for pair in "[email protected]"; do 
    name="${pair#*:}" 
    [ ":$name" = ":$pair" ] && continue 
    [ -n "$name" ] || continue 

    file="${pair%%:*}" 
    file="${file#[$ignorefirst]}" 
    file="${file%[$ignorelast]}" 

    $CC $CFLAGS -P -E "$file" | \ 
    sed -e '/#/ d' | tr -s '\t\n\v\f\r ' '  ' | \ 
    sed -e 's|\(struct [^ ]*\) {|\n\1 {\n|g; s|}|\n}\n|g; s| *;|\n|g; s|)([^)]*)||g' | \ 
    awk -v name="$name" \ 
    'BEGIN { 
     RS = " *\n" 
     FS = " *," 
     split("", members) 
    } 

    $0 == ("struct " name " {") { 
     inside = 1 
     next 
    } 

    $0 == "}" { 
     inside = 0 
     next 
    } 

    inside { 
     for (i = 1; i <= NF; i++) { 
      member = $i 
      sub(/\[[^\[\]]*\]/, "", member) 
      sub(/^.*[ \*(]/, "", member) 
      if (!(member in members)) 
       members[member] = member 
     } 
    } 

    END { 
     for (member in members) 
      printf " add_type_member(\"%s\", \"%s\", offsetof(struct %s, %s));\n", name, member, name, member 
    }' || exit 1 
done 

# emit the rest of the generator code. 
sed -e 's|^ ||' <<END 
    } 

    size_t type_slots(struct type_list *list) 
    { 
     const size_t size = type_list_size(list); 
     const size_t max_slots = 4 * size + 1; 
     size_t  slots = size; 
     size_t  *used, i, n; 

     struct type_list *item; 

     used = malloc(max_slots * sizeof used[0]); 
     if (!used) { 
      fprintf(stderr, "Error: Out of memory.\n"); 
      exit(EXIT_FAILURE); 
     } 

     while (1) { 
      if (slots >= max_slots) { 
       fprintf(stderr, "Error: Weak hash function; hash table grows too large.\n"); 
       fprintf(stderr, "  (Need more than %zu slots for %zu data entries.)\n", max_slots, size); 
       exit(EXIT_FAILURE); 
      } 

      for (i = 0; i < slots; i++) 
       used[i] = 0; 

      for (item = list; item != NULL; item = item->next) 
       ++used[item->hash % slots]; 

      n = used[0]; 
      for (i = 1; i < slots; i++) 
       if (used[i] > n) 
        n = used[i]; 

      if (n <= 1) { 
       free(used); 
       return slots; 
      } 

      slots++; 
     } 
    } 


    size_t generate_type(const char *type, struct type_member_list *list, const size_t size) 
    { 
     /* Maximum size for current hash table. */ 
     const size_t max_slots = 4*size + 1; 
     size_t  slots = size; 
     size_t  *used, i, n; 

     struct type_member_list *item; 

     if (size < 1) 
      return 0; 

     used = malloc(max_slots * sizeof used[0]); 
     if (!used) { 
      fprintf(stderr, "Error: Out of memory.\n"); 
      exit(EXIT_FAILURE); 
     } 

     while (1) { 

      if (slots >= max_slots) { 
       fprintf(stderr, "Error: Weak hash function; hash table grows too large.\n"); 
       fprintf(stderr, "  (Need more than %zu slots for %zu data entries.)\n", max_slots, size); 
       exit(EXIT_FAILURE); 
      } 

      /* Clear slot use counts. */ 
      for (i = 0; i < slots; i++) 
       used[i] = 0; 

      /* Count slot occupancies. */ 
      for (item = list; item != NULL; item = item->next) 
       ++used[item->hash % slots]; 

      /* Find the maximum slot occupancy. */ 
      n = used[0]; 
      for (i = 1; i < slots; i++) 
       if (used[i] > n) 
        n = used[i]; 

      /* Suitable size? */ 
      if (n <= 1) 
       break; 

      /* Try a larger hash table, then. */ 
      slots++; 
     } 

     free(used); 

     /* Print out the contents of this hash table. */ 
     printf("static const struct member struct_%s_members[%zu] = {\n", type, slots); 
     for (i = 0; i < slots; i++) { 
      for (item = list; item != NULL; item = item->next) 
       if (item->hash % slots == i) 
        break; 
      if (item) { 
       printf(" { .offset = %zu,\n", item->offset); 
       printf("  .hash = %zu,\n", item->hash); 
       printf("  .namelen = %zu,\n", item->namelen); 
       printf("  .name = \"%s\" },\n", item->name); 
      } else { 
       printf(" { .offset = 0,\n"); 
       printf("  .hash = 0,\n"); 
       printf("  .namelen = 0,\n"); 
       printf("  .name = NULL },\n"); 
      } 
     } 
     printf("};\n\n"); 

     return slots; 
    } 

    int main(void) 
    { 
     struct type_list *list; 
     size_t   main_slots, i; 

     add_types_and_members(); 

     printf("#include <stdlib.h>\n"); 
     printf("#include <string.h>\n"); 
     printf("#include <errno.h>\n"); 
     printf("\n"); 
     printf("struct member {\n"); 
     printf(" const size_t  offset;\n"); 
     printf(" const size_t  hash;\n"); 
     printf(" const size_t  namelen;\n"); 
     printf(" const char *const name;\n"); 
     printf("};\n"); 
     printf("\n"); 
     printf("struct type {\n"); 
     printf(" const size_t    hash;\n"); 
     printf(" const size_t    namelen;\n"); 
     printf(" const size_t    members;\n"); 
     printf(" const struct member *const member;\n"); 
     printf(" const char *const   name;\n"); 
     printf("};\n"); 
     printf("\n"); 
     printf("%s\n", hash_of_def); 
     printf("\n"); 

     for (list = types; list != NULL; list = list->next) 
      list->slots = generate_type(list->type, list->members, type_member_list_size(list->members)); 

     main_slots = type_slots(types); 

     printf("static const size_t  num_types = %zu;\n", main_slots); 
     printf("static const struct type types[%zu] = {\n", main_slots); 
     for (i = 0; i < main_slots; i++) { 
      for (list = types; list != NULL; list = list->next) 
       if (list->hash % main_slots == i) 
        break; 

      if (list) { 
       printf(" { .hash = %zuUL,\n", list->hash); 
       printf("  .namelen = %zu,\n", list->typelen); 
       printf("  .members = %zu,\n", list->slots); 
       printf("  .member = struct_%s_members,\n", list->type); 
       printf("  .name = \"%s\" },\n", list->type); 
      } else { 
       printf(" { .hash = 0,\n"); 
       printf("  .namelen = 0,\n"); 
       printf("  .members = 0,\n"); 
       printf("  .member = NULL,\n"); 
       printf("  .name = NULL },\n"); 
      } 
     } 
     printf("};\n"); 
     printf("\n"); 
     printf("size_t member_offset(const char *type, const char *name, const size_t not_found)\n"); 
     printf("{\n"); 
     printf(" const size_t typelen = (type) ? strlen(type) : 0;\n"); 
     printf(" const size_t namelen = (name) ? strlen(name) : 0;\n"); 
     printf("\n"); 
     printf(" if (typelen > 0 && namelen > 0) {\n"); 
     printf("  const size_t typehash = hash_of(type, typelen);\n"); 
     printf("  const size_t t = typehash %% num_types;\n"); 
     printf("  if (types[t].hash == typehash &&\n"); 
     printf("   types[t].namelen == typelen &&\n"); 
     printf("   !strcmp(types[t].name, type)) {\n"); 
     printf("   const size_t   namehash = hash_of(name, namelen);\n"); 
     printf("   const struct member *const member = types[t].member + (namehash %% types[t].members);\n"); 
     printf("   if (member->hash == namehash &&\n"); 
     printf("    member->namelen == namelen &&\n"); 
     printf("    !strcmp(member->name, name)) {\n"); 
     printf("    errno = 0;\n"); 
     printf("    return member->offset;\n"); 
     printf("   }\n"); 
     printf("  }\n"); 
     printf(" }\n"); 
     printf(" errno = ENOENT;\n"); 
     printf(" return not_found;\n"); 
     printf("}\n\n"); 

     return EXIT_SUCCESS; 
    } 
END 

このバージョンはdjb2 xorハッシュ関数を使用します。他のものを使用している場合は、sed ... <<END行の後にCで記述し、行の始めにENDで始まり、hash_of_function Bash関数で終了します。 (sedは、8つのインデントを削除するだけで、スクリプトの読みやすさを向上させることができます)。これは高速でシンプルです。現実世界のユースケースで十分かどうかは分かりませんが、私はそれを投げたいくつかのテストヘッダファイルのために、うまくいきました。

既知の構造タイプと既知の構造タイプのメンバーの両方がハッシュテーブルに格納されます。エントリは小さいので、これはパフォーマンスの向上のために行われます。ハッシュテーブルはハッシュテーブルスロットごとに最大1つのエントリを持ち、いくつかの空きスロットがあります。これは、ルックアップごとに2つまでのプローブ(1つのテーブルにつき1つのプローブ)を意味します。中間のCプログラムは、エントリごとに最大で1つのタイプまたはメンバを配置する最小のサイズ(スロット数)を検索するので、単純な配列を使用できます。これは、ハッシュ・テーブル検索のための一定の時間($ O(1)$)の複雑さをもたらす。与えられた2つの文字列からハッシュを計算する必要があるため、技術的には時間の複雑さは長さによって異なります。つまり、という高速のハッシュ関数を使用する必要があります。ハッシュ関数は完全または暗号的に安全である必要はありません。

各ハッシュテーブルに対する1つのプローブは、最初にハッシュ、次に文字列の長さ、最後に文字列自体を比較して、誤った一致がないことを保証します。これは、一致が見つかった場合、正確に2つのstrcmp()が作成されることを意味します。

存在しないメンバーまたは存在しないタイプのオフセットを見つけるために関数が呼び出されないことがわかっている場合は、安全にstrcmp()のチェックを省略できます。

あなたは複雑な..あなたはおそらくCコードは生成Cプログラムを書いて、この時点では気づいていたよう

./member-offset-generator.bash mytypes.h:type1 mytypes.h:type2 | less 

を実行することによって生成された中間プログラムを調べることができます。 Cコードを生成するCプログラムを生成するスクリプトを書くことは、通常、メンテナンスにはあまり価値がないことです。しかし、スクリプトを維持することは、生成されたコードが価値があるよりも多くの労力を必要とする高いリスクがありますが、確かに実行可能です。このリスクに注意してください。

makeを実行した場合)Makefileのデフォルト動作はmake clean exampleと同じです。あなたは、それぞれのファイルに上記のすべてを保存し、makeは、それが実行するコマンドを出力し、私はそれらのいずれかを隠していなかったので、あなたが

rm -f *.o example member-offset.c member-offset-generator.c member-offset-generator 
rm -f member-offset.c member-offset-generator member-offset-generator.c 
./member-offset-generator.bash mytypes.h:type1 mytypes.h:type2 > member-offset-generator.c 
gcc -Wall -O2 member-offset-generator.c -o member-offset-generator 
./member-offset-generator > member-offset.c 
rm -f member-offset-generator member-offset-generator.c 
gcc -Wall -O2 -c member-offset.c 
gcc member-offset.o main.c -o example 

のようなものが表示されるはずです

make 

を実行する場合(対応するコマンドの先頭に@を付ける)。そして

、あなたが

./example type1 one type1 two type1 three type1 callback 

LP64アーキテクチャ(intが32ビットであること、及びlongとポインタ64でサンプルプログラムすべき出力するx86-64で

struct type1 has member one at offset 0. 
struct type1 has member two at offset 1. 
struct type1 has member three at offset 3. 
struct type1 has member callback at offset 7. 

を実行する場合ビット)、実行中

./example type2 four type2 five type2 six type2 seven 

出力

struct type2 has member four at offset 0. 
struct type2 has member five at offset 1. 
struct type2 has member six at offset 16. 
struct type2 has member seven at offset 20. 

x86-64では、-m32 GCCオプションを使用して32ビットコードをコンパイルできます。だから、我々は構造体のメンバーのタイプのサポートを追加する場合、これは、イントロスペクションのいくつかの種類を許容するように拡張することができ

make CFLAGS="-Wall -O2 -m32" clean all 

を実行し、その後

./example type2 four type2 five type2 six type2 seven 

出力

struct type2 has member four at offset 0. 
struct type2 has member five at offset 1. 
struct type2 has member six at offset 12. 
struct type2 has member seven at offset 16. 

ハッシュテーブルのエントリに追加します。

しかし、私はこの作業を維持するのに必要なメンテナンスの努力をどの程度重要視すべきかを十分に強調することはできません。コードベースに厳密なコーディング基準があり、誰かがこのコードジェネレータージェネレーターを十分によく知っていれば、構造を正しく解析し、複数の開発者が長期的にそれを維持することができます。私はなぜこのようなものを使わないのか分からない。それ以外の場合は、重い負担となり、プロジェクトの残りの部分を引き下げる可能性があります。特に、コードジェネレータージェネレーターを維持するのに十分な知識を持っている開発者が一人しかいない場合、それらは出てきます。私の意見では、特定の人に依存しているプロジェクトはありません。

ご不明な点がございましたら、お気軽にコメントしてください。私は説明しようとします。しかし、私は437行で、その本来の概念のような(Cコードの出力は、これまでに書いた他の例については過去に行ったことがあるので)全体としてmember-offset-generator.bashスクリプトを説明しません。スクリプトによって作成されたCプログラム)複雑さ、それは誰にも努力する価値はありません。

+0

問題に対処するために大変感謝してくれてありがとう。大変感謝しています。この考えは私のために働くでしょう。 –