সি একটি নিম্ন-স্তরের ভাষা, প্রায় একটি পোর্টেবল অ্যাসেমব্লার, সুতরাং এর ডেটা স্ট্রাকচার এবং ভাষার কাঠামো ধাতুর কাছাকাছি থাকে (ডেটা স্ট্রাকচারের কোনও গোপন ব্যয় থাকে না - প্যাডিং, প্রান্তিককরণ এবং হার্ডওয়্যার এবং এবিআই দ্বারা আরোপিত আকারের সীমাবদ্ধতা বাদে )। সুতরাং সি প্রকৃতপক্ষে স্থানীয়ভাবে গতিময় টাইপিং নেই। তবে আপনার যদি এটির প্রয়োজন হয় তবে আপনি একটি কনভেনশন গ্রহণ করতে পারেন যে আপনার সমস্ত মানগুলি কিছু ধরণের তথ্য (যেমন কিছু enum
...) দিয়ে শুরু করে সমষ্টি ; ব্যবহারের union
-s এবং (অ্যারে-ভালো জিনিস জন্য) নমনীয় অ্যারের সদস্য মধ্যে struct
এছাড়াও অ্যারের আকার রয়েছে।
(সি-তে প্রোগ্রামিং করার সময়, দরকারী কনভেনশনগুলি সংজ্ঞায়িত করা, ডকুমেন্ট করা এবং অনুসরণ করা আপনার দায়িত্ব - বিশেষত প্রাক-শর্তাবলী এবং আক্রমণকারীদের; সি গতিশীল মেমরি বরাদ্দকরণের জন্য free
কিছু গতিযুক্ত malloc
মেমোরি জোনটি কী উচিত সে সম্পর্কে ব্যাখ্যা সম্মেলন প্রয়োজন )
সুতরাং, মান যা বাক্সযুক্ত পূর্ণসংখ্যার, অথবা স্ট্রিং, বা কোন ধরণের হয় প্রতিনিধিত্ব করতে স্কিম -একটি প্রতীক , অথবা মূল্যবোধের ভেক্টর, আপনি ধারণার দিক থেকে একটি ব্যবহার করব বাঁধা ইউনিয়ন (পয়েন্টার একটি ইউনিয়ন হিসাবে প্রয়োগ করা) -always টাইপ ধরনের দ্বারা শুরু -, যেমন:
enum value_kind_en {V_NONE, V_INT, V_STRING, V_SYMBOL, V_VECTOR};
union value_en { // this union takes a word in memory
const void* vptr; // generic pointer, e.g. to free it
enum value_kind_en* vkind; // the value of *vkind decides which member to use
struct intvalue_st* vint;
struct strvalue_st* vstr;
struct symbvalue_st* vsymb;
struct vectvalue_st* vvect;
};
typedef union value_en value_t;
#define NULL_VALUE ((value_t){NULL})
struct intvalue_st {
enum value_kind_en kind; // always V_INT for intvalue_st
int num;
};
struct strvalue_st {
enum value_kind_en kind; // always V_STRING for strvalue_st
const char*str;
};
struct symbvalue_st {
enum value_kind_en kind; // V_SYMBOL
struct strvalue_st* symbname;
value_t symbvalue;
};
struct vectvalue_st {
enum value_kind_en kind; // V_VECTOR;
unsigned veclength;
value_t veccomp[]; // flexible array of veclength components.
};
গতিশীল ধরণের কিছু মান পেতে
enum value_kind_en value_type(value_t v) {
if (v.vptr != NULL) return *(v.vkind);
else return V_NONE;
}
এখানে ভেক্টরগুলির কাছে একটি "গতিশীল কাস্ট" রয়েছে:
struct vectvalue_st* dyncast_vector (value_t v) {
if (value_type(v) == V_VECTOR) return v->vvect;
else return NULL;
}
এবং ভেক্টরগুলির ভিতরে একটি "নিরাপদ অ্যাকসেসর":
value_t vector_nth(value_t v, unsigned rk) {
struct vectvalue_st* vecp = dyncast_vector(v);
if (vecp && rk < vecp->veclength) return vecp->veccomp[rk];
else return NULL_VALUE;
}
উপরের শর্ট ফাংশনগুলির বেশিরভাগটি আপনি সাধারণত static inline
কিছু শিরোলেখ ফাইল হিসাবে সংজ্ঞায়িত করবেন ।
বিটিডাব্লু, আপনি যদি বোহমের আবর্জনা সংগ্রহকারী ব্যবহার করতে পারেন তবে আপনি কিছু উচ্চ স্তরের (তবে অনিরাপদ) স্টাইলে বেশ সহজেই কোডিং করতে সক্ষম হবেন এবং স্কিমের বেশ কয়েকটি অনুবাদক সেভাবে সম্পন্ন হন। একটি বৈকল্পিক ভেক্টর নির্মাণকারী হতে পারে
value_t make_vector(unsigned size, ... /*value_t arguments*/) {
struct vectvalue_st* vec = GC_MALLOC(sizeof(*vec)+size*sizeof(value));
vec->kind = V_VECTOR;
va_args args;
va_start (args, size);
for (unsigned ix=0; ix<size; ix++)
vec->veccomp[ix] = va_arg(args,value_t);
va_end (args);
return (value_t){vec};
}
এবং যদি আপনার তিনটি ভেরিয়েবল থাকে
value_t v1 = somevalue(), v2 = otherval(), v3 = NULL_VALUE;
আপনি তাদের ব্যবহার করে একটি ভেক্টর তৈরি করতে পারেন make_vector(3,v1,v2,v3)
আপনি যদি বোহমের আবর্জনা সংগ্রহকারী (বা নিজের নিজস্ব ডিজাইন) ব্যবহার করতে না চান তবে আপনারা ডেস্ট্রাক্টর সংজ্ঞায়িত করতে এবং কাকে, কীভাবে এবং কখন মেমরিটি রাখা উচিত ডকুমেন্টিংয়ের বিষয়ে খুব যত্নশীল হওয়া উচিত free
; দেখতে এই উদাহরণ। সুতরাং আপনি উপরের malloc
পরিবর্তে ব্যবহার করতে পারেন (তবে তার ব্যর্থতার বিরুদ্ধে পরীক্ষা করুন) GC_MALLOC
তবে আপনাকে সাবধানে সংজ্ঞায়িত করতে হবে এবং কিছু ডেস্ট্রাক্টর ফাংশন ব্যবহার করতে হবেvoid destroy_value(value_t)
সি এর শক্তি হ'ল উপরের মতো কোড তৈরি করতে এবং আপনার নিজস্ব কনভেনশনগুলি (বিশেষত আপনার সফ্টওয়্যারটিতে) সংজ্ঞায়িত করার জন্য পর্যাপ্ত স্তর হ'ল।