ANSI C के नाम स्थान क्यों नहीं हैं?


92

नाम स्थान रखने से अधिकांश भाषाओं के लिए नो-ब्रेनर की तरह लगता है। लेकिन जहां तक ​​मैं बता सकता हूं, एएनएसआई सी इसका समर्थन नहीं करता है। क्यों नहीं? भविष्य के मानक में इसे शामिल करने की कोई योजना है?


13
C ++ का उपयोग C-with-namespace के रूप में करें!
आराक

3
मैं निश्चित रूप से कर सकता हूं, लेकिन मैं अभी भी जानना चाहता हूं
पुलकित सिन्हा

5
२ बातें। एक अनावश्यक विशिष्ट वाक्यविन्यास: नामस्थान वाली अन्य सभी भाषाएं बस 'का उपयोग करती हैं।' विभाजक के रूप में 'के अन्य उपयोगों के साथ अस्पष्ट नहीं है।'। और, अधिक गंभीर रूप से, c ++ ने निर्देशन का उपयोग करके कभी भी स्कूप नहीं किया है। जिसका अर्थ था कि प्रोग्रामर्स ने वैश्विक दायरे में नाम स्थान को आयात करने के निर्देशों का उपयोग किया। जिसका मतलब था कि c ++ मानक समिति अब std में नई सुविधाएँ नहीं जोड़ सकती है :: कभी कोड की मात्रा के परिणामस्वरूप जो विभाजन के कारण टूट जाएगा, वह विभाजन निरर्थक है।
क्रिस बेक

2
@ क्रिस बेके: मुझे विशिष्ट वाक्यविन्यास पसंद है। मुझे यह जानना पसंद है कि क्या मैं नाम स्थान में एक कक्षा देख रहा हूं या एक कक्षा में एक सदस्य।
जेरेमीप

6
@ChrisBecke, यह कुछ साल देर से है, लेकिन यह दिलचस्प है कि आप तर्क देते हैं कि C ++ नेमस्पेस को खराब तरीके से लागू किया गया था, इसलिए उन्हें C. में लागू नहीं किया जाना चाहिए। फिर आप ध्यान दें कि अन्य भाषाएं C ++ के हैंगअप के बिना उन्हें लागू करती हैं। यदि अन्य भाषाएँ यह कर सकती हैं, तो उन्हें C से क्यों नहीं मिलवाया जाए?
weberc2

जवाबों:


68

C के नाम स्थान हैं। एक संरचना टैग के लिए, और अन्य प्रकार के लिए। निम्नलिखित परिभाषा पर विचार करें:

struct foo
{
    int a;
};

typedef struct bar
{
    int a;
} foo;

पहले वाले का टैग है फू है, और बाद में टाइपो के साथ फू फू में बनाया गया है। फिर भी कोई नाम-टकराव नहीं होता। इसका कारण यह है कि संरचना टैग और प्रकार (अंतर्निहित प्रकार और टाइप किए गए टाइप) अलग नामस्थानों में रहते हैं।

C जो अनुमति नहीं देता है वह इच्छाशक्ति द्वारा नए नामस्थान बनाने की है। सी को भाषा में महत्वपूर्ण समझे जाने से पहले मानकीकृत किया गया था, और नामस्थान जोड़ने से पीछे की ओर भी अनुकूलता का खतरा होगा, क्योंकि इसे सही काम करने के लिए नाम की आवश्यकता है। मुझे लगता है कि इसका श्रेय तकनीकीताओं के कारण हो सकता है, दर्शनशास्त्र को नहीं।

संपादित करें: जेरेमीप ने सौभाग्य से मुझे सही किया और उन नामों का उल्लेख किया जो मैंने याद किया। लेबल के लिए और संरचना / संघ के सदस्यों के लिए भी नामस्थान हैं।


8
वास्तव में दो से अधिक नाम स्थान हैं। आपके द्वारा उल्लेखित दो के अलावा, प्रत्येक संरचना और संघ के सदस्यों के लिए लेबल और नाम रिक्त स्थान के लिए एक नाम स्थान है।
जेरेमीप

