close
دانلود فیلم
آشنایی با زبان برنامه نویسی D - بخش دوم

سازگاری
تقدم عملگر و قوانین سنجش
D عملگرهای C و قوانین تقدم آنها را حفظ می کند همچنین ترتیب قوانین سنجش و قوانین تقدم . این از اشکالات ریز که از ابتدای برنامه نمایان می شود جلوگیری می کند .

دسترسی مستقیم به API های C
نه تنها D نوع داده های مطابق با C دارد همچنین دسترسی مستقیم به توابع C را فراهم می سازد . هیچ نیازی به نوشتن توابع بسته بندی شده یا کدی برای کپی کردن اجزای متراکم یک توده به صورت یک به یک نیست.

پشتیبانی از تمام نوع داده های C
ارتباط با هر API زبان C و یا کد کتابخانه ای C ممکن است . این پشتیبانی تمام انواع C 99 را در بر می گیرد . D شامل توانایی صف بندی اعضای ساختمان برای مطمئن شدن از سازگاری با فرمتهای داده خارجی می باشد.



پردازش استثنای سیستم عامل
مکانیسم پردازش استثناهای D متصل به روشی است که سیستم عامل در سطح زیرین استثناها را در یک برنامه کاربردی پردازش می کند .

کنترل پروژه
نسخه سازی

D SPAN>. D تکنیک if # و

نبود هشدار
کامپایلرهای D هشدارهایی برای کدهای نامطمئن تولید نمی کنند . کد یا توسط کامپایلر قابل قبول است یا نیست . این خصوصیت هر گونه بحثی در این زمینه که آیا هشدار خطایی صحیح است یا نه و نیز هر بحثی در این باره که با آن هشدار چه کنیم را از بین می برد . نیاز برای هشدار کامپایلر نشانه ی طراحی ضعیف زبان است .

استهلاکDeprecation
به مرور زمان ،بعضی کدهای کهنه کتابخانه با نو تر و نسخه بهتر جایگزین می شود . نسخه قدیمی باید برای پشتیبانی کدهای به جا مانده از قبل موجود باشد اما می تواند لقب مستهلک بگیرد . کدهایی که نسخه های مستهلک را به کار می گیرند ، می توانند به انتخاب برنامه نویس توسط یک سویچ کامپایلر برچسب غیر قانونی بخورند که باعث آسان شدن کار برنامه نویسان برای نشان دادن هر وابستگی به خصوصیات مستهلک می شود .

نمونه برنامه D غربال اراتستن (تست اعداد اول):

import c.stdio ;
bit [8191] flags ;
int main (){
   int i , count , prime , k , iter ;
   print f(“ 10 iterations n ) ;
   for ( iter = 1 ; iter<=10 ; iter++ ) {
      count = 0 ;
      flags [ ] = 1 ;
      for ( i = 0 ; i < flags . length ; i++){ 
         if ( flags [i] ) {
         prime = i + i +3 ;
         k = i + prime ; 
         while ( k < flags . Length) {
            flags , [ k] = 0 ;
            k + = prime ; 
            }
            count + = 1 ;
         }
      }
   }
   print f ( “ % d primes” , count ) ;
   return 0 ;
}

