web-dev-qa-db-ja.com

Cのsizeof単一構造体メンバー

別の構造体に依存する構造体を宣言しようとしています。 sizeofを使用して安全性を高めたいです。

typedef struct _parent
{
  float calc ;
  char text[255] ;
  int used ;
} parent_t ;

次に、child_tと同じサイズのparent_t.text構造体を宣言します。

これどうやってするの? (以下の擬似コード。)

typedef struct _child
{
  char flag ;
  char text[sizeof(parent_t.text)] ;
  int used ;
} child_t ;

parent_tstruct _parentでいくつかの異なる方法を試しましたが、私のコンパイラは受け入れません。

トリックとして、これはうまくいくようです:

parent_t* dummy ;
typedef struct _child
{
  char flag ;
  char text[sizeof(dummy->text)] ;
  int used ;
} child_t ;

dummyを使用せずにchild_tを宣言することは可能ですか?

97
kevinarpe

_#define_を使用してバッファサイズを定義することは、それを行うための慣用的な方法の1つですが、別の方法は次のようなマクロを使用することです。

_#define member_size(type, member) sizeof(((type *)0)->member)
_

次のように使用します:

_typedef struct
{
    float calc;
    char text[255];
    int used;
} Parent;

typedef struct
{
    char flag;
    char text[member_size(Parent, text)];
    int used;
} Child;
_

実際、sizeof((type *)0)->member)が定数式としても許可されていることに少し驚いています。クール。

179
Joey Adams

プリプロセッサディレクティブ、つまり#defineを使用します。

#define TEXT_LEN 255

typedef struct _parent
{
  float calc ;
  char text[TEXT_LEN] ;
  int used ;
} parent_t ;

typedef struct _child
{
  char flag ;
  char text[TEXT_LEN] ;
  int used ;
} child_t ;
9
dave mankoff

LinuxカーネルではFIELD_SIZEOF(t, f)を自由に使用できます。次のように定義されています。

#define FIELD_SIZEOF(t, f) (sizeof(((t*)0)->f))

このタイプのマクロは、他の回答で言及されています。ただし、既に定義されているマクロを使用する方が移植性が高くなります。

7
Dmitry

次のようなサイズのプリプロセッサディレクティブを使用できます。

#define TEXT_MAX_SIZE 255

親と子の両方で使用します。

4
codaddict

別の可能性は、タイプを定義することです。 2つのフィールドのサイズを同じにしたいという事実は、それらのフィールドのセマンティクスが同じであることを示しています。

typedef char description[255];

そして、フィールドを持っています

description text;

両方のタイプで。

4
Jens Gustedt

c ++ソリューション:

sizeof(Type :: member)も同様に機能しているようです:

struct Parent
{
    float calc;
    char text[255];
    int used;
};

struct Child
{
    char flag;
    char text[sizeof(Parent::text)];
    int used;
};
4
korish

struct.hは既に定義されています。

#define fldsiz(name, field) \
    (sizeof(((struct name *)0)->field))

だからできる

#include <stdlib.h> /* EXIT_SUCCESS */
#include <stdio.h>  /* printf */
#include <struct.h> /* fldsiz */

struct Penguin {
    char name[128];
    struct Penguin *child[16];
};
static const int name_size  = fldsiz(Penguin, name) / sizeof(char);
static const int child_size = fldsiz(Penguin, child) / sizeof(struct Penguin *);

int main(void) {
    printf("Penguin.name is %d chars and Penguin.child is %d Penguin *.\n",
           name_size, child_size);
    return EXIT_SUCCESS;
}

しかし、ヘッダーを見ると、これはBSDのものであり、ANSIまたはPOSIX標準ではないようです。 Linuxマシンで試してみたが、うまくいきませんでした。限られた有用性。

4
Neil Edelman

@ joey-adams、ありがとう!私は同じものを探していましたが、非char配列については、この方法でも完全に機能します:

#define member_dim(type, member) sizeof(((type*)0)->member) / \
                                 sizeof(((type*)0)->member[0])

struct parent {
        int array[20];
};

struct child {
        int array[member_dim(struct parent, array)];
};

int main ( void ) {
        return member_dim(struct child, array);
}

期待どおり20を返します。

そして、@ brandon-horsley、これもうまくいきます:

#define member_dim(type, member) sizeof(((type){0}).member) / \
                                 sizeof(((type){0}).member[0])
0
Grandma