@JeremyP: सुधार के लिए बहुत धन्यवाद। मैंने केवल इस मेमोरी को लिखा था, मैंने मानक की जांच नहीं की :-)

2
कार्यों के लिए नाम स्थान के बारे में क्या?
थीमीहाई

8
इसे अच्छी तरह से नामस्थान कहा जा सकता है, लेकिन मेरा मानना ​​है कि ये ओपी के बारे में पूछ रहे नामस्थानों के प्रकार नहीं हैं।
avl_sweden

1
@jterm नोप। मैं हैकिंग सी सुविधाओं की वकालत नहीं कर रहा हूं, केवल तथ्यों को बता रहा हूं। प्रत्येक structपरिभाषा अपने सदस्यों के लिए एक नया नाम स्थान घोषित करती है। मैं उस तथ्य का शोषण करने की वकालत नहीं कर रहा हूँ, और न ही मैं इसका शोषण करने के किसी भी माध्यम के बारे में जानता हूँ क्योंकि structइसमें स्थैतिक सदस्य नहीं हो सकते।
जेरेमीप

99

पूर्णता के लिए "लाभ" प्राप्त करने के कई तरीके हैं जो आपको नामस्थान से मिल सकते हैं, सी में।

मेरी पसंदीदा विधियों में से एक है एक संरचना का उपयोग करने के लिए विधि बिंदुओं का एक गुच्छा जो आपके पुस्तकालय / आदि के लिए इंटरफ़ेस है।

फिर आप इस संरचना का एक बाहरी उदाहरण का उपयोग करते हैं जिसे आप अपने सभी कार्यों की ओर इशारा करते हुए अपने पुस्तकालय के अंदर शुरू करते हैं। यह आपको क्लाइंट नेमस्पेस (वैश्विक दायरे में बाहरी चर के अलावा, संभवत: सैकड़ों तरीकों से ..) पर कदम रखे बिना अपनी लाइब्रेरी में अपना नाम सरल रखने की अनुमति देता है।

इसमें कुछ अतिरिक्त रखरखाव शामिल है लेकिन मुझे लगता है कि यह न्यूनतम है।

यहाँ एक उदाहरण है:

