2011-04-05 14 views
7

हैलो मैं सी में सामान्य डेटा प्रकार के रूप में शून्य * का उपयोग करने की कोशिश कर रहा हूं। मैं जो चाहता हूं वह एक तंत्र है जिसका उपयोग मैं कुछ भी स्टोर कर सकता हूं और कुछ भी प्राप्त कर सकता हूं। मैंने कुछ कोड लिखा, लेकिन यह पिछले मामले में असफल रहा है। क्या कोई भी कोड को देख सकता है, अगर आपके पास कोई अन्य विचार है तो कृपया मुझे बताएं।सी में सामान्य डेटा प्रकार [void *]

मुझे पता है कि मैं स्टोर करने की कोशिश कर रहा हूं, इसलिए उस समय मुझे डेटा प्रकार पता है, लेकिन प्रतिशोध के दौरान मुझे केवल शुरुआती पता और आकार पता है।

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <assert.h> 


static void store(void *destination, void *source, size_t size) { 
    memcpy ((char*)destination, source, size); 
} 
static void retrieve (void *destination, void *source, size_t size) { 
    memcpy (destination, (char*)source, size); 
} 

void *storage_char_ptr = (void*) malloc (sizeof(char*)); 
void *storage_int_ptr = (void*) malloc (sizeof(int*)); 
void *storage_int  = (void*) malloc (sizeof(int)); 

int main() { 

    int int_in = 65; 
    void *int_out_ptr; 
    int *ptr = (int*) malloc (sizeof(int)); 
    memcpy (ptr, &int_in, sizeof(int)); 

    store (storage_int_ptr, &ptr, sizeof(int*)); 
    retrieve (&int_out_ptr, storage_int_ptr, sizeof(int*)); 
    assert (int_in == *(int*)int_out_ptr); 

    char *char_in = "HelloWorld!!"; 
    void *char_out; 
    store (storage_char_ptr, &char_in, sizeof(char*)); 
    retrieve (&char_out, storage_char_ptr, sizeof(char*)); 
    assert (strcmp (char_in, (char*)char_out) == 0); 

    char_in = _strdup("HelloWorld!!"); 
    store (storage_char_ptr, &char_in, sizeof(char*)); 
    retrieve (&char_out, storage_char_ptr, sizeof(char*)); 
    assert (strcmp (char_in, (char*)char_out) == 0); 

    /* This is where it is failing */ 
    int_in = 55; 
    void* int_out; 
    store (storage_int, &int_in, sizeof(int)); 
    retrieve (&int_out, storage_int, sizeof(int)); 
    assert (55 == *(int*)int_out); 

} 
+2

यह कैसे विफल रहा है? – MByD

उत्तर

9

चयनित प्रकार की गणना के साथ संयुक्त void* की बजाय आपको आवश्यक सभी प्रकार के संघ का उपयोग करना बेहतर होगा। यदि आपके पास प्रकारों की सीमित सूची नहीं है, तो void* सूचक और कम से कम आवंटित आकार वाली संरचना का उपयोग करें।

उदाहरण के लिए:

struct ANYTYPE 
{ 
    enum { 
     typUndefined, 
     typInt,   // 1 
     typUint, 
     typString, 
     typByteString, 
     typLong,   // 5 
     typFloat, 
     typDouble, 
    } iType; 

    void* value; 
}; 

यह आप आसानी से सही ढंग से स्मृति पुनःआवंटन और सामान्य कोड है कि मूल्य पर कार्रवाई करने से पहले प्रकार का विश्लेषण कर सकते बनाने के लिए अनुमति देता है। आप संघ के साथ एक समान विकल्प होता है:,

struct ANYTYPE 
{ 
    enum { 
     typUndefined, 
     typInt,   // 1 
     typUint, 
     typString, 
     typLong 
    } iType; 

    union 
    { 
     int i; 
     unsigned int u; 
     char* s; 
     long l; 
    } value; 
} 

एक संघ में सभी तत्वों को एक ही स्मृति स्थान का उपयोग कर रहे हैं और केवल एक एक्सेस किया जाना चाहिए। गणना के माध्यम से, आप जानते हैं कि किस तत्व को एक्सेस किया जाना चाहिए। बेशक आपके पास ओओ सुरक्षा नहीं है जैसे सी ++ में, इसलिए आपको यह सुनिश्चित करने की ज़रूरत है कि आप इस संरचना का उपयोग करते हुए हर जगह गणना को सही ढंग से सेट करें।

