การมีเนมสเปซดูเหมือนจะไม่ใช่เรื่องง่ายสำหรับภาษาส่วนใหญ่ แต่เท่าที่บอก ANSI C ไม่รองรับ ทำไมจะไม่ล่ะ? มีแผนที่จะรวมไว้ในมาตรฐานในอนาคตหรือไม่?
การมีเนมสเปซดูเหมือนจะไม่ใช่เรื่องง่ายสำหรับภาษาส่วนใหญ่ แต่เท่าที่บอก ANSI C ไม่รองรับ ทำไมจะไม่ล่ะ? มีแผนที่จะรวมไว้ในมาตรฐานในอนาคตหรือไม่?
คำตอบ:
C มีเนมสเปซ หนึ่งสำหรับแท็กโครงสร้างและอีกรายการสำหรับประเภทอื่น ๆ พิจารณาคำจำกัดความต่อไปนี้:
struct foo
{
int a;
};
typedef struct bar
{
int a;
} foo;
อันแรกมีแท็ก foo และต่อมาถูกสร้างเป็นประเภท foo ด้วย typedef ยังคงไม่มีการปะทะกันของชื่อเกิดขึ้น เนื่องจากแท็กโครงสร้างและประเภท (ชนิดในตัวและชนิดที่พิมพ์แล้ว) อยู่ในเนมสเปซแยกกัน
สิ่งที่ C ไม่อนุญาตคือการสร้างเนมสเปซใหม่ตามความประสงค์ C เป็นมาตรฐานก่อนหน้านี้ถือว่ามีความสำคัญในภาษาหนึ่งและการเพิ่มเนมสเปซจะคุกคามความเข้ากันได้แบบย้อนกลับด้วยเนื่องจากต้องใช้ชื่อที่ยุ่งเหยิงเพื่อให้ทำงานได้ถูกต้อง ฉันคิดว่าสิ่งนี้สามารถนำมาประกอบกันได้เนื่องจากเทคนิคไม่ใช่ปรัชญา
แก้ไข: JeremyP โชคดีที่แก้ไขฉันและพูดถึงเนมสเปซที่ฉันพลาด มีเนมสเปซสำหรับป้ายกำกับและสำหรับสมาชิกโครงสร้าง / สหภาพเช่นกัน
struct
คำจำกัดความจะประกาศเนมสเปซใหม่สำหรับสมาชิก ฉันไม่สนับสนุนการใช้ประโยชน์จากข้อเท็จจริงนั้นและฉันไม่ทราบถึงวิธีการใช้ประโยชน์ใด ๆ เนื่องจากstruct
ไม่สามารถมีสมาชิกแบบคงที่ได้
เพื่อความสมบูรณ์มีหลายวิธีในการบรรลุ "ประโยชน์" ที่คุณอาจได้รับจากเนมสเปซในภาษา C
หนึ่งในวิธีที่ฉันชอบคือการใช้โครงสร้างเพื่อเก็บตัวชี้วิธีการมากมายซึ่งเป็นส่วนต่อประสานกับห้องสมุดของคุณ / ฯลฯ
จากนั้นคุณใช้อินสแตนซ์ภายนอกของโครงสร้างนี้ซึ่งคุณเริ่มต้นภายในไลบรารีของคุณโดยชี้ไปที่ฟังก์ชันทั้งหมดของคุณ สิ่งนี้ช่วยให้คุณสามารถทำให้ชื่อของคุณเรียบง่ายในไลบรารีของคุณโดยไม่ต้องเหยียบเนมสเปซของไคลเอนต์ (นอกเหนือจากตัวแปรภายนอกที่ขอบเขตส่วนกลางตัวแปร 1 ตัวเทียบกับวิธีการหลายร้อยวิธี .. )
มีการบำรุงรักษาเพิ่มเติมบางอย่างที่เกี่ยวข้อง แต่ฉันรู้สึกว่ามันน้อยมาก
นี่คือตัวอย่าง:
/* 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
นี่เป็นวิธีที่สะอาดกว่าการโกงชื่อและความโหดร้ายอื่น ๆ ที่บางภาษายอมส่งมอบเนมสเปซ
ในอดีตคอมไพเลอร์ C ไม่ได้ยุ่งเกี่ยวกับชื่อ (ทำบน Windows แต่การโกงสำหรับหลักการcdecl
เรียกประกอบด้วยการเพิ่มคำนำหน้าขีดล่างเท่านั้น)
สิ่งนี้ทำให้ง่ายต่อการใช้ไลบรารี C จากภาษาอื่น ๆ (รวมถึงแอสเซมเบลอร์) และเป็นสาเหตุหนึ่งที่คุณมักเห็นextern "C"
Wrapper สำหรับ C ++ API
เหตุผลทางประวัติศาสตร์เท่านั้น ไม่มีใครคิดว่าจะมีเนมสเปซในเวลานั้น นอกจากนี้พวกเขาพยายามทำให้ภาษาเรียบง่าย พวกเขาอาจจะมีในอนาคต
ไม่ใช่คำตอบ แต่ไม่ใช่ความคิดเห็น C ไม่มีวิธีกำหนด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(); }
ซึ่งมีความสำคัญเช่นกัน (ish)
ANSI C ถูกคิดค้นก่อนเนมสเปซ
เนื่องจากผู้ที่ต้องการเพิ่มความสามารถนี้ให้กับ C ไม่ได้รวมตัวกันและจัดระบบเพื่อสร้างแรงกดดันให้กับทีมผู้เขียนคอมไพเลอร์และในหน่วยงาน ISO
C ไม่รองรับเนมสเปซเช่น C ++ การใช้งานเนมสเปซ C ++ ทำให้ชื่อยุ่งเหยิง วิธีการที่ระบุไว้ด้านล่างช่วยให้คุณได้รับประโยชน์จากเนมสเปซใน 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 }
โดยใช้ไฟล์เทมเพลตดังนี้
คูณแม่แบบ 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 }
ฉันได้สร้างบทช่วยสอนที่มีรายละเอียดมากขึ้นเกี่ยวกับลิงก์ที่ให้ไว้ซึ่งจะแสดงวิธีการทำงานกับรายการที่เชื่อมโยง หวังว่านี่จะช่วยใครสักคน!