دستکاری نام کیست؟ توضیح بده.
در ساخت کامپایلر، دستکاری نام (که به آن دکوراسیون نام نیز گفته می‌شود) روشی است که در بسیاری از زبان‌های برنامه‌نویسی جدید و سطح بالا برای حل مشکلات ناشی از نیاز به تعریف کردن اسامی منحصر به فرد در هنگام ترجمه به زبان سطح پایین‌تر استفاده می‌شود.این روش، راهی را برای کدگذاری اطلاعات اضافی در نام یک متغیر، تابع، ساختار، کلاس یا نوع‌دادهی دیگر ارائه می‌دهد تا اطلاعات بیشتری از طرف کامپایلرها به پیونددهنده‌ها منتقل شود تا بتوانند اسامی مشترک را از یکدیگر تمیز دهند. چرا که این ویژگی در زبان‌های سطح پایین‌تر (مثلاً اسمبلیها) وجود ندارد و نیاز است که با استفاده از راه دیگری به حل تداخل‌های به وجود آمده در نام‌ها پرداخته شود.نیاز به چنین روشی زمانی به چشم می‌آید که در یک زبان برنامه‌نویسی، امکان تعریف موجودیت‌های مختلف با شناسه‌ی یکسان فراهم باشد (تا زمانی که فضای نام یا امضاءهای متفاوتی داشته باشند). مثلاً امکان اضافه بار توابع (به انگلیسی: ) در برخی زبان‌های برنامه‌نویسی این اجازه را به برنامه‌نویس می‌دهد که برای خوانایی بیشتر برنامه یا راحتی کار خودش، توابع مختلفی با نام یکسان داشته باشد.هر کد هدفی که توسط کامپایلر تولید شده باشد، معمولاً توسط برنامه‌ای به نام پیونددهنده به قطعات دیگری از کد هدف (که ممکن است توسط همین کامپایلر یا کامپایلر دیگری تولید شده باشند) متصل می‌شود. پیونددهنده برای این کار نیاز به اطلاعات جامعی از هر موجودیت برنامه دارد. برای مثال برای آن که یک تابع را به درستی به کد اصلی متصل کند، نیاز به نام، تعداد پارامترها و نوع پارامترهایش دارد.هدف از دستکاری نام.به‌طور کلی می‌توان گفت که امروزه تکنیک‌های دستکاری نام، ۳ هدف اصلی را دنبال می‌کنند که عبارت‌اند از:در ابتدا دستکاری نام تنها برای هدف اول ایجاد شد ولی بعدها در کامپایلرها از آن برای اهداف دیگر نیز استفاده شد. به همین دلیل ممکن است برخی کامپایلرها تنها هدف اول را به کمک دستکاری نام انجام دهند و برای انجام دادن دو کار دیگر از روش‌های دیگری بهره بگیرند.چگونگی دستکاری نام.کامپایلرهای مختلف، به روش‌های مختلفی این کار را انجام می‌دهند. حتی در میان کامپایلرهای موجود برای یک زبان خاص نیز لزوماً این روش یکسان نیست. اما در نهایت همهٔ آنها نام‌ها را در زبان مقصد به طریقی تغییر می‌دهند که به یک مجموعه نام منحصر به فرد برای موجودیت‌های برنامه برسند. برای نمونه تبدیل کد توابع را در نظر بگیرید. دو تابع با نام یکسان، مجبورند که امضاءهای متفاوتی داشته باشند (امضای توابع شامل تعداد، نوع و ترتیب ورودی‌های و خروجی‌هایش است). وگرنه نمی‌توان آنها را از هم تشخیص داد و برنامه دچار خطای زمان کامپایل می‌شود. از همین تفاوت می‌توان استفاده کرد تا برای توابع نام‌های منحصر به فردی تولید کرد.دستکاری نام در زبان‌های C و ++C.به عنوان مثال در برنامهٔ زیر توابعی که نامشان است تداخل قابل رفع دارند؛ ولی دو تابع با نام تداخلشان قابل رفع نیست:int f(int a, int b) { return a + b;int f(int c) { return c;int f(float a, float b) { return 1;int g(int a, int b) { return a + b;int g(int c, int d) { return 1;اکنون برای توابعی که نامشان است، همان‌طور که گفته شد یک ایدهٔ ساده برای رفع تداخل این است که امضای تابع را درون نامش بگنجانیم؛ مثلاً اولین را در نظر بگیرید. خروجی‌اش از نوع صحیح است و ورودی‌هایش نیز دو عدد صحیح اند. می‌توان قبل از نام تابع نوع خروجی‌اش را ذکر کرد و پس از آن نیز نوع ورودی‌هایش را به ترتیب آورد و تمام این‌بخش‌ها را با استفاده از زیر خط از هم جدا کرد. به این ترتیب نام اولین تابع به یا به اختصار تغییر می‌کند. پس از اعمال این کار سه تابع بالا به شکل زیر در می‌آیند:int _i_f_i_i(int a, int b) { return a + b;int _i_f_i(int c) { return c;int _i_f_f_f(float a, float b) { return 1;و همان‌طور که مشاهده می‌کنید دیگر تداخلی در نام توابع وجود ندارد و اسامی کاملاً منحصر به فرد شده‌اند.C.با وجود این که دستکاری نام معمولاً در زبان‌هایی که از اضافه بار توابع پشتیبانی نمی‌کنند (مانند C و classic Pascal) نیاز نمی‌شود، از آن‌ها در برخی کاربردها برای ارائهٔ اطلاعات بیشتر در مورد توابع استفاده می‌شود. به عنوان مثال کامپایلرهایی که هدفشان اجرا شدن برنامه در پلتفرم‌های مایکروسافت ویندوز است، از قراردادهای فراخوانی مختلفی پشتیبانی می‌کنند که شیوهٔ ارسال پارامترها به زیرروال‌ها و دریافت نتایج برگردانده شده را مشخص می‌کنند. از آنجا که این قراردادهای فراخوانی با هم سازگاری ندارند، کامپایلرها از دستکاری استفاده می‌کنند تا بفهمند برای صدا کردن یک زیرروال از کدام قرارداد باید استفاده شود.روش دستکاری توسط مایکروسافت ایجاد شد و پس از آن به صورت غیررسمی توسط کامپایلرهای دیگری مانند Digital Mars، Borland و GNU GCC در هنگام کامپایل کردن کد برای پلتفرم‌های ویندوز استفاده شد. حتی بعدها در زبان‌های دیگری مانند , , Delphi، Fortran و به کار رفت. این موضوع به زیرروال‌های نوشته شده در زبان‌های مذکور این امکان را می‌دهد که توسط کتابخانه‌های ویندوز و با استفاده از قرارداد فراخوانی متفاوتی نسبت به پیش‌فرض خودشان صدا زده شوند.هنگام کامپایل کردن مثال‌های زیر که به زبان C هستند: کامپایلرهای ۳۲ بیتی به ترتیب موارد زیر را خروجی می‌دهند: _f _g@4 @h@4در و که روش‌هایی برای دستکاری نام هستند، به ترتیب تابع به صورت codice_1 و codice_2 کدگذاری می‌شود که تعداد بایت‌های ورودی(ها) در لیست پارامترها (شامل آن‌هایی که در در ثبات‌ها پاس داده می‌شوند) در مبنای ۱۰ است. در حالت صرفاً یک زیر خط (_) ابتدای اسم تابع قرار می‌دهیم.قرارداد ۶۴ بیتی در ویندوز، در ابتدای اسم زیر خط ندارد. این تفاوت باعث می‌شود که در برخی مواقع خاص در هنگام تبدیل کردن کد به نسخهٔ ۶۴ بیتی، تعدادی ارجاع حل‌نشده باقی‌بماند.++C.دستکاری نام در کامپایلرهای ++C بسیار استفاده می‌شود. در استاندارد ++C روش خاصی برای دستکاری نام مشخص نشده‌است بنابراین کامپایلرهای مختلف ممکن است اطلاعات متفاوتی را در اسم‌ها وارد کنند. نمونه‌های اولیهٔ کامپایلرهای ++C کد منبع را به کد زبان C تبدیل می‌کردند و سپس آن کد باید به کد هدف که قابل اجرا بر روی ماشین است تبدیل شود. از این جهت نیاز بود تا نمادها با شناسه‌های C مطابقت داشته‌باشند. حتی بعدها که کامپایلرهایی برای ++C نوشته شدند که کد منبع را مستقیماً به کد قابل اجرا بر روی ماشین تبدیل می‌کردند، پیونددهنده‌های سیستم عموماً از نمادهای ++C پشتیبانی نمی‌کردند و در نتیجه دستکاری نام کماکان نیاز بود.برای زبان ++C یک طرح دکوراسیون (Decoration Scheme) استاندارد وجود ندارد. پس هر کامپایلر مجبور است یک نمونه برای خودش در نظر گرفته و از آن استفاده کند. ++C همچنین شامل ساختارها و ویژگی‌های پیچیده‌ای نظیر کلاس‌ها، قالب‌ها، فضاهای نام و سربارگذاری عملگرها می‌باشد که معنی یک نماد مشخص را بسته به موقعیتی که در آن استفاده می‌شود، تغییر می‌دهد. فراداده در مورد این ویژگی‌ها، با استفاده از دستکاری نام نمادها ممکن است ابهام‌آمیز باشند. از آنجا که سیستم‌های دستکاری نام برای این ویژگی‌ها میان کامپایلرهای مختلف یکسان نیستند، تنها تعداد کمی از پیونددهنده‌ها می‌توانند کد شیءای که توسط کامپایلرهای مختلف تولید شده‌اند را پیوند دهند.در ++C نام متغیر یک فضای نام نیز دستکاری می‌شود به این صورت که اسم فضای نام به آن اضافه می‌شود تا بتوان متغیرهایی با نام یکسان در فضاهای نام متفاوت داشت. کامپایلرهای ++C اسم متغیرهای C را نیز برای تشخیص فضای نامی که متغیر C در آن قرار دارد دستکاری می‌کند.مثالی پیچیده‌تر در زبان ++C.در ابتدای این بخش یک مثال سادهٔ فرضی از دستکاری نام در زبان ++C آورده شد. حال به سراغ یک مثال واقعی‌تر می‌رویم. نمادهای دستکاری شده در این مثال که در کامنت‌هایی زیر هر شناسه آورده شده‌اند، توسط کامپایلرهای GNU GCC 3.x تولید شده‌اند: namespace wikipedia class article public: std::string format (void); /* = _ZN9wikipedia7article6formatEv */ bool print_to (std::ostream&amp;); /* = _ZN9wikipedia7article8print_toERSo */ class wikilink public: wikilink (std::string const&amp; name); /* = _ZN9wikipedia7article8wikilinkC1ERKSs */ }; تمام نمادهای دستکاری شده با codice_3 شروع می‌شوند (توجه داشته باشید که در زبان C شناسه‌ای که با زیر خط و در ادامه یک حرف بزرگ انگلیسی شروع شود، جزو شناسه‌های رزرو است، پس از مغایرت میان شناسه‌ها جلوگیری می‌شود). برای نام‌های تو در تو (شامل فضاهای نام و کلاس‌ها)، به دنبالشان یک codice_4 می‌آید و پس از آن یک دنباله از طول‌ها و شناسه‌ها (منظور طول شناسهٔ بعدی است) قرار می‌گیرد، و در آخر یک codice_5. به عنوان مثال، codice_6 تبدیل می‌شود به: _ZN"9Wikipedia7article6"formatEبرای توابع، پس از آن اطلاعات مربوط به نوع ورودی‌ها می‌آید؛ مثلاً برای که یک تابع (بدون ورودی) است به دنبالش codice_7 قرار می‌گیرد: _ZN"9Wikipedia7article6"formatEvبرای ، نوع استاندارد (که یک برای codice_8 است) استفاده شده‌است، که دارای نام مستعار مخصوص codice_9 است؛ پس یک مرجع برای این نوع codice_10 است و در نتیجه نام کامل تابع برابر خواهد بود با: _ZN"9Wikipedia7article8"print_toERSoچگونه کامپایلرهای مختلف ++C توابع یکسان را دستکاری می‌کنند.آنچه در بالا گفته شد تنها مثالی از یک روش برای دستکاری نام بود. در واقعیت، استانداردی برای نحوهٔ دستکاری نام‌ها در زبان ++C وجود ندارد و کامپایلرهای مختلفی که برای آن وجود دارند به روش‌های گوناگونی این کار را انجام می‌دهند. در جدول زیر می‌توانید مثال‌هایی از تعدادی از این روش‌ها مشاهده کنید:مدیریت نمادهای زبان C هنگام پیوند از ++C.زبان C از پشتیبانی نمی‌کند؛ بنابراین وقتی در کد ++C می‌خواهیم از توابعی استفاده کنیم که به زبان C نوشته‌شده‌اند، باید به کامپایلر ++C بگوییم آن‌ها را دستکاری نکند (در صورت دستکاری‌کردن نام این توابع، پیونددهنده در هنگام پیوند دادن نمی‌تواند تعریف آن‌ها را بیابد). برای این کار از استفاده می‌کنیم.برای مثال، کتابخانه استاندارد رشته‌ها یعنی شامل قطعه‌کدی به صورت زیر است: #ifdef __cplusplusextern "C"void *memset (void *, int, size_t);char *strcat (char *, const char *);int strcmp (const char *, const char *);char *strcpy (char *, const char *); strcpy(a, argv[2]);else memset(a, 0, sizeof(a));زبان‌های برنامه‌نویسی دیگری که از دستکاری نام استفاده می‌کنند.در این مقاله تنها مثال‌هایی از زبان‌های C و ++C آورده شد. اما زبان‌های دیگری نیز هستند که از این تکنیک استفاده می‌کنند. مانند:در لیست بالا تنها تعدادی از زبان‌های معروفی که از این تکنیک استفاده می‌کنند ذکر شده‌اند. به‌طور کلی هر زبانی که در آن قابلیت تعریف موجودیت‌های مختلف با نام‌های یکسان (اضافه بار) وجود داشته باشد می‌تواند به این لیست اضافه شود.