مقادیر واسطه ممیز شناور
در بسیاری کامپیوترها ، اعمال با دقت بالا بیشتر از اعمال با دقت کمتر وقت نمی گیرند .این باعث می شوند که مفاهیم شمارشی بالاترین دقت ممکن را برای اعمال داخلی موقتی به کار ببرند . فلسفه مورد بحث این نیست که زبان را به پائین مقسوم علیه سخت افزاری محدود کنیم بلکه آن را قادر به بهره برداری از بهترین توانایی های سخت افزار مورد نظر نماییم .
برای اعمال ممیز شناور و مقادیر واسطه دستورات یک دقت بالاتر می تواند به کار رود . تنها حد پایین دقت توسط نوع عملوندها مشخص می شود نه حد بالای آن . نکته پیاده سازی : در ماشین های اینتل x 86 برای نمونه انتظار می رود ( اما لازم نیست ) که محاسبات واسطه ای در دقت کامل هشتاد بیتی که توسط سخت افزار پیاده سازی می شود انجام شود .
امکان دارد که در مسیر استفاده از مقادیر موقت و زیر عبارات معمول ، کد بهینه شده یک جواب دقیقتر از کد بهینه نشده فراهم سازد .
الگوریتم ها باید طوری نوشته شود که براساس حداقل دقت محاسبات کار کند .  آنها نباید در مواقعی که دقت واقعی بالاتر است افت عملکرد یابند یا شکست بخورند . انواع double یا float برخلاف نوع گسترش یافته فقط باید در موارد زیر به کار رود :
۱. کاهش مصرف حافظه برای آرایه های بزرگ .
۲. داده ها و آرگومان های توابع سازگار با C .

<dd dir="RTL" style="margin-bottom: 0.5cm; text-align: right " >

انواع موهومی و مختلط
در زبان های موجود ، یک تلاش عجیب برای به زور جا دادن انواع مختلط در تسهیلات تعریف نوع موجود مانند قالب ها ، ساختمان ها و … وجود داردو تمام این ها معمولاً در نهایت با شکست مواجه می شود.
شکست می خورند چون مفاهیم اعمال مختلط می تواند بسیار دقیق باشد و کامپایلر نمی داند که برنامه نویس در تلاش برای انجام چه کاری است بنابراین نمی تواند پیاده سازی معنایی را بهینه نماید .
تمام این کارها برای اجتناب از اضافه کردن یک نوع جدید انجام شده است . اضافه کردن یک نوع جدید بدین معناست که کامپایلر می تواند تمامی مفاهیم اعمال مختلط را دقیق پیاده کند . پس برنامه نویس می تواند بر یک پیاده سازی صحیح ( یا حداقل دارای ثبات ) اعداد مختلط اعتماد کند .
همراه بودن با یک بسته نوع مختلط برای یک نوع موهومی مورد نیاز است .یک نوع موهومی برخی از پیامدهای ظریف معنایی را حذف می کند و کارآیی را بهبود می بخشد بدون اینکه مجبور به انجام اعمال اضافی روی قسمت حقیقی واضح صفر ، باشیم . الفاظ موهومی دارای یک پسوند i می باشند .
imaginary j = 1.3 i ;
هیچ املای خاص برای نوع مختلط وجود ندارد فقط یک نوع حقیقی و موهومی را با هم جمع کنید :
complex c= 4.5 + 2i ;
افزودن دو نوع جدید به زبان کافی است از این رو انواع مختلط و موهومی دارای دقت توسعه یافته هستند . هیچ نوع اعشاری مختلط و موهومی یا نوع دابل مختلط یا موهومی وجود ندارد ( توجه : راه برای افزودن آنها در آینده باز است ) .

اعداد مختلط دارای دو صفت خاصه هستند :
قسمت حقیقی را به عنوان گسترش یافته بدست می دهد // .re
قسمت موهومی را به عنوان عدد موهومی بدست می دهد // .im

برای مثال :

c . re is 4.5
c . im is 2i

کنترل گرد کردن
حسابگر ممیز شناور IEEE 754 شامل توانایی تنظیم کردن چهار روش گرد کردن است . D املایی خاص برای دسترسی به آنها افزوده است : [ blah , blah , blah ]

پرچمهای استثناء
حسابگر ممیز شناور IEEE 754 می تواند پرچمهای مختلف را براساس آن چه در یک محاسبه رخ داده است تنظیم نماید : [ blah , blah , blah ]. این پرچمها می توانند به وسیله املای زبان SET / Reset شوند .

مقایسه های ممیز شناور
علاوه بر عملگرهای مقایسه معمولی < , < = , > , >= , == , != زبان D تعداد بیشتری که خاص اعداد ممیز شناور است اضافه می کند .

