C में sizeof सिंगल स्ट्रक्चर मेंबर


109

मैं एक ऐसी संरचना को घोषित करने का प्रयास कर रहा हूं जो किसी अन्य संरचना पर निर्भर है। मैं 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_tऔर struct _parent, लेकिन मेरा कंपाइलर स्वीकार नहीं करेगा।

एक चाल के रूप में, यह काम करने लगता है:

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

क्या इसके child_tउपयोग के बिना घोषित करना संभव है dummy?

जवाबों:


202

हालाँकि इसे करने के लिए बफर आकार #defineको एक मुहावरेदार तरीके से परिभाषित करना, दूसरा इस तरह से एक मैक्रो का उपयोग करना होगा:

#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)एक स्थिर अभिव्यक्ति के रूप में भी अनुमति दी गई है। सुन्दर सामान।


2
वाह, मैं नहीं जानता था आकार ((प्रकार *) 0) -> सदस्य) काम करता है। अब मेरे देव मशीन पर नहीं है, लेकिन यह सभी संकलक के लिए काम करता है? उस जॉय के लिए धन्यवाद।
गंगाधर

4
@ गंगाधर: हां, यह सभी कंपाइलरों के लिए काम करता है। के ऑपरेंड का sizeofमूल्यांकन नहीं किया जाता है, इसलिए नल पॉइंटर को डीफ़्रॉफ़ेंस करने के साथ कोई समस्या नहीं है (क्योंकि यह वास्तव में डीरेफ़र्ड नहीं है)।
जेम्स मैकनेलिस

4
आश्चर्यजनक? इसका सादा C89, <stddef.h> में "ऑफसेटऑफ़" का कार्यान्वयन देखें या समान कार्यान्वयन eetimes.com/design/other/4024941/…
user411313

1
@XavierGeoffrey: यहां, आकार प्रकार ((* * 0) के प्रकार को प्रभावित करता है) -> सदस्य, और उस प्रकार के आकार को लौटाता है। ((प्रकार *) 0) केवल संरचनात्मक प्रकार का एक शून्य सूचक है। ptr-> सदस्य (संकलन के समय) एक अभिव्यक्ति है जिसका प्रकार सदस्य का होता है। साइज़ोफ़ के भीतर का कोड कभी नहीं चलता (यदि ऐसा होता, तो प्रोग्राम सीफ़ॉल्ट हो जाता!)। केवल आकार के भीतर मूल्य का प्रकार देखा जाता है।
जॉय एडम्स

1
Offset_of के लिए विकिपीडिया पृष्ठ सी मानक के अनुसार अपरिभाषित व्यवहार के रूप में नोटों इस, तो मैं यह सब compilers के साथ काम करने पर यकीन नहीं होता।
ग्रीम

30

मैं अभी अपनी विकास मशीन पर नहीं हूं, लेकिन मुझे लगता है कि आप निम्न में से एक कर सकते हैं:

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

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


संपादित करें : मुझे यह पसंद है कि मैं इस तकनीक का उपयोग करके सदस्य_साइज मैक्रो जॉय का सुझाव देता हूं, मुझे लगता है कि मैं इसका उपयोग करूंगा।


12
दूसरा रूप बहुत अच्छा है (और वैचारिक रूप से साफ है कि इसमें अशक्त बिंदु शामिल नहीं हैं), लेकिन आपको यह उल्लेख करना चाहिए कि यह पूर्व-सी 99 संकलक में संभव नहीं है।
आर .. गिटहब स्टॉप हेल्पिंग ICE

11

आप FIELD_SIZEOF(t, f)लिनक्स कर्नेल में उपयोग करने के लिए स्वतंत्र हैं । यह सिर्फ निम्नलिखित के रूप में परिभाषित किया गया है:

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

इस प्रकार के मैक्रो का उल्लेख अन्य उत्तरों में किया गया है। लेकिन पहले से परिभाषित मैक्रो का उपयोग करना अधिक पोर्टेबल है।


4
FIELD_SIZEOF आधुनिक लिनक्स कर्नेल में प्रयुक्त मैक्रो है, जो लिनक्स / कर्नेल में पाया जाता है।
कॉलिन इयान किंग

