यदि शून्य सूचक (शून्य *) दो डेटा प्रकारों में से एक है, तो कैसे सत्यापित करें?


10

मैं एक फ़ंक्शन लिख रहा हूं जहां मैं 2 typeएस मापदंडों को स्वीकार करना चाहता हूं ।

  • A string(चार *)
  • एक structureजहां वहाँ n तत्वों की संख्या होगी।

और इसे प्राप्त करने के लिए मैं एक साधारण void *प्रकार के पैरामीटर का उपयोग करने के बारे में सोच रहा हूं । लेकिन मुझे नहीं पता कि कैसे सत्यापित किया जाए कि पैरामीटर एक प्रकार का है या दूसरा, सुरक्षित रूप से।


10
आप नहीं कर सकते! बहुत कम से कम, आपको फ़ंक्शन में एक दूसरा पैरामीटर जोड़ना होगा, जो इंगित करता है कि किन void*बिंदुओं को।
एड्रियन मोल

4
... और अगर आपको कोई दूसरा पैरामीटर जोड़ना है, तो आप बस दो अलग-अलग फ़ंक्शन लिख सकते हैं func_strऔर func_structसंकलन समय पर टाइप चेक प्राप्त कर सकते हैं।
एम ओहम

हाँ, इसीलिए मैं सोच रहा था कि क्या यह केवल एक फंक्शन में संभव है
लोकलहोस्ट

1
आप सुरक्षित और पोर्टेबल तरीके से नहीं कर सकते। यदि आप पर्याप्त बहादुर हैं तो आप कोशिश करने और अनुमान लगाने की कोशिश कर सकते हैं कि स्मृति के पहले बाइट्स ऐसे दिखते हैं जैसे आप पात्रों के लिए क्या उम्मीद कर सकते हैं, लेकिन मैं उस सुरक्षित को नहीं कहूंगा ।
सर्ज बलेस्टा

यदि आप केवल स्ट्रिंग और संरचना कार्यों के लिए एक सामान्य नाम चाहते हैं, तो आप एक _Genericमैक्रो का उपयोग कर सकते हैं । आप स्व-पहचान प्रकार भी बना सकते हैं, उदाहरण के लिए टैग की गई यूनियनों के साथ , जिसका अर्थ होगा कि आप एक कच्ची char *स्ट्रिंग को पारित नहीं कर सकते । यह सब संभव है कि इसके लायक होने की तुलना में अधिक परेशानी हो।
एम ओहम

जवाबों:


12

का अनुवाद void*है
"प्रिय संकलक, यह एक सूचक है, इस पर आपके लिए कोई अतिरिक्त जानकारी नहीं है।"।

आमतौर पर कंपाइलर आपसे (प्रोग्रामर) बेहतर जानता है, क्योंकि उसे पहले मिली जानकारी और अब भी याद है और शायद आप भूल गए हों।
लेकिन इस विशेष मामले में, आप बेहतर जानते हैं या बेहतर जानने की जरूरत है। void*जानकारी के सभी मामलों में अन्यथा उपलब्ध है, लेकिन केवल प्रोग्रामर के लिए, जो "जानने के लिए होता है"। प्रोग्रामर को कंपाइलर को जानकारी प्रदान करना है - या रनिंग प्रोग्राम को बेहतर करना है, क्योंकि एक फायदा void*यह है कि रनटाइम के दौरान जानकारी बदल सकती है।
आमतौर पर यह कार्य के लिए अतिरिक्त मापदंडों के माध्यम से जानकारी देने के द्वारा किया जाता है, कभी-कभी संदर्भ के माध्यम से, अर्थात कार्यक्रम "पता करने के लिए होता है" (उदाहरण के लिए प्रत्येक संभव प्रकार के लिए एक अलग फ़ंक्शन है, जो भी फ़ंक्शन का अर्थ है प्रकार का अर्थ होता है)।

तो अंत void*में प्रकार की जानकारी शामिल नहीं है।
कई प्रोग्रामर इसे गलत समझते हैं "मुझे टाइप जानकारी जानने की आवश्यकता नहीं है"।
लेकिन विपरीत सच है, प्रोग्रामर की जिम्मेदारी void* बढ़ जाती है कि वह प्रकार की जानकारी पर नज़र रखे और प्रोग्राम / कंपाइलर को उचित रूप से प्रदान करे।


इसके अलावा, संकलक वास्तव में जानता है कि किस प्रकार का डेटा इंगित किया गया है। इसलिए यदि आप किसी void*फंक्शन में कूदते हैं , गलत टाइप के लिए जाते हैं, तो डेटा को डी-रेफर करते हैं ... फिर सभी तरह के अपरिभाषित व्यवहार को आमंत्रित किया जाता है।
लुंडिन

5

void*जेनेरिक प्रोग्रामिंग के लिए एक तरह से पदावनत हैं, ऐसी कई स्थितियाँ नहीं हैं जहाँ आपको इनका उपयोग आजकल करना चाहिए। वे खतरनाक हैं क्योंकि वे गैर-मौजूद प्रकार की सुरक्षा का नेतृत्व करते हैं। और जैसा कि आपने उल्लेख किया है, आप टाइप जानकारी भी खो देते हैं, जिसका अर्थ है कि आपको कुछ बोझिल चीजों को घसीटना enumहोगा void*

इसके बजाय आपको C11 का उपयोग करना चाहिए _Genericजो संकलन-समय पर प्रकारों की जांच कर सकते हैं और प्रकार की सुरक्षा जोड़ सकते हैं। उदाहरण:

#include <stdio.h>

typedef struct
{
  int n;
} s_t; // some struct

void func_str (const char* str)
{
  printf("Doing string stuff: %s\n", str);
}

void func_s (const s_t* s)
{
  printf("Doing struct stuff: %d\n", s->n);
}

#define func(x) _Generic((x),              \
  char*: func_str, const char*: func_str,  \
  s_t*:  func_s,   const s_t*:  func_s)(x) \


int main()
{
  char str[] = "I'm a string";
  s_t s = { .n = 123 };

  func(str);
  func(&s); 
}

constउन सभी प्रकारों के योग्य ( ) संस्करण प्रदान करना याद रखें जिन्हें आप समर्थन करना चाहते हैं।


यदि आप बेहतर संकलक त्रुटियां चाहते हैं, जब कॉलर गलत प्रकार से गुजरता है, तो आप स्थैतिक अभिक्रिया जोड़ सकते हैं:

#define type_check(x) _Static_assert(_Generic((x), \
  char*:   1,  const char*: 1,  \
  s_t*:    1,  const s_t*:  1,  \
  default: 0), #x": incorrect type.")

#define func(x) do{ type_check(x); _Generic((x),     \
  char*: func_str, const char*: func_str,            \
  s_t*:  func_s,   const s_t*:  func_s)(x); }while(0) 

यदि आप कुछ ऐसा प्रयास करते हैं जैसे int x; func(x);आपको संकलक संदेश मिलेगा "x: incorrect type"

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