کاربرد union ها در سی

درود, خیلی وقت ها شده که دوستام از من می پرسند که union برای چی هست؟ به درد چی میخوره؟ در این آموزش قصد دارم یک کوچولو از کارای جذابی که میشه با union هارو کرد بهتون بگم. در واقع بااستفاده از union ها شما می توانید با داده های موجود به طریق های مختلف برخورد کنید. برای مثال, در سی تابعی وجود نداره که داده short را در فایل ذخیره کنه اما اگر بخواهید این کارو انجام بدید چه باید کنید؟ این جاهست که از سازندگان سی به خاطر ساخت union ها تشکر می کنید. خب برای کار بالا می تونید به صورت زیر عمل کنید:union w_char{ short int number; char ch[2]; };حال به لطف کد بالا می تونید داده short رو در فایل ذخیره کنید. (داده گرفته شده را در number ذخیره کنید و هنگام نوشتن و خواندن در فایل با chars کار کنید.)اما من می خوام یه کاردیگه ای رو هم با union و struct انجام بدم و اونم بدست آوردن بیت های یک داده ۱ بایتی است.(البته شما با عملگرهای بیتی خیلی سریع می توانید این کارو انجام بدید ولی اینجا برای اینکه نشون بدیم چقدر union ها و struct ها خوب و باحال هستند با اونا این کارو انجام می دیم)چون هر بایت شامل ۸ بیت هست پس یک struct به صورت زیر تعریف می کنیمstruct byte_bits{ _Bool zero:1, one :1, two:1, three:1, four:1, five:1, six:1, seven:1; };در واقع با استفاده از این struct به بیت های یک بایت داده دسترسی پیدا می کنیمحالا با استفاده از union ها این کار رو عملی می کنیم, به این صورتunion char_bits{ struct byte_bits bits; char data; };خب همانطوری که می دونید در union ها بزرگترین داده به عنوان طول union درنظر گرفته میشه و همه داده های فیلد های union در اون فضا ذخیره میشه و ما از این خاصیت باحال اون استفاده می کنید که بیت های داده رو بدست آوریم. پس به تابع زیر دقت کنیدchar *get_bits(char data){ struct byte_bits{ _Bool zero:1, one :1, two:1, three:1, four:1, five:1, six:1, seven:1; }; union char_bits{ struct byte_bits bits; char data; }temp; temp.data = data; char *bits = (char *)malloc(sizeof(char) * 9); *(bits+8) = NULL; *(bits+7) = temp.bits.zero + '0'; *(bits+6) = temp.bits.one + '0'; *(bits+5) = temp.bits.two + '0'; *(bits+4) = temp.bits.three + '0'; *(bits+3) = temp.bits.four + '0'; *(bits+2) = temp.bits.five + '0'; *(bits+1) = temp.bits.six + '0'; *bits = temp.bits.seven + '0'; return bits; }همان طور که دیدید ما داده ای رو که کاربر وارد می کنه با data در union ذخیره می کنیم اما چون به بیت های اون نیاز داریم خودمون با bits کار می کنیم. به این ترتیب ما تونستیم با یک نوع داده به انواع مختلف برخورد کنیم.چند نکته:۱- در کد بالا چون من می خواستم در آخر به شکلی مثل زیرprintf("%s\n", bits);چاپ کنم بیت هارو با '0' جمع کردم که به کد اسکی تبدیل بشه اون عدد مورد نظر.۲- شما می تونید اون کار جمع کردن رو هم به روش های مختلف (برای مثال با if) هم انجام بدید. ۳- شما می توانید برای داده های بیشتر(۲ بایتی,۴بایتی و…) هم این روش رو پیاده سازی کنید.در واقع من فقط می خواستم بهتون نشون بدم که این کار چگونه انجام میشه و شما با خلاقیت خودتون می تونید باهاش کارهای باحال ترو بهتری رو انجام بدید.امیدوارم که این آموزش مفید بوده باشه و دیگه نگید union ها به درد چی می خورند. و در نظر داشته باشید که این یکی از قابلیت های مفید union ها بود و با استفاده از اون شما می توانید کاراهای جذاب تر دیگه هم انجام بدید.و در اخر کد کامل برنامه که تست کنید رو هم براتون گذاشتم#include <stdio.h> #include <stdlib.h> char *get_bits(char data){ struct byte_bits{ _Bool zero:1, one :1, two:1, three:1, four:1, five:1, six:1, seven:1; }; union char_bits{ struct byte_bits bits; char data; }temp; temp.data = data; char *bits = (char *)malloc(sizeof(char) * 9); *(bits+8) = NULL; *(bits+7) = temp.bits.zero + '0'; *(bits+6) = temp.bits.one + '0'; *(bits+5) = temp.bits.two + '0'; *(bits+4) = temp.bits.three + '0'; *(bits+3) = temp.bits.four + '0'; *(bits+2) = temp.bits.five + '0'; *(bits+1) = temp.bits.six + '0'; *bits = temp.bits.seven + '0'; return bits } int main(int argc, char *argv[]) { char a = 129; char *bits = get_bits(a); printf("%s\n", bits); free(bits); return 0; }