مدیریت حافظه
هر برنامه غیر جزیی نیاز به تخصیص و آزاد سازی حافظه دارد . هر چه پیچیدگی ، اندازه و کارآیی برنامه ها افزایش می یابد تکنیکهای مدیریت حافظه مهمتر می شوند . D اختیارات متعددی در زمینه مدیریت حافظه پیشکش می کند .

سه روش پایه تخصیص حافظه در D :
۱. داده استاتیک : در سگمنت داده پیش فرض تخصیص می یابند .
۲. داده پشته : در پشته برنامه CPU تخصیص می یابند .
۳. داده زباله جمع آوری شده :  به صورت پویا در heap جمع آوری زباله تخصیص می یابند .

قسمت بعدی تکنیک ها را برای استفاده از آنها توضیح می دهد به همراه برخی قابلیت های پیشرفته:

رشته ها ( و آرایه ها ) copy – on – write
فرستادن یک آرایه به یک تابع را در نظر بگیرید و احتمالاً  تغییر دادن آرایه و برگرداندن آرایه جدید . از آنجا که آرایه ها با ارجاع فرستاده می شوند نه با مقدار ، یک پیامد وخیم این است که ندانیم محتویات آرایه از آن کیست ؟ برای مثال تابعی که آرایه ای از کاراکترها را به حروف بزرگ برمی گرداند .

char [] toupper ( char [] s ) {
   int i ;
   for ( i =0 ; i < s . length ; i++ ){
      char c = s[i] ;
      if ('a' <= c && c <= 'z ' )
      s[i] = c - (cast(char)'a' - 'A ' ) ;
      }
   return s ;
}

توجه کنید که نسخه []S که فراخوانی شد تغییر هم کرد شاید این اصلاً آن چیز مورد توقع نبود یا بدتر آنکه []S ممکن است تکه ای از حافظه فقط خواندنی باشد .
اگر یک کپی از S همواره توسط تابع ساخته می شد به طور ناکارا و بدون لزوم ،زمان و حافظه برای حروفی که خودشان بزرگ هستند مصرف می شد .
راه حل پیاده سازی copy – on – write است که یعنی یک کپی ساخته می شود فقط اگررشته ها نیاز به تغییر دارند . بعضی زبان های پردازنده رشته ها این عمل را به عنوان پیش فرض انجام می دهند اما هزینه بسیار سنگین است .
در نتیجه آن رشته “abcdwF ” پنج مرتبه بوسیله تابع کپی می شود. برای اینکه از این قرارداد به نحوی با حداکثر کارآیی استفاده شود باید به صورت واضح در کد ظاهر شود .

char [] toupper (char [] s) {
   int changed ;
   int i ;
   changed = 0 ;
   for (i=0 ; i DT >
   char c = s[i] ;
   if (‘a’ <= c && c<= ‘z ) {
      if ( ! changed ){
         char [] r = new char [ s.length ] ;
         r []= s ;
         changed = 1 ; 
         } 
         s [i] = c – ( cast ( char ) ‘a’ – ‘A ) ;
      }
   }
   return s ;
}

copy – on – write پروتکلی است که به وسیله توابع پردازش آرایه ها در کتابخانه ی زمان اجرای phibo زبان D پیاده سازی شده است .