@ColinIanKing तो यह सामान्य में C का एक मुहावरेदार तरीका है जिससे संरचनात्मक सदस्य आकार प्राप्त कर सकता है? क्या ऐसा मैक्रो अभी तक आधुनिक C में एक मानक में शामिल नहीं है?
सेंटऑनारियो

मेरे ज्ञान में मानक C में कोई समतुल्य स्थूल नहीं है
कॉलिन इयान किंग

इसे हाल ही में linux / kernel.h से हटाया गया था ।
एंड्री मकुक्खा

10

प्रीप्रोसेसर निर्देश का प्रयोग करें, अर्थात # डिफाइन:

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

नयन से सहमत। अन्य समाधान काम करते हैं, लेकिन कुछ अलग नहीं करते हैं। यदि आप अधिक स्पष्ट होना चाहते हैं, तो इसे PARENT_TEXT_LEN या कुछ समान रूप से वर्णनात्मक कहें। फिर आप बफर लंबाई की त्रुटियों को रोकने के लिए इसे अपने कोड में सशर्त में भी उपयोग कर सकते हैं और यह सरल पूर्णांक तुलना कर रहा है।
mankoff

1
मुझे लगता है कि आकार के समाधान का लाभ यह है कि आपको मूल संरचना तक पहुंच की आवश्यकता नहीं है, अगर यह किसी लाइब्रेरी या कहीं और परिभाषित किया गया है।

@evilclown: लेकिन आप ऐसा करते हैं: "चार पाठ [सदस्‍यता / अभिभावक, पाठ)];" आपको "जनक" का संदर्भ देना होगा।
mankoff

3
मुझे नहीं लगता कि आपने मुझे समझा है। मान लें कि मूल संरचना drand48_data(stdlib.h में परिभाषित की गई है) है और आप इसका आकार चाहते हैं __x। माता-पिता की संरचना के स्रोत तक पहुंच नहीं होने पर, आप उचित स्थिति की तरह प्रतीत नहीं होने पर #define X_LEN 3stdlib.h का उपयोग नहीं कर सकते और बदल सकते हैं member_size

5

आप आकार के लिए एक प्रीप्रोसेसर निर्देश का उपयोग कर सकते हैं:

#define TEXT_MAX_SIZE 255

और माता-पिता और बच्चे दोनों में इसका उपयोग करें।


हां, लेकिन यह हमेशा एक विकल्प नहीं होता है: कहते हैं, लाइनक्स /usr/include/bits/dirent.hमें d_nameक्षेत्र का आकार (संरचना direct/ dirent) DIRSIZकिसी भी अधिक लेकिन हार्ड-कोडित के रूप में परिभाषित नहीं किया गया है ; तो sizeof()निर्भरता रखने का एकमात्र साफ तरीका लगता है
ー ジ

5

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

लेकिन, शीर्ष लेख में देखने पर, ऐसा प्रतीत होता है कि यह एक बीएसडी चीज है न कि एएनएसआई या पोसिक्स मानक। मैंने इसे एक लिनक्स मशीन पर आज़माया और यह काम नहीं किया; सीमित उपयोगिता।


4

एक अन्य संभावना एक प्रकार को परिभाषित करने की होगी। तथ्य यह है कि आप दो क्षेत्रों के लिए एक ही आकार सुनिश्चित करना चाहते हैं एक संकेतक है कि आपके पास उनके लिए समान शब्दार्थ है, मुझे लगता है।

typedef char description[255];

और फिर एक मैदान है

description text;

आपके दोनों प्रकारों में।


4

सी ++ समाधान:

sizeof (प्रकार :: सदस्य) के रूप में अच्छी तरह से काम करने लगता है:

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

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

3
प्रश्न C के बारे में है, C ++ के बारे में नहीं।
मार्क

0

@ जॉय-एडम्स, धन्यवाद! मैं एक ही चीज़ खोज रहा था, लेकिन गैर चार सरणी के लिए और यह इस तरह से भी पूरी तरह से ठीक काम करता है:

#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 रिटर्न देता है।

और, @ ब्रैंडन-हॉर्सली, यह भी अच्छा काम करता है:

#define member_dim(type, member) sizeof(((type){0}).member) / \
                                 sizeof(((type){0}).member[0])
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.