टाइपडिफ तय लंबाई सरणी


210

मुझे एक 24-बिट डेटा char[3]प्रकार को परिभाषित करना है। मैं प्रकार का प्रतिनिधित्व करने के लिए उपयोग कर रहा हूं । मैं typedef कर सकते हैं char[3]करने के लिए type24? मैंने इसे एक कोड नमूने में आज़माया। मैंने typedef char[3] type24;अपनी हेडर फ़ाइल में रखा । संकलक ने इसकी शिकायत नहीं की। लेकिन जब मैंने void foo(type24 val) {}अपनी सी फ़ाइल में फ़ंक्शन को परिभाषित किया , तो उसने शिकायत की। मैं type24_to_int32(type24 val)इसके बजाय कार्यों को परिभाषित करने में सक्षम होना चाहूंगा type24_to_int32(char value[3])

जवाबों:


320

टाईपडेफ होगा

typedef char type24[3];

हालाँकि, यह शायद एक बहुत बुरा विचार है, क्योंकि परिणामी प्रकार एक सरणी प्रकार है, लेकिन इसके उपयोगकर्ता यह नहीं देखेंगे कि यह एक सरणी प्रकार है। यदि फ़ंक्शन तर्क के रूप में उपयोग किया जाता है, तो इसे संदर्भ द्वारा पारित किया जाएगा, न कि मूल्य द्वारा, और इसके sizeofलिए यह गलत होगा।

एक बेहतर समाधान होगा

typedef struct type24 { char x[3]; } type24;

आप शायद unsigned charइसके बजाय का उपयोग करना चाहते हैं char, क्योंकि बाद में कार्यान्वयन-परिभाषित हस्ताक्षर है।


10
क्या कोई अच्छा दस्तावेज है, जो पैरामीटर के रूप में टाइप किए गए एफ़ेड को पास करने से जुड़े कोने के मामलों का वर्णन करता है? उदाहरण के लिए, एक समारोह एक पैरामीटर लेता है, तो type24 foo, क्या आकार, प्रकार, और के अर्थ होगा foo, *foo, **foo, &foo, और &&foo? क्या वर्षों में ऐसे किसी भी भाव के अर्थ और वैधता बदल गई है?
सुपरकाट

4
संभवतः 24-बिट डेटा प्रकार के रूप में संरचना पैकिंग चेतावनी का उल्लेख करने योग्य है, आरजीबी छवि डेटा जैसे अलग-अलग परिभाषित पैकिंग शब्दार्थों के साथ कुछ करने के लिए मैप करने का इरादा हो सकता है।
श १

2
@ sh1: सभी आधुनिक वास्तविक दुनिया के ABI के बारे में मुझे पता है - यहां तक ​​कि जहां गलत तरीके से पहुंच बहुत महंगी है - संरचनाओं को संरचना के बिना उनके सदस्यों की तुलना में मजबूत संरेखण आवश्यकताएं नहीं मिलती हैं। बेशक ओपी या इस दृष्टिकोण का उपयोग करने वाले किसी अन्य व्यक्ति को मेरे दावे को सत्यापित करना चाहिए कि क्या यह उनके कार्यक्रम के व्यवहार और पोर्टेबिलिटी के लिए मायने रखता है।
आर .. गिटहब स्टॉप हेल्पिंग ICE

4
@ आर .. इसका एक हिस्सा भ्रामक है - सी में, सरणियों को हमेशा संदर्भ से पारित किया जाता है, अर्थात, यदि आप किसी फ़ंक्शन के तर्क के रूप में पारित सरणी को संशोधित करते हैं, तो आप फ़ंक्शन के संदर्भ में ही नहीं, विश्व स्तर पर भी ऐसा करते हैं। यह कहा जा रहा है, एक यह भी तर्क दे सकता है कि सी सरणियों को हमेशा मूल्य से पारित किया जा रहा है क्योंकि हम बस पहले तत्व के पते से गुजरते हैं, जिसे कैली स्टैक पर स्टैक पर कॉपी किया जाता है। हालांकि, दोनों मामलों में, जवाब भ्रामक है।
baibo

1
@ बोबोगो: यह पैकिंग नहीं है, यह केवल गैर-गंभीर पैडिंग का सम्मिलन है। संरचना का संरेखण उसके सदस्यों में से किसी एक का अधिकतम संरेखण है, जिसमें से सभी में संरेखण है 1.
R .. GitHub STOP HELPING ICE

49

तुम्हें चाहिए

typedef char type24[3];

सी प्रकार की घोषणाएं अजीब हैं। यदि आप उस प्रकार का वैरिएबल घोषित कर रहे हैं, तो आप ठीक उसी प्रकार टाइप करते हैं, जैसे कि चर नाम होगा।


33

से आर .. के जवाब :

