2013-02-02 58 views
6

मेरे पास बहुत सारे फ़ंक्शन हैं जो तर्क के रूप में स्ट्रिंग की अपेक्षा करते हैं, जिसके लिए मैं char* का उपयोग करता हूं, लेकिन मेरे सभी फ़ंक्शंस जो बाइट-सरणी की अपेक्षा करते हैं, char* का भी उपयोग करते हैं।स्ट्रिंग और बाइट सरणी के बीच अंतर करें?

समस्या यह है कि मैं आसानी से एक स्ट्रिंग-फ़ंक्शन में बाइट-सरणी को पार करने की गलती कर सकता हूं, जिससे सभी प्रकार के अतिप्रवाह होते हैं, क्योंकि शून्य-टर्मिनेटर नहीं मिल सकता है।

यह आमतौर पर किस प्रकार से संबंधित है? मैं uint8_t लेने के लिए अपने सभी बाइट-सरणी कार्यों को बदलने की कल्पना कर सकता हूं, और फिर जब मैं स्ट्रिंग पास करता हूं तो संकलक साइन-नेस के बारे में चेतावनी देगा। या यहां सही दृष्टिकोण क्या है?

+0

एक बाइट-सरणी के लिए एक रैपर बनाएं ?? –

+0

@ वॉननहिल्ट्स मैं नहीं देखता कि यह मेरी समस्या का हल कैसे करता है? – Muis

+0

एक स्ट्रिंग * एक बाइट सरणी है। चूंकि आप वास्तव में सी में सरणी नहीं पारित कर सकते हैं, लेकिन पहले तत्व के लिए केवल एक सूचक, आप आमतौर पर एक आकार को पारित करना होगा। बस जांचें कि सरणी में शून्य मान है या नहीं। यदि ऐसा होता है, तो यह एक "स्ट्रिंग" है। अन्यथा, यह नहीं है। –

उत्तर

1

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

  • एक char वस्तु पर एक सूचक (इस सूचक प्रकार के "आधिकारिक" परिभाषा है)
  • एक char सरणी
  • एक स्ट्रिंग

ज्यादातर मामलों जहां है में संभव है सी मानक में mondern इंटरफेस एक untyped बाइट ar के लिए void* का उपयोग करता है रे, और आपको शायद उस सम्मेलन का पालन करना चाहिए, और केवल स्ट्रिंग के लिए char* का उपयोग करना चाहिए।

char[] स्वयं शायद ही कभी इस तरह उपयोग किया जाता है; मैं इनके लिए बहुत से उपयोग मामलों की कल्पना नहीं कर सकता। यदि आप उन्हें संख्याओं के रूप में सोचते हैं तो आपको signed या unsigned संस्करण का उपयोग करना चाहिए, यदि आप उन्हें थोड़ा पैटर्न unsigned char के रूप में देखते हैं तो आपकी पसंद होनी चाहिए।

तुम सच में समारोह पैरामीटर के रूप में एक सरणी (char या नहीं) आप स्पष्ट रूप से यह संकेत करके अपने कोड के आकस्मिक पाठक के लिए है कि इस तथ्य चिह्नित कर सकते हैं इसका मतलब यह हैं:

void toto(size_t n, char A[const n]); 

यह

void toto(size_t n, char *const A); 
के बराबर है

लेकिन आपके इरादे को स्पष्ट बनाता है। और भविष्य में ऐसे उपकरण भी हो सकते हैं जो आपके लिए जांच कर रहे सीमाएं करें।

2

मैं आम तौर पर चारों ओर

बनाने के निम्नलिखित

typedef struct { 
    unsigned char* data; 
    unsigned long length; 
    unsigned long max_length; 
} array_t; 

की तरह एक सरणी कुछ तो array_t पारित * और सरणी कार्यों कि array_t ले *

void array_create(array_t* a, unsgined long length) // allocates memory, sets the max_length, zero length 

void array_add(array_t* a, unsigned char byte) // add a byte 

आदि

+1

शायद 'हस्ताक्षर किए गए लंबे' –

+0

हाँ के बजाय 'size_t' का उपयोग करना बेहतर होगा, आप सही हैं –

0

लिखें बनाने स्ट्रिंग और बाइट्स दोनों को संभालने के लिए एक आम संरचना।

struct str_or_byte 
{ 
    int type; 
    union 
    { 
     char *buf; 
     char *str; 
    }pointer; 
    int buf_length; 
} 

तो type तो pointer.buf केवल buf_length तक पहुँचने के स्ट्रिंग नहीं है। अन्यथा सीधे pointer.str पर buf_length की जांच किए बिना पहुंचें और इसे निरस्त समाप्त स्ट्रिंग के रूप में बनाए रखें।

या तो केवल लंबाई को ध्यान में रखते हुए बाइट सरणी के रूप में स्ट्रिंग को बनाए रखें, स्ट्रिंग के लिए निरंतर समाप्त चार्टर न रखें।

struct str_or_byte 
{ 
    char *buf; 
    int buf_length; 
} 

और स्ट्रिंग मैनुपलेशन फ़ंक्शन का उपयोग न करें जो लंबाई पर विचार नहीं कर रहे हैं। strncpy, strncat, strncmp ... बजाय strcpy, strcat, strcmp ...

0

सी सम्मेलन का उपयोग कर सी। यहां मेरे द्वारा उपयोग किए जाने वाले नियम हैं (std lib के बाद फ़ैशन)

void foo(char* a_string); 

void bar(void* a_byte_array, size_t number_of_bytes_in_the_array); 

यह याद रखना आसान है। यदि आप एक सिंगल * पीआरटी पास कर रहे हैं, तो यह एक शून्य-समाप्त चार सरणी होनी चाहिए।

 संबंधित मुद्दे

  • कोई संबंधित समस्या नहीं^_^