زبان برنامه نویسی سی/عملگرهای منطقی و بیتی

عملگرهای بیتی Bitwise Operators

ویرایش

عملگرهای بیتی (Bitwise Operators) پردازش در سطح بیت را بر روی عملوندهای خود انجام می‌دهند . دقت کنید که به غیر از عملگر نه بیتی ، بقیه عملگرها ، تنها می‌توانند بر روی عملوندهای صحیح مثبت ، عمل کنند ( در مورد نه بیتی نیز فقط برخی از کامپایلرها مثل GCC اجازه عمل بر روی اعداد منفی و یا داشتن خروجی منفی را می‌دهند )

در مثال‌های زیر نوع داده را کاراکتر در نظر گرفته‌ایم (char) بنابراین ، اعداد به عنوان عملوند در کاراکترها ذخیره شده‌اند و همچنین نتیجه در یک کاراکتر ذخیره شده است ( در غیر این صورت و به عنوان مثال اگر اعداد در داده‌های صحیح -int- ذخیره شده باشند ، ۸ بیت به ۱۶ بیت و یا ۳۲ بیت تبدیل می‌شود و عمل‌های عملگرهای زیر بر روی آنها نتایج دیگری خواهند داشت )

عملگر نه بیتی ~ :

عملگر ~ (Bitwise Not) اگر در یک عبارت یا زیر عبارت که تنها یک عملوند دارد ، پیش از نام یک شناسه یا یک مقدار عددی قرار بگیرد ، در مبنای دودویی آن عدد یا مقدار شناسه را برعکس می‌کند . یعنی بیت‌های ۱ را به ۰ تبدیل می‌کند و بیت‌های ۰ را به بیت‌های ۱ تبدیل می‌کند
مثلاً a~ مقدار داخل a را در مبنای دودویی برعکس می‌کند یا 4~ که عدد ۴ را که در مبنای دودویی می‌شود 00000100 به 11111011 تبدیل می‌کند که در مبنای دهدهی می‌شود 251
دقت کنید که نوع داده ما عددی بود که در char ذخیره کرده بودیم و یک بایت ، حجم داشت . اگر نوع داده صحیح باشد ۴ بایت حجم خواهد داشت که تمام ۰ های پشت سر عدد ۱۰۰ که همان ۴ است به ۱ تبدیل می‌شوند

عملگر و بیتی & :

عملگر & (Bitwise And) اگر در یک عبارت یا زیر عبارت ، بین دو عملوند قرار بگیرد ، دو مقدار عددی را در مبنای دودویی مورد مطابقت قرار می‌دهد و اگر هر دو بیت‌ها ۱ باشند ۱ را خروجی می‌دهد ولی اگر هر یک و یا هر دوی آنها ۰ باشند ، ۰ را خروجی می‌دهد . مثلاً 9 & 5 که 5 در مبنای دودویی در یک بایت می‌شود 00000101 و 9 در مبنای دودویی می‌شود 00001001 که فقط بیت آخر در هر دو ۱ می‌باشد بنابراین بیت آخر می‌شود 1 و همه بیت‌های قبل از آن 0 می‌شوند که می‌شود 00000001 که در مبنای دهدهی خودمان می‌شود 1

عملگر یا بیتی | :

عملگر | (Bitwise OR) اگر در یک عبارت یا زیر عبارت ، بین دو عملوند قرار بگیرد ، دو مقدار عددی را در مبنای دودویی مورد مطابقت قرار می‌دهد و اگر هر یک از بیت‌های عملوندها ۱ باشد ، ۱ را خروجی می‌دهد و اگر هر دو ۰ باشند ، ۰ را خروجی خواهد داد . مثلاً 9 | 5 که دو عدد ۵ و ۹ در مبنای دودویی می‌شوند 00000101 و 00001001 که تنها بیت یکی مانده به آخر در هر دوی آنها 0 است در نتیجه عدد به دست آمده می‌شود 00001101 که در مبنای دهدهی می‌شود 13

عملگر زُر (XOR) ^ :

عملگر ^ (Bitwise XOR) تلفیق AND و OR بیتی است که می‌شود زور XOR و در یک عبارت یا زیر عبارت اگر دو عملوند ، سمت چپ و راست این عملگر قرار بگیرند ، دو مقدار عددی را در مبنای دودویی مورد مطابقت قرار می‌دهد و اگر دو بیت متناظر ، متفاوت باشند ۱ را در خروجی باز می‌گرداند و اگر یکسان باشند ۰ را خروجی می‌دهد . به طور مثال 9 ^ 5 که خروجی آن 00001100 است و در مبنای دهدهی می‌شود 12

عملگر انتقال به چپ بیتی >> :

عملگر >> اگر یک عملوند در سمت چپش قرار بگیرد ، آن را به لحاظ بیتی ، در مبنای دودویی ، به اندازه عملوند سمت راست عملگر ، به سمت چپ انتقال می‌دهد و در مقابل عدد عملوند چپ در مبنای دودویی به اندازه عملوندِ سمت راست ، 0 قرار می‌دهد . مثلاً 12 در مبنای دودویی می‌شود 1100 که اگر آن را در یک کاراکتر ذخیره کرده باشیم می‌شود 00001100 و اگر بنویسیم 2 >> 12 عدد 1100 ( که همان 12 است ) دو بیت به سمت چپ انتقال پیدا می‌کند و می‌شود 00110000 که در مبنای دهدهی می‌شود 48 نکته : هر یک واحد انتقال به چپ بیتی به منزله یک بار ضرب شدن عدد در ۲ است . مثلاً ۱۶ در مبنای دودویی می‌شود 00010000 که اگر یک واحد به چپ انتقال بدهیم ( 1 >> 16 ) می‌شود ۳۲ یعنی 00100000 و اگر دو واحد به چپ انتقال دهیم ۱۶ می‌شود ۶۴ یعنی 01000000 . عمل انتقال به چپ نسبت به عمل ضرب در CPU سریع‌تر انجام می‌شود