हालाँकि, यह संभवतः एक बहुत बुरा विचार है, क्योंकि परिणामी प्रकार एक सरणी प्रकार है, लेकिन इसके उपयोगकर्ता यह नहीं देखेंगे कि यह एक सरणी प्रकार है। यदि एक फ़ंक्शन तर्क के रूप में उपयोग किया जाता है, तो इसे संदर्भ द्वारा पारित किया जाएगा, मूल्य द्वारा नहीं, और इसके लिए आकार फिर गलत होगा।

जो उपयोगकर्ता यह नहीं देखते हैं कि यह एक सरणी है, सबसे अधिक संभावना है कि वे इस तरह से कुछ लिखेंगे (जो विफल):

#include <stdio.h>

typedef int twoInts[2];

void print(twoInts *twoIntsPtr);
void intermediate (twoInts twoIntsAppearsByValue);

int main () {
    twoInts a;
    a[0] = 0;
    a[1] = 1;
    print(&a);
    intermediate(a);
    return 0;
}
void intermediate(twoInts b) {
    print(&b);
}

void print(twoInts *c){
    printf("%d\n%d\n", (*c)[0], (*c)[1]);
}

यह निम्नलिखित चेतावनियों के साथ संकलित करेगा:

In function intermediate’:
warning: passing argument 1 of print from incompatible pointer type [enabled by default]
    print(&b);
     ^
note: expected int (*)[2]’ but argument is of type int **’
    void print(twoInts *twoIntsPtr);
         ^

और निम्नलिखित उत्पादन का उत्पादन करता है:

0
1
-453308976
32767

13

C में मान द्वारा एरे को फ़ंक्शन पैरामीटर के रूप में पारित नहीं किया जा सकता है।

आप सरणी को एक संरचना में रख सकते हैं:

typedef struct type24 {
    char byte[3];
} type24;

और फिर उस मूल्य से गुजरें, लेकिन निश्चित रूप से इसका उपयोग करने के लिए कम सुविधाजनक है: x.byte[0]इसके बजाय x[0]

आपका फ़ंक्शन type24_to_int32(char value[3])वास्तव में पॉइंटर से गुजरता है, मूल्य से नहीं। यह बिल्कुल बराबर है type24_to_int32(char *value)और 3इसे नजरअंदाज किया जाता है।

यदि आप पॉइंटर द्वारा पास होने से खुश हैं, तो आप ऐरे से चिपक सकते हैं और कर सकते हैं:

type24_to_int32(const type24 *value);

यह एक पॉइंटर-टू-एरे पास करेगा, न कि पॉइंटर-टू-फर्स्ट एलिमेंट, इसलिए आप इसे इस प्रकार उपयोग करें:

(*value)[0]

मुझे यकीन नहीं है कि यह वास्तव में एक लाभ है, क्योंकि यदि आप गलती से लिखते हैं value[1]तो कुछ बेवकूफ होता है।


2
मुझे लगता है कि इस उत्तर का उल्लेख decayकहीं और किया जा सकता है (और हो सकता है कि यह इंगित करके कि स्थिति लौटने वाले सरणियों के लिए बदतर है - जो बिल्कुल काम नहीं करती है)।
फ्रेरिच राबे

9

सरणी प्रकार को फ़ंक्शन तर्क या टेम्प्लेट पैरामीटर के रूप में ठीक से उपयोग करने के लिए, टाइप किए गए के बजाय एक संरचना बनाएं, फिर एक operator[]संरचना में जोड़ें ताकि आप सरणी को कार्यक्षमता की तरह रख सकें:

typedef struct type24 {
  char& operator[](int i) { return byte[i]; }
  char byte[3];
} type24;

type24 x;
x[2] = 'r';
char c = x[2];

14
यह एक C प्रश्न है, C ++ नहीं। न तो सी में मौजूद चीजें हैं char&और न हीoperator[]
माइकल मॉरिस

3

यहां एक छोटा उदाहरण है कि टाइप्डिफ एरे को भ्रमित रूप से असंगत क्यों किया जा सकता है। अन्य जवाब एक समाधान प्रदान करते हैं।

#include <stdio.h>
typedef char type24[3];

int func(type24 a) {
        type24 b;
        printf("sizeof(a) is %zu\n",sizeof(a));
        printf("sizeof(b) is %zu\n",sizeof(b));
        return 0;
}

int main(void) {
        type24 a;
        return func(a);
}

इससे उत्पादन होता है

sizeof(a) is 8
sizeof(b) is 3

क्योंकि टाइप 24 एक पैरामीटर के रूप में एक पॉइंटर है। (सी में, सरणियों को हमेशा संकेत के रूप में पारित किया जाता है।) gcc8 संकलक डिफ़ॉल्ट रूप से, चेतावनी के साथ चेतावनी जारी करेगा।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.