جمع آوری زباله
D زبانی دارای جمع آوی زباله کامل می باشد . بدین معنی که هیچ وقت نیاز به آزادسازی حافظه نیست . فقط به هنگام نیاز حافظه را تخصیص دهید و جمع آور زباله به طور دوره ای تمام حافظه بی استفاده را به توده حافظه آزاد برمی گرداند .
برنامه نویسان C ++ , C که به کنترل دستی حافظه هنگام تخصیص و آزاد سازی آن عادت دارند احتمالاً به مزایا و تأثیر جمع آوری زباله یقین ندارند . تجربه ی پروژه های جدید که با در نظر گرفتن جمع آوری زباله نوشته شده اند همچنین پروژه های موجود که به سبک جمع آوری زباله برگردانده شده اند نشان می دهد که :
۱. برنامه های دارای جمع آور زباله سریعتر هستند . این واضح است اما دلایلی قابل بیان است .
۲. شمارش در جاعات یک روش معمول برای حل مسائل تخصیص حافظه آشکار است . کد پیاده سازی اعمال اضافه و تفریق هر جا که انتساب صورت می گیرد یکی از دلایل کندی است .
۳.پنهان کردن کد مذکور در پس کلاسهای اشاره گر هوشمند به افزایش سرعت کمک نمی کند . ( روش شمارش ارجاعات به هیچ وجه راه حل عمومی نیست جایی که ارجاعات حلقه ای هرگز حذف نمی شوند . )
۴. مخرب های کلاس برای آزادسازی منابع مورد نیاز یک شیئ به کار می رود . برای اغلب کلاسها این منابع ، حافظه تخصیص یافته است . با جمع آوری زباله اغلب مخرب ها خالی می شوند و در نهایت می توانند دور انداخته شوند .
۵. تمام مخرب هایی که حافظه را آزاد می کنند می توانند معنی دار شوند در مواقعی که اشیاء ، بر روی پشته تخصیص حافظه می یابند . برای هر کدام مکانیزمی باید در نظر گرفته شود طوری که اگر یک استثناء رخ داد تمام مخربها از هر چارچوب فراخوانی شوند تا هر حافظه تخصیص یافته برای آنها را رها کنند . اگر مخرب ها نامربوط شوند هیچ نیازی برای در نظر گرفتن چارچوب های خاص پشته برای پردازش استثناها نیست در نتیجه کد سریعتر اجرا می شود .
۶. تمام کدهای لازم برای مدیریت حافظه می تواند برای تکامل جزیی اضافه شود . برنامه بزرگتر کمتر در حافظه اصلی و بیشتر آن در حافظه مجازی قرار می گیرد و آرامتر و کندتر اجرا می شود .
۷. جمع آور حافظه هنگامی صورت می گیرد که حافظه تنگ و کم شود . تا وقتی حافظه جا دارد برنامه در حداکثر سرعت ممکن اجرا میشود و هیچ وقتی برای آزاد کردن حافظه ، صرف نمی کند .
۸.جمع آورنده های زباله مدرن ، اکنون به مراتب پیشرفته تر و سریع تر هستند . جمع آورنده های تولید کننده و کپی کننده ، قسمت عمده ناکارایی الگوریتم های جارو کردن و اختصاص دادن را حذف می کنند .
۹.جمع آورنده های زباله مدرن فشرده سازی توده حافظه را انجام می دهند . فشرده سازی توده مراقب است که تعداد صفحاتی که به طور فعال به وسیله یک برنامه ارجاع شده اند را کاهش دهد بدین معنی که دسترسی های حافظه احتمالاً بیشتر به حافظه می رسند تا به مبادله حافظه .
۱۰. جمع آورنده های زباله حافظه استفاده شده را اصلاح می کنند . بنابراین به رخنه های حافظه - که باعث می شوند برنامه های با اجرای طولانی مدت آن قدر حافظه مصرف کننده تا سیستم هنگ کند- تن در نمی دهد .
۱۱. برنامه های دارای جمع آور زباله دارای اشکالات کمتر یافتن اشاره گرها می باشند به این خاطر که هیچ ارجاع سرگردان به حافظه آزاد شده نمی ماند .
۱۲. برنامه های دارای جمع آور زباله برای گسترش و اشکال زدایی سریعترند . چون هیچ نیازی برای گسترش ، اشکال زدایی ، امتحان ، یا ابقاء کد آزاد سازی حافظه دستی وجود ندارد .
۱۳. برنامه های دارای جمع زباله به طور معنی داری کوچکترند چون هیچ کد آزادسازی حافظه وجود ندارد و از این رو نیازی به پردازشگرهای استثناها برای آزاد سازی حافظه وجود ندارد .