/* 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 पद्धति पर एक मजबूत संघ बनाता है। हालाँकि कुछ सीमाएँ हैं, एक के लिए आप कार्यों के रूप में मैक्रोज़ का उपयोग नहीं कर सकते हैं।


12
... और कंपाइलर स्मार्ट हैं "डीरेफेरेंस" फंक्शन पॉइंटर को कंपाइल टाइम पर जब आप करते हैं library.method1()?
einpoklum

1
यह तो कमाल है। एक चीज जो मैं जोड़ सकता हूं, मैं अपनी सभी फ़ंक्शंस को .cडिफ़ॉल्ट रूप से स्टैटिक में स्थिर करने की कोशिश कर रहा हूं , इस प्रकार केवल वही फ़ंक्शंस उजागर होते हैं const structजो .cफ़ाइल में परिभाषा में स्पष्ट रूप से उजागर होते हैं ।
19

3
यह एक महान विचार है, लेकिन आप स्थिरांक और दुश्मनी से कैसे निपटते हैं?
जूल

1
@einpoklum - necro के लिए खेद है, लेकिन कम से कम संस्करण 6.3.0 के रूप में, जीसीसी function1/ और method2दोनों के साथ संकलित करने पर / के वास्तविक पते की गणना करेगा । जब तक आप अपने स्वयं के स्रोत के साथ इस तरह के पुस्तकालयों को संकलित नहीं करते हैं, तब तक यह दृष्टिकोण अपने फ़ंक्शन कॉल में कुछ ओवरहेड जोड़ देगा। -O2-flto
एलेक्स रिंकिंग

3
@AlexReinking: ठीक है, यह अच्छा है, लेकिन हम इन कार्यों को कभी भी पूरा नहीं करेंगे। और - necro'ing महान है, कोई माफी आवश्यक नहीं है।
einpoklum

24

C के नाम स्थान हैं। वाक्य-विन्यास है namespace_name। तुम भी उन्हें घोंसला बना सकते हैं general_specific_name। और यदि आप हर बार नाम स्थान का नाम लिखे बिना नामों का उपयोग करने में सक्षम होना चाहते हैं, तो संबंधित हेडप्रोसेसर मैक्रोज़ को हेडर फ़ाइल में शामिल करें, जैसे।

#define myfunction mylib_myfunction

यह नामकरण और अन्य अत्याचारों की तुलना में बहुत अधिक क्लीनर है, कुछ भाषाएं नाम स्थान देने के लिए प्रतिबद्ध हैं।


24
मैं इसे अलग तरह से देखता हूं। व्याकरण की शिकायत करना, प्रतीकों पर नाम का प्रचलन शुरू करना, इत्यादि कुछ ऐसा हासिल करना जो पहले से ही तुच्छता के साथ करने के लिए तुच्छ था, जिसे मैं एक गंदा हैक और खराब डिज़ाइन कहूंगा।
आर .. गिटहब स्टॉप हेल्पिंग ICE

41
मैं यह नहीं देखता कि आप वास्तव में उस स्थिति का समर्थन कैसे कर सकते हैं। जब हर दूसरे सिस्टम में नेमस्पेस लागू करने के लिए एक अलग होमग्रोन हैक है, तो परियोजनाओं को एकीकृत करने के बारे में जावास्क्रिप्ट समुदाय से पूछें। मैंने कभी किसी को 'नेमस्पेस' या 'पैकेज' कीवर्ड के बारे में शिकायत करते हुए नहीं सुना कि उनकी भाषा में बहुत अधिक जटिलता है। दूसरी ओर, मैक्रोज़ से अटे हुए कोड को डीबग करने की कोशिश करने से बाल तेजी से निकल सकते हैं!
वेबर 2

5
मैंने बहुत से लोगों के बारे में C ++ नाम मैनलिंग (डिबगिंग, टूलचिन, एबीआई संगतता, डायनेमिक सिंबल लुकिंग ...) के दृष्टिकोण के बारे में शिकायत की है और यह जानने की जटिलता नहीं है कि वास्तव में एक विशेष नाम का क्या जिक्र है।
आर .. गिटहब स्टॉप हेल्पिंग ICE

6
@R .. ऐसा नहीं होगा यदि C ++ में मैनबलिंग नाम मानकीकृत हो। यह अकेले ABI संगतता के साथ मदद नहीं करेगा, लेकिन निश्चित रूप से नाम मानचित्रण समस्या को ठीक करेगा।
मैल्कम

20
मुझे यह उड़ाने का मन है कि सी लोग वास्तव में सीधे चेहरे के साथ इस पर बहस करेंगे। C ++ में तेज किनारों के साथ कई विशेषताएं हैं जो लोगों को दु: ख देती हैं। नाम स्थान उन सुविधाओं में से एक नहीं हैं। वे महान हैं, वे बहुत अच्छी तरह से काम करते हैं। और कुछ भी रिकॉर्ड के लिए प्रीप्रोसेसर के साथ तुच्छ नहीं है। अंत में, नाम का नाम तुच्छ है, कमांड लाइन उपयोगिताओं के बहुत सारे हैं जो इसे आपके लिए करेंगे।
निर फ्राइडमैन

12

ऐतिहासिक रूप से, सी कंपाइलर नामों को नहीं cdeclजोड़ते हैं (वे विंडोज पर करते हैं, लेकिन कॉलिंग कन्वेंशन के लिए मैनलिंग में केवल अंडरस्कोर प्रीफ़िक्स जोड़ना शामिल है)।

इससे सी लाइब्रेरीज़ को अन्य भाषाओं (कोडांतरक सहित) से उपयोग करना आसान हो जाता है और यही एक कारण है कि आप अक्सर extern "C"C ++ API के लिए रैपर देखते हैं।


2
लेकिन ऐसी समस्या क्यों है? मेरा मतलब है, मान लें कि सभी नामांकित नाम _da13cd6447244ab9a30027d3d0a08903 से शुरू होंगे और फिर नाम (यह एक यूयूआईडी v4 है जो मैंने अभी बनाया है)? एक मौका है कि यह उन नामों को तोड़ सकता है जो इस विशेष यूयूआईडी का उपयोग करते हैं, लेकिन यह मौका अनिवार्य रूप से शून्य है। इसलिए व्यवहार में केवल_नामेश_नाम लिखने की समस्या नहीं होगी ।
ईनपोकलूम

7

सिर्फ ऐतिहासिक कारण। उस समय किसी नेमस्पेस जैसा कुछ होने के बारे में नहीं सोचा था। साथ ही वे वास्तव में भाषा को सरल रखने की कोशिश कर रहे थे। भविष्य में उनके पास यह हो सकता है


2
क्या भविष्य में सी में नाम स्थान जोड़ने के लिए मानक समिति में कोई आंदोलन है? C / C ++ मॉड्यूल की ओर बढ़ने से संभव है कि यह भविष्य में इसे आसान बना सके?
lanoxx

1
@lanoxx बैकवर्ड संगतता कारणों के कारण C में नामस्थान जोड़ने की कोई वसीयत नहीं है।
थीमीहाई

6

उत्तर नहीं, टिप्पणी नहीं। सी 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(); }जिनके साथ यह भी महत्वपूर्ण है (ईश)।
einpoklum

3

ANSI C का आविष्कार नाम स्थान से पहले किया गया था।


10
ये था? पहला एएनएसआई सी कल्पना 1989 थी। मुझे पूरा यकीन है कि नामस्थान (किसी रूप में या किसी अन्य) से पहले प्रोग्रामिंग भाषाओं में थे। उदाहरण के लिए, Ada को 1983 में मानकीकृत किया गया था और इसमें नामस्थान के रूप में पैकेज थे। बदले में वे अनिवार्य रूप से मोडुला -2 मॉड्यूल पर आधारित थे।
JUST MY correct OPINION

4
मैं एएनएसआई सी के आविष्कार की तारीख नहीं बताऊंगा जब इसकी कल्पना आधिकारिक तौर पर अपनाई गई थी; भाषा पहले से मौजूद थी, और कल्पना ने जो कुछ भी पहले से ही दर्ज किया था। हालाँकि इस साइट के कुछ उत्तरों से शायद लगता है कि कल्पना पहले और बाद में संकलक के रूप में आई थी।
रात्रि

ANSI C में पूर्व ANSI C से कुछ महत्वपूर्ण अंतर थे, लेकिन नामस्थान उनमें से एक नहीं थे।
dan04

इस बीच, मैं 2020 में लिख रहा हूं, अच्छी तरह से नामस्थानों के अस्तित्व में आने के बाद। नवीनतम सी मानकों अभी भी उनके पास नहीं है। जितना C समझ में आता है, यह एक ऐसी विशेषता है जो बुरी तरह से गायब है।

3

क्योंकि जो लोग सी में इस क्षमता को जोड़ना चाहते हैं, उन्होंने एक साथ नहीं मिला है और संकलक लेखक टीमों और आईएसओ निकायों पर कुछ दबाव डालने के लिए आयोजित किया है।


1
मुझे लगता है कि हम सी में नाम स्थान देखेंगे तभी ये लोग खुद को व्यवस्थित करेंगे और नाम स्थान समर्थन के साथ एक एक्सटेंशन (ओं) का निर्माण करेंगे। तब आईएसओ निकायों के पास कोई विकल्प नहीं होगा, लेकिन उन्हें मानक (अधिक या कम परिवर्तनों के साथ) के रूप में प्रकाशित करें। यह कैसे जावास्क्रिप्ट (जो इस संबंध में सी के साथ कुछ समानताएं हैं) ने किया।
थीमीहाई

3
@ तेमिहाई: "एक एक्सटेंशन बनाएँ" = नामस्थानों को संकलित करने के लिए जीसीसी और लोगों को मिलाएं।
ईनपोकलुम

1

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 }

मैंने प्रदान किए गए लिंक पर एक बहुत अधिक विस्तृत ट्यूटोरियल बनाया है जो यह दिखाता है कि यह लिंक की गई सूचियों के साथ कैसे काम करता है। उम्मीद है कि यह किसी की मदद करता है!


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