नाम स्थान रखने से अधिकांश भाषाओं के लिए नो-ब्रेनर की तरह लगता है। लेकिन जहां तक मैं बता सकता हूं, एएनएसआई सी इसका समर्थन नहीं करता है। क्यों नहीं? भविष्य के मानक में इसे शामिल करने की कोई योजना है?
नाम स्थान रखने से अधिकांश भाषाओं के लिए नो-ब्रेनर की तरह लगता है। लेकिन जहां तक मैं बता सकता हूं, एएनएसआई सी इसका समर्थन नहीं करता है। क्यों नहीं? भविष्य के मानक में इसे शामिल करने की कोई योजना है?
जवाबों:
C के नाम स्थान हैं। एक संरचना टैग के लिए, और अन्य प्रकार के लिए। निम्नलिखित परिभाषा पर विचार करें:
struct foo
{
int a;
};
typedef struct bar
{
int a;
} foo;
पहले वाले का टैग है फू है, और बाद में टाइपो के साथ फू फू में बनाया गया है। फिर भी कोई नाम-टकराव नहीं होता। इसका कारण यह है कि संरचना टैग और प्रकार (अंतर्निहित प्रकार और टाइप किए गए टाइप) अलग नामस्थानों में रहते हैं।
C जो अनुमति नहीं देता है वह इच्छाशक्ति द्वारा नए नामस्थान बनाने की है। सी को भाषा में महत्वपूर्ण समझे जाने से पहले मानकीकृत किया गया था, और नामस्थान जोड़ने से पीछे की ओर भी अनुकूलता का खतरा होगा, क्योंकि इसे सही काम करने के लिए नाम की आवश्यकता है। मुझे लगता है कि इसका श्रेय तकनीकीताओं के कारण हो सकता है, दर्शनशास्त्र को नहीं।
संपादित करें: जेरेमीप ने सौभाग्य से मुझे सही किया और उन नामों का उल्लेख किया जो मैंने याद किया। लेबल के लिए और संरचना / संघ के सदस्यों के लिए भी नामस्थान हैं।
struct
परिभाषा अपने सदस्यों के लिए एक नया नाम स्थान घोषित करती है। मैं उस तथ्य का शोषण करने की वकालत नहीं कर रहा हूँ, और न ही मैं इसका शोषण करने के किसी भी माध्यम के बारे में जानता हूँ क्योंकि struct
इसमें स्थैतिक सदस्य नहीं हो सकते।
पूर्णता के लिए "लाभ" प्राप्त करने के कई तरीके हैं जो आपको नामस्थान से मिल सकते हैं, सी में।
मेरी पसंदीदा विधियों में से एक है एक संरचना का उपयोग करने के लिए विधि बिंदुओं का एक गुच्छा जो आपके पुस्तकालय / आदि के लिए इंटरफ़ेस है।
फिर आप इस संरचना का एक बाहरी उदाहरण का उपयोग करते हैं जिसे आप अपने सभी कार्यों की ओर इशारा करते हुए अपने पुस्तकालय के अंदर शुरू करते हैं। यह आपको क्लाइंट नेमस्पेस (वैश्विक दायरे में बाहरी चर के अलावा, संभवत: सैकड़ों तरीकों से ..) पर कदम रखे बिना अपनी लाइब्रेरी में अपना नाम सरल रखने की अनुमति देता है।
इसमें कुछ अतिरिक्त रखरखाव शामिल है लेकिन मुझे लगता है कि यह न्यूनतम है।
यहाँ एक उदाहरण है:
/* interface.h */
struct library {
const int some_value;
void (*method1)(void);
void (*method2)(int);
/* ... */
};
extern const struct library Library;
/* interface.h */
/* interface.c */
#include "interface.h"
void method1(void)
{
...
}
void method2(int arg)
{
...
}
const struct library Library = {
.method1 = method1,
.method2 = method2,
.some_value = 36
};
/* end interface.c */
/* client code */
#include "interface.h"
int main(void)
{
Library.method1();
Library.method2(5);
printf("%d\n", Library.some_value);
return 0;
}
/* end */
का उपयोग । वाक्यविन्यास क्लासिक Library_function () Library_some_value पद्धति पर एक मजबूत संघ बनाता है। हालाँकि कुछ सीमाएँ हैं, एक के लिए आप कार्यों के रूप में मैक्रोज़ का उपयोग नहीं कर सकते हैं।
library.method1()
?
.c
डिफ़ॉल्ट रूप से स्टैटिक में स्थिर करने की कोशिश कर रहा हूं , इस प्रकार केवल वही फ़ंक्शंस उजागर होते हैं const struct
जो .c
फ़ाइल में परिभाषा में स्पष्ट रूप से उजागर होते हैं ।
function1
/ और method2
दोनों के साथ संकलित करने पर / के वास्तविक पते की गणना करेगा । जब तक आप अपने स्वयं के स्रोत के साथ इस तरह के पुस्तकालयों को संकलित नहीं करते हैं, तब तक यह दृष्टिकोण अपने फ़ंक्शन कॉल में कुछ ओवरहेड जोड़ देगा। -O2
-flto
C के नाम स्थान हैं। वाक्य-विन्यास है namespace_name
। तुम भी उन्हें घोंसला बना सकते हैं general_specific_name
। और यदि आप हर बार नाम स्थान का नाम लिखे बिना नामों का उपयोग करने में सक्षम होना चाहते हैं, तो संबंधित हेडप्रोसेसर मैक्रोज़ को हेडर फ़ाइल में शामिल करें, जैसे।
#define myfunction mylib_myfunction
यह नामकरण और अन्य अत्याचारों की तुलना में बहुत अधिक क्लीनर है, कुछ भाषाएं नाम स्थान देने के लिए प्रतिबद्ध हैं।
ऐतिहासिक रूप से, सी कंपाइलर नामों को नहीं cdecl
जोड़ते हैं (वे विंडोज पर करते हैं, लेकिन कॉलिंग कन्वेंशन के लिए मैनलिंग में केवल अंडरस्कोर प्रीफ़िक्स जोड़ना शामिल है)।
इससे सी लाइब्रेरीज़ को अन्य भाषाओं (कोडांतरक सहित) से उपयोग करना आसान हो जाता है और यही एक कारण है कि आप अक्सर extern "C"
C ++ API के लिए रैपर देखते हैं।
सिर्फ ऐतिहासिक कारण। उस समय किसी नेमस्पेस जैसा कुछ होने के बारे में नहीं सोचा था। साथ ही वे वास्तव में भाषा को सरल रखने की कोशिश कर रहे थे। भविष्य में उनके पास यह हो सकता है
उत्तर नहीं, टिप्पणी नहीं। सी namespace
स्पष्ट रूप से परिभाषित करने का एक तरीका प्रदान नहीं करता है । इसमें परिवर्तनशील गुंजाइश है। उदाहरण के लिए:
int i=10;
struct ex {
int i;
}
void foo() {
int i=0;
}
void bar() {
int i=5;
foo();
printf("my i=%d\n", i);
}
void foobar() {
foo();
bar();
printf("my i=%d\n", i);
}
आप चर और कार्यों के लिए योग्य नामों का उपयोग कर सकते हैं:
mylib.h
void mylib_init();
void mylib_sayhello();
केवल नामस्थान से यह अंतर है कि आप using
आयात नहीं कर सकते हैं from mylib
।
namespace mylib { void init(); void say_hello(); }
जिनके साथ यह भी महत्वपूर्ण है (ईश)।
ANSI C का आविष्कार नाम स्थान से पहले किया गया था।
क्योंकि जो लोग सी में इस क्षमता को जोड़ना चाहते हैं, उन्होंने एक साथ नहीं मिला है और संकलक लेखक टीमों और आईएसओ निकायों पर कुछ दबाव डालने के लिए आयोजित किया है।
C, C ++ जैसे नामस्थानों का समर्थन नहीं करता है। C ++ नामस्थानों के क्रियान्वयन से नामों की गणना होती है। नीचे उल्लिखित दृष्टिकोण आपको सी ++ में नामस्थानों का लाभ प्राप्त करने की अनुमति देता है, जबकि ऐसे नाम हैं जो मंगली नहीं हैं। मुझे पता है कि प्रश्न की प्रकृति सी नामस्थान का समर्थन क्यों नहीं करती है (और एक तुच्छ उत्तर यह होगा कि यह लागू नहीं होता है क्योंकि यह :))। मैंने अभी सोचा कि यह किसी को यह देखने में मदद कर सकता है कि मैंने कैसे टेम्प्लेट और नेमस्पेस की कार्यक्षमता को लागू किया है।
मैंने सी का उपयोग करके नामस्थान और / या टेम्प्लेट का लाभ कैसे प्राप्त करें, इस पर एक ट्यूटोरियल लिखा।
नाम और सी में टेम्पलेट (लिंक्ड सूची का उपयोग करके)
मूल नाम स्थान के लिए, एक सम्मेलन के रूप में नामस्थान के नाम को उपसर्ग कर सकता है।
namespace MY_OBJECT {
struct HANDLE;
HANDLE *init();
void destroy(HANDLE * & h);
void do_something(HANDLE *h, ... );
}
के रूप में लिखा जा सकता है
struct MY_OBJECT_HANDLE;
struct MY_OBJECT_HANDLE *my_object_init();
void my_object_destroy( MY_OBJECT_HANDLE * & h );
void my_object_do_something(MY_OBJECT_HANDLE *h, ... );
एक दूसरा तरीका जो मुझे चाहिए था, वह है नेमस्पेसिंग और टेम्प्लेट की अवधारणा का उपयोग मैक्रो कॉन्टेनेशन और शामिल करने के लिए। उदाहरण के लिए, मैं एक बना सकता हूं
template<T> T multiply<T>( T x, T y ) { return x*y }
निम्नानुसार टेम्पलेट फ़ाइलों का उपयोग करना
गुणा-template.h
_multiply_type_ _multiply_(multiply)( _multiply_type_ x, _multiply_type_ y);
गुणा-template.c
_multiply_type_ _multiply_(multiply)( _multiply_type_ x, _multiply_type_ y) {
return x*y;
}
अब हम int_multiply को इस प्रकार परिभाषित कर सकते हैं। इस उदाहरण में, मैं एक int_multiply.h / .c फ़ाइल बनाऊंगा।
int_multiply.h
#ifndef _INT_MULTIPLY_H
#define _INT_MULTIPLY_H
#ifdef _multiply_
#undef _multiply_
#endif
#define _multiply_(NAME) int ## _ ## NAME
#ifdef _multiply_type_
#undef _multiply_type_
#endif
#define _multiply_type_ int
#include "multiply-template.h"
#endif
int_multiply.c
#include "int_multiply.h"
#include "multiply-template.c"
इस सब के अंत में, आपके पास एक फ़ंक्शन और हेडर फ़ाइल होगी।
int int_multiply( int x, int y ) { return x * y }
मैंने प्रदान किए गए लिंक पर एक बहुत अधिक विस्तृत ट्यूटोरियल बनाया है जो यह दिखाता है कि यह लिंक की गई सूचियों के साथ कैसे काम करता है। उम्मीद है कि यह किसी की मदद करता है!