جمع آوی زباله یک نوشداروی همه کاره نیست بعضی اشکالات هم دارد :
۱. وقتی یک مجموعه برنامه همزمان اجرا می شود قابل پیشگویی نیست بنابراین برنامه به طور دلخواه می تواند مکث کند.
۲. زمانی که برای اجرای یک مجموعه مصرف می شود نامحدود است با اینکه در عمل بسیار کوتاه است اما ضمانتی وجود ندارد .
۳. تمام رشته های اجرا به غیر از رشته جمع آوری زباله در حالی که جمع آوری در جریان است باید مکث کند .

نحوه برقراری ارتباط اشیای دارای جمع آوری زباله با کد بیرونی
جمع آور زباله در سگمنت داده ایستا ، پشته ها و محتویات رجیستر هر thread ، به دنبال ریشه ها می گردد . اگر تنها ریشه یک شیئ بیرون از آنها باشد ، جمع آور زباله آن را از بین می برد و حافظه را آزاد می‌سازد .

برای اجتناب از این واقعه باید :
۱. ریشه دسترسی به یک شیئ را در جایی نگهداری کنیم که جمع آور زباله در آن جا به دنبال ریشه می گردد .
۲.به شیئ مجدداً توسط تخصیص دهنده کد خارجی یا کتابخانه های زمان اجرای C یعنی malloc/ free ، حافظه تخصیص دهیم .

اشاره گرها و جمع آور زباله
الگوریتم های جمع آوری زباله بستگی دارد به اشاره گرهایی که به چیزی در حال اشاره ‌اند و غیر اشاره‌گرها که به چیزی اشاره نمی کرده اند . بدین منظور دستورات زیر که در C غیر معمول نیستند باید به دقت در D از آنها خودداری شود :
۱. اشاره گرها را با xor کردن آنها با مقادیر دیگر مخفی نکنید مانند اشاره گر xor شده حقه‌ی لیست پیوندی در C . از حقه‌ی xor برای جا به جا کردن مقادیر دو اشاره گر استفاده نکنید .
۲. اشاره گرهای به مقادیر صحیح را توسط cast یا دیگر حقه ها ذخیره نکنید ، چون جمع آوری زباله انواع غیر اشاره‌گر را برای یافتن ریشه های دسترسی بررسی نمی کند .
۳. از مزیت هم ترازی اشاره گرها برای ذخیره فلگهای بیتی در بیتهای سطح پائین یا بیتهای سطح بالا استفاده نکنید .
۴. مقادیر صحیح را در اشاره گرها نگهداری نکنید .
۵. مقادیر جادویی را در اشاره گرها ذخیره نکنید به غیر از null .
۶. اگر شما باید یک مکان نگهداری خاص را بین انواع اشاره گر و غیر اشاره‌گر به اشتراک بگذارید از union استفاده کنید تا جمع آور زباله تکلیف خودش را در آن مورد بداند .
در حقیقت تا جایی که می شود از اشاره گرها استفاده نکنید . D دارای امکاناتی مانند اشیاء مرجع ، آرایه های پویا و جمع آوری زباله است که نشان می دهد که اغلب اشاره گرهای آشکارا ، متروک و بلااستفاده خواهند بود . اشاره گرها برای ارتباط موفق با API های C و بعضی کارهای کیمیاگرانه در D فراهم شده اند .

ساختمانها و یونیون ها
نحوه اعلان :

Tag { DeclDefs }
Tag Identifier { DeclDefs }
Tag Identifier ;
Tag: struct / union

شبیه C کار می کنند با تفاوتهای زیر :
۱. بدون فیلد های بیت
۲. نحوه آرایش به طور آشکار قابل مشخص کردن است .
۳. اعلان هایی مانند ; struct ABC x ،مجاز نیستند بنویسید ; ABC x .
۴. ساختمانها یا یونیون های بی نام می توانند عضوی از ساختمانها یا یونیون های دیگر باشند .
۵. انتساب دهنده های پیش فرض اولیه برای اعضا پشتیبانی می شود .
۶. توابع عضو و اعضای استاتیک مجاز است .
ساختمانها و یونیون ها به معنی اجتماع ساده داده ها یا راهی برای رنگ و آب دادن به یک ساختمان داده می باشد ، علاوه بر سخت افزار یا یک نوع خارجی ، انواع خارجی می توانند توسط API سیستم عامل یا یک فرمت فایل تعریف شوند . خصوصیات شیئ گرا نیز با نوع داده کلاس فراهم شده اند .

