sizeof tek yapı üyesi C


109

Başka bir yapıya bağımlı olan bir yapı bildirmeye çalışıyorum. sizeofGüvenli / bilgiçlikçi olmak için kullanmak istiyorum .

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

Şimdi child_tile aynı boyutta bir yapı bildirmek istiyorum parent_t.text.

Bunu nasıl yapabilirim? (Aşağıdaki sözde kod.)

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

Ben birkaç farklı şekilde çalıştı parent_tve struct _parentancak benim derleyici kabul etmeyecektir.

Bir numara olarak, bu işe yarıyor gibi görünüyor:

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

O bildirmek mümkün mü child_tkullanılmadan dummy?

Yanıtlar:


202

Arabellek boyutunu a ile tanımlamak #definedeyimsel bir yol olsa da, başka bir yöntem şöyle bir makro kullanmak olacaktır:

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

ve şu şekilde kullanın:

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

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

Aslında sizeof((type *)0)->member)sabit bir ifade olmasına izin verildiğine biraz şaşırdım . Güzel şeyler.


2
Vay be, sizeof ((type *) 0) -> üye) 'nin çalıştığını bilmiyordum. Şu anda geliştirme makinemde değilim, ancak bu tüm derleyiciler için çalışıyor mu? Bunun için teşekkürler Joey.
— Gangadhar

4
@Gangadhar: Evet, bu tüm derleyiciler için çalışıyor. İşleneni sizeofdeğerlendirilmez, bu nedenle boş göstericiye başvurunun kaldırılmasıyla ilgili bir sorun yoktur (çünkü gerçekte başvurulmamıştır).
— James McNellis

4
olağanüstü? düz C89, <stddef.h> 'de "offsetof" uygulamasına veya aynı uygulamaya bakın eetimes.com/design/other/4024941/…
— user411313

1
@XavierGeoffrey: Burada sizeof, ((tür *) 0) -> üye türünü belirtir ve bu türün boyutunu döndürür. ((tür *) 0) yapı türünün boş göstericisidir. ptr-> üye (derleme zamanında), üye türü olan bir ifadedir. Sizeof içindeki kod asla çalışmaz (çalışsaydı, program segfault olurdu!). Yalnızca sizeof içindeki değer türüne bakılır.
— Joey Adams

1
Offset_of için Vikipedi sayfası Ben tüm derleyiciler ile çalışma konuda bahse girmezdim C standardına göre tanımsız davranış olarak notlar bu yüzden.
— Graeme

30

Şu anda geliştirme makinemde değilim, ancak aşağıdakilerden birini yapabileceğinizi düşünüyorum:

sizeof(((parent_t *)0)->text)

sizeof(((parent_t){0}).text)


Düzenleme : Joey'nin bu tekniği kullanarak önerdiği member_size makrosunu beğendim, bunu kullanacağımı düşünüyorum.


12
İkinci form çok güzel (ve kavramsal olarak temiz, çünkü boş işaretçiler içermiyor), ancak bunun C99 öncesi derleyicilerde mümkün olmadığını belirtmelisiniz.
— R .. GitHub BUZA YARDIM ETMEYİ DUR

11

FIELD_SIZEOF(t, f)Linux çekirdeğini kullanmakta özgürsünüz . Sadece şu şekilde tanımlanır:

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

Bu tür makrolardan başka cevaplarda bahsedilmektedir. Ancak önceden tanımlanmış bir makroyu kullanmak daha taşınabilirdir.


4
FIELD_SIZEOF, linux / kernel.h'de bulunan, modern Linux çekirdeklerinde kullanılan makrodur
— Colin Ian King

@ColinIanKing Yani bu genel olarak yapı üye boyutunu elde etmenin deyimsel bir yolu mu? Modern C'de bir Standartta böyle bir makro henüz yer almadı mı?
— St.Antario

Bildiğim
— Colin Ian King

Yakın zamanda linux / kernel.h'den kaldırıldı .
— Andriy Makukha

10

Bir önişlemci yönergesi kullanın, yani #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 ;

Nyan ile aynı fikirde. Diğer çözümler işe yarıyor, ancak farklı bir şey başaramıyor. Daha açık olmak istiyorsanız, buna PARENT_TEXT_LEN veya eşit derecede açıklayıcı bir ad verin. Daha sonra, arabellek uzunluğu hatalarını önlemek için kodunuz boyunca koşul ifadelerinde de kullanabilirsiniz ve basit tamsayı karşılaştırmaları yapacaktır.
— dave mankoff

1
Bence sizeof çözümünün avantajı, bir kitaplıkta veya başka bir yerde tanımlanmışsa, ana yapıya erişmeniz gerekmemesidir.

@evilclown: ama şunu yaparsınız: "char text [member_size (Parent, text)];" "Ebeveyn" e başvurmanız gerekir.
— dave mankoff

3
beni anladığını sanmıyorum üst yapının drand48_data(stdlib.h içinde tanımlı) olduğunu ve sizeof değerini istediğinizi varsayalım __x. Eğer olamaz #define X_LEN 3kullanarak, stdlib.h değiştirebilir ve member_sizemakul bir durum gibi görünüyor ebeveyn yapı kaynağına erişimi olmadığı zamanlarda üstündür.

5

Boyut için bir önişlemci yönergesini şu şekilde kullanabilirsiniz:

#define TEXT_MAX_SIZE 255

ve bunu hem ebeveynde hem de çocukta kullanın.


evet, ama bu her zaman bir seçenek değildir: mesela, linux'ta /usr/include/bits/dirent.halanın boyutu d_name(struct direct/ dirent) artık tanımlanmıyor, DIRSIZkodlanmış; böylece sizeof()bağımlılık tutmak için tek temiz bir yol olarak görünmektedir
— ジョージ

5

struct.h zaten tanımlanmış mı

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

böylece yapabilirsin

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

ancak başlığa bakıldığında, bunun bir BSD olayı olduğu ve ANSI veya POSIX standardı olmadığı anlaşılıyor. Bunu bir Linux makinesinde denedim ve işe yaramadı; sınırlı kullanışlılık.


4

Bir başka olasılık da bir tür tanımlamak olabilir. İki alan için de aynı büyüklükte olmasını sağlamak istemeniz, onlar için aynı anlamlara sahip olduğunuzun bir göstergesi sanırım.

typedef char description[255];

ve sonra bir tarla var

description text;

her iki türünüzde.


4

c ++ çözümü:

sizeof (Type :: member) da çalışıyor gibi görünüyor:

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

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

3
Soru C ++ ile değil, C ile ilgili.
— Marc

0

@ joey-adams, teşekkür ederim! Ben de aynı şeyi arıyordum, ancak char olmayan dizi için ve şu şekilde bile mükemmel çalışıyor:

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

Beklendiği gibi 20 döndürür.

Ve @ brandon-horsley, bu da iyi çalışıyor:

#define member_dim(type, member) sizeof(((type){0}).member) / \
                                 sizeof(((type){0}).member[0])
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.