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.