انتساب اولیه استاتیک ساختمان ها
به اعضای ساختمان استاتیک به طور پیش فرض مقدار صفر انتساب داده می شود و به مقادیر ممیز شناور مقدار NAN . اگر یک انتساب دهنده اولیه‌ی استاتیک فراهم شود ، اعضا به وسیله نام عضو ، علامت ':' و املای دستور ، انتساب اولیه می شوند . در ضمن ممکن است اعضا به هر نحو انتساب اولیه شوند .

struct X { int a; int b; int c; int d = 7 ; }
static X x = { a:1, b:2}; // c is set to 0, d to 7
static X z = { c:4, b:5, a:2 , d:5}; // z.a = 2, z.b = 5, z.c = 4, d = 5
<dd dir="RTL" style="margin-bottom: 0.5cm; text-align: right”> انتساب اولیه‌ استاتیک یونیون ها

یونیون ها به طور آشکار مقدار دهی اولیه می شوند :

union U { int a ; double b } ;
static U u = { b : 5.0 } ; // u.b = 5.0

دیگر اعضای یونیون که انتساب دهنده را جای می گذارند ولی فضای بیشتری اشغال می کنند مقدار صفر می گیرند .

Enums
اعلان :

EnumDeclaration :
enum identifier { EnumMembers }
enum { EnumMembers }
enum identifier ;

Enum کاربرد معمولی ماکروی define # در زبان C را برای تعریف مقادیر ثابت جایگزین میکند.
Enum ها همچنین می توانند بی نام باشند که در آن مورد به سادگی ثابت های مجتمع را تعریف می کنند و یا دارای نام باشند که مقدمه یک نوع جدید خواهند بود . اعلان زیر :

enum { A, B, C } // anonymous enum

مقادیر ثابت A=0 , B=1 , C=2 که معادل دستورات زیر است را تعریف میکند :

const int A = 0; const int B = 1; const int C = 2 ;

در حالی که اعلان زیر:

enum X { A, B, C } // named enum

نوع جدید X با مقادیر X.A=0 , X.B=1 , X.C=2 تعریف می کند.
Enum ها باید حداقل دارای یک عضو باشند . اگر برای یک عضو Enum یک عبارت ریاضی فراهم شده باشد ارزش عضو مذکور برابر حاصل عبارت است و عضو بعدی Enum دارای ارزش عضو قبلی به علاوه یک است . مثلاً در مورد زیر :

Enum { A , B = 5 + 7 , C, D = 8 , E }
داریم A = 0 , B = 12 , C = 13 , D = 8 , E = 9

صفات Enum
کوچکترین عضو min
بزرگترین عضو max
سایز نگهداری ارزش عضو size

مقدار دهی اولیه‌ی Enum :
در غیاب یک مقدار دهنده به صورت آشکار ، یک متغیر Enum دارای مقدار اولین عضو است .

Enum X { A = 3 , B,C }

مقدار X برابر 3 می شود .// ; X x

لینک کوتاه پست
مطالب مرتبط با پست جاری
  • نکات مهم
    1- لطفا نظر خود را با زبان فارسی بیان کنید
    2- رایتم نظرات اسپم و تبلیغی شما را تایید نمی کند
    3- لطفا نظرات شما بدون ابهام و واضح باشد
  • نام
    ایمیل (منتشر نمی‌شود) (لازم)
    وبسایت
    :):(;):D;)):X:?:P:*=((:O@};-:B/:):S
    نظر خصوصی
    مشخصات شما ذخیره شود ؟[حذف مشخصات] [شکلک ها]
    کد امنیتی
به کانال تلگرام سایت ما بپیوندید