عملگر انتقال به راست بیتی << :

عملگر >> اگر یک عملوند در سمت چپش قرار بگیرد ، آن را به لحاظ بیتی ، در مبنای دودویی ، به اندازه عملوند سمت راست عملگر ، به سمت راست انتقال می‌دهد و در پشت عدد عملوند چپ در مبنای دودویی به اندازه عملوند سمت راست ، 0 قرار می‌دهد . مثلاً 12 که در مثال پیشین هم نوشتیم در یک کاراکتر در مبنای دودویی می‌شود 00001100 و اگر بنویسیم 3 << 12 عدد 1100 ( که همان 12 است ) سه بیت به سمت راست انتقال می‌یابد و می‌شود 00000001 که در مبنای دهدهی می‌شود 1 و اگر دو بیت آن را انتقال می‌دادیم می‌شد 00000011 که در مبنای دهدهی می‌شود 3 نکته : هر یک واحد انتقال به راست بیتی به منزله یک بار تقسیم عدد به ۲ است ؛ که البته اگر عدد بخش پذیر نباشد ، گرد می‌شود . مثلاً ۱۷ در مبنای دودویی می‌شود 00010001 که اگر یک واحد آن را به سمت راست انتقال دهیم می‌شود ۸ یعنی 00001000 و اگر دو واخد به سمت راست انتقال دهیم می‌شود ۴ یعنی 00000100 . عمل انتقال به راست نسبت به عمل تقسیم در CPU سریع‌تر انجام می‌شود

دقت کنید : همان طور که در ابتدای موضوع هم نوشتیم ، عمل‌های بیتی نمی‌توانند بر روی اعداد منفی عمل کنند و یا خروجی منفی بدهند ( به غیر از نه بیتی که کامپایلری مثل GCC از خروجی منفی آن پشتیبانی می‌کند )

دقت کنید : در عمل انتقال به چپ و راست ، مقدار انتفال باید از تعداد بیت‌های نوع داده‌ای که می‌خواهید آن را انتقال دهید ، کمتر باشد . مثلاً 341 >> 7 در کامپایلرها تعریف نشده است و اگر چنین کدهایی بنویسید رفتاری تعریف نشده بروز خواهد داد ( مثلاً نوع داده char هشت بیت دارد و شما تعیین می‌کنید تا ۵۶ بیت عدد انتقال یابد به چپ که عدد در نهایت می‌شود 0 اما کامپایلرها معمولاً از آن پشتیبانی نمی‌کنند )

عملگرهای منطقی Logical Operators

ویرایش

عملگر نه منطقی ! :

عملگر ! ، اگر در یک عبارت یا زیر عبارت که تنها یک عملوند دارد ، پیش از نام یک شناسه یا یک مقدار عددی قرار بگیرد ، خلاف مقدار ۰ و ۱ ـی آن را باز می‌گرداند . اگر مقدار ، هر چیزی جز 0 باشد مقدار 0 را باز می‌گرداند و اگر 0 باشد مقدار 1 را باز می‌گرداند . ضمن اینکه در مقدارهای منطقی Boolean اگر مقدار غلط باشد (false) ، مقدار درست را باز می‌گرداند (true) و اگر مقدار true باشد مقدار غلط false را باز می‌گرداند
مثلاً a! یا 5! که در مورد دومی چون 5 مغایر با 0 است مقدار 0 را باز می‌گرداند

عملگر و منطقی && :

عملگر && اگر دو عبارت در سمت راست و چپ خود داشته باشد ، اگر هر دوی آنها درست true یا غیر 0 باشند مقدار درست true یا مقدار غیر 0 را باز می‌گرداند و در صورتی که هر یک از آنها 0 یا غلط false باشد مقدار 0 یا غلط false را باز می‌گرداند . مثلاً (4>2 && 1==1) مقدار درست true و مغایر با 0 ( معمولاً 1 ) را باز می‌گرداند ( چرا که ۴ بزرگتر از ۲ است و ۱ هم مساوی ۱ است )

عملگر یا منطقی || :

عملگر || اگر دو عبارت در سمت راست و چپ خود داشته باشد ، اگر هر یک از آنها درست true یا غیر 0 باشد ، مقدار درست true یا مقدار غیر 0 ( معمولاً 1 ) را باز می‌گرداند و در صورتی که هر دوی آنها غلط false یا 0 باشند مقدار غلط false یا 0 زا باز می‌گرداند ( بدیهی است که اگر هر دو درست باشند ، نتیجه ارزیابی « درست » است ) مثلاً (5>8 || 2 =! 9) مقدار درست true و مغایر با 0 دارد ( چرا که ۹ مساوی ۲ دو نیست و این عبارت صحیح است و علیرغم درست نبودن عبارت ۵>۸ که می‌گوید ۸ کوچکتر از ۵ است ، باز هم مقدار ارزیابی « درست » است ؛ چرا که یکی از آنها درست است یعنی یکی از عبارت اول یا دوم درست است )