+0

@ बेनोइट थियरी, क्या आप कृपया अधिक बता सकते हैं, यदि आपके पास कोई उदाहरण है। मैं संरचना समाधान में intrested हूँ। – Avinash

+0

धन्यवाद बेनोइट, लेकिन मेरे पास प्रकारों की सीमित सूची है, तो क्या आप संरचना दृष्टिकोण पर अधिक प्रकाश डाल सकते हैं। – Avinash

+0

@ एविनाश, यहां तक ​​कि आपके पास प्रकारों की एक सीमित सूची है, संघ अभी भी बेहतर है। एक संघ लगभग एक संरचना के समान है। –

5

आप सूचक int_out में पूर्णांक मान (55) कॉपी कर रहे हैं:

यहाँ कोड है। (अगले 4 से 8 में बाइट्स) में जो कुछ भी झूठ का पता 55, यह इसके बजाय संख्यात्मक मूल्य 55 की संभावना नहीं है,

int int_in = 55; 
int int_out; 
store (storage_int, &int_in, sizeof(int)); 
retrieve (&int_out, storage_int, sizeof(int)); 
assert (55 == int_out); 

एक और समस्या की कोशिश अपने कोड के साथ: char_in/char_out भागों में, आप कर रहे हैं केवल सूचक मूल्यों की प्रतिलिपि बनाते हैं। यह काम करता है (इस मामले में), लेकिन संभवतः आप वास्तव में क्या इरादा नहीं रखते हैं, या है ना? क्या तुम सच में सूचक संग्रहीत करना चाहते हैं, तो आप store और retrieve भाग को छोड़ सकते हैं:

char* str_in = "hello, world";  // Original value 
void* generic_ptr = str_in;  // ... a pointer to which is stored in some data structure 
char* str_out = generic_ptr;  // ... which can later be retrieved 

रूप में अच्छी तरह से काम करेगा। दूसरी ओर:

: यदि आप स्ट्रिंग की वास्तविक सामग्री को संग्रहीत करने का इरादा है, आप इसे स्ट्रिंग के प्रतिलिपि को (अपने दूसरे उदाहरण के रूप में की तरह, _strdup के साथ) कॉपी करने के लिए, और बचाने के सूचक है
char* str_in = _strdup("copy me"); 
void* generic_ptr = str_in;   // Gets stored in your data structures 
4

आप पॉइंटर को ओवरराइट कर रहे हैं, फिर इसे डिफ्रेंस कर रहे हैं ... यदि आपका कोड ऐसा दिखाई देता है तो यह काम करेगा ... लेकिन ऐसा नहीं हो सकता है कि आप क्या कर रहे हैं।

int int_out; 
    store (storage_int, &int_in, sizeof(int)); 
    retrive (&int_out, storage_int, sizeof(int)); 
    assert (55 == int_out); 

या:

int *int_out; 
    store (storage_int, &int_in, sizeof(int)); 
    retrive (&int_out, storage_int, sizeof(int)); 
    assert (55 == (int)int_out); 

हालांकि, दूसरे मामले में यह थोड़ा संदिग्ध है, क्योंकि यह मानता है कि दोनों 'int' और 'int *' एक ही आकार के होते हैं, तो आप कर रहे हैं पुनर्प्राप्त करते समय दूसरे के शीर्ष पर स्टोर करने में सक्षम। मेरा मानना ​​है कि यह सभी प्रणालियों पर मामला नहीं है।

1

डिर्क पूरी तरह से सही है। एक और तरीका यह व्यक्त करने के लिए, में लाए डेटा डाल करने के लिए आवंटित कोई जगह नहीं है कि वहाँ है

कोशिश:।

int_in = 55; 
void* int_out = malloc (sizeof (int_in)); 
store (storage_int, &int_in, sizeof(int)); 
retrieve (int_out, storage_int, sizeof(int)); 
assert (55 == *(int*)int_out); 
बेशक

, आप malloc के अलावा कुछ() का उपयोग कर सकते हैं, और वहाँ यह देखने के लिए कोई जांच नहीं है कि malloc() विफल रहा है, लेकिन यह आपको सही रास्ते पर ले जाना चाहिए।

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