<?xml version="1.0"?>
<rss version="2.0"><channel><title>&#x627;&#x644;&#x628;&#x631;&#x645;&#x62C;&#x629;: &#x644;&#x63A;&#x629; C++</title><link>https://academy.hsoub.com/programming/cpp/page/4/?d=2</link><description>&#x627;&#x644;&#x628;&#x631;&#x645;&#x62C;&#x629;: &#x644;&#x63A;&#x629; C++</description><language>ar</language><item><title>&#x627;&#x644;&#x645;&#x643;&#x631;&#x627;&#x631;&#x627;&#x62A; (Iterators) &#x641;&#x64A; Cpp</title><link>https://academy.hsoub.com/programming/cpp/%D8%A7%D9%84%D9%85%D9%83%D8%B1%D8%A7%D8%B1%D8%A7%D8%AA-iterators-%D9%81%D9%8A-cpp-r892/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2020_06/8.png.49a1ca780551bcc136d256634831fb7d.png" /></p>

<p>
	المكررات (Iterators) وسيلة لتنفيذ عمليات على سلسلة عناصر على التوالي، رغم أنها ليست عناصر في نفسها، وإنما هي في الأساس عبارة عن مواضع (Positions)، كذلك فإنها امتداد لمفهوم المؤشرات، انظر المثال التالي:
</p>

<pre class="ipsCode">
A B C
</pre>

<p>
	يحتوي التسلسل السابق على ثلاثة عناصر، وأربعة مواضع كما يوضح التمثيل التالي:
</p>

<pre class="ipsCode">
+---+---+---+---+
| A  |  B | C |    |
+---+---+---+---+
</pre>

<p>
	العناصر هي أشياء تؤلف تسلسلًا معيّنًا، أما المواضع فهي الأماكن التي يمكن أن تحدث فيها عمليات ما على ذلك التسلسل، فعند إدراج عنصر جديد فإننا ندرجه في موضع ما قبل أو بعد العنصر A مثلًا، وليس داخل العنصر A نفسه، بل حتى حذف العنصر يتم بإيجاد موضعه أولًا ثم حذفه (<code>erase(A</code>.
</p>

<h3>
	من المكرِّرات إلى القيم
</h3>

<p>
	للانتقال من موضع إلى قيمة، يجب أن يُحصّل (dereferenced) المُكرِّر:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1044_7" style="">
<span class="kwd">auto</span><span class="pln"> my_iterator </span><span class="pun">=</span><span class="pln"> my_vector</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">();</span><span class="pln"> </span><span class="com">// موضع</span><span class="pln">
</span><span class="kwd">auto</span><span class="pln"> my_value </span><span class="pun">=</span><span class="pln"> </span><span class="pun">*</span><span class="pln">my_iterator</span><span class="pun">;</span><span class="pln"> </span><span class="com">// قيمة</span></pre>

<p>
	يمكن النظر إلى المُكرِّر كمُحصِّلٍ للقيمة التي يشير إليها في التسلسل، لهذا يجب ألا تحاول أبدًا تحصيل الموضع <code>end()‎</code> في التسلسل:
</p>

<pre class="ipsCode">
+---+---+---+---+
| A  |  B | C |    |
+---+---+---+---+
↑               ↑
|               +-- مكرّر لا يشير إلى أي قيمة، لا تحاول تحصيله
+---------------   A تحصيل هذا المكرّر سيعيد القيمة
</pre>

<p>
	سيعيد التعبير <code>begin()</code> مكرِّرًا يشير إلى الموضع الأول، وذلك في جميع التسلسلات والحاويات (Containers) الموجودة في مكتبة C++ القياسية، بينما سيعيد <code>end()</code> مكرِّرًا يشير إلى موضع يلي الموضع الأخير (وليس الموضع الأخير نفسه)، لهذا تسمى تلك المكررات أحيانًا <code>first</code> و <code>last</code>. انظر المثال التالي:
</p>

<pre class="ipsCode">
+---+---+---+---+
|  A | B | C |     |
+---+---+---+---+
↑               ↑
|                |
+- first       +- last
</pre>

<p>
	من الممكن الحصول على مُكرِّر لأي تسلسل، ذلك أن جميع التسلسلات -حتى الفارغة منها- تحتوي على موضع واحد على الأقل:
</p>

<pre class="ipsCode">
+---+
|      |
+---+
</pre>

<p>
	في التسلسل الفارغ، يمثّل كل من <code>begin()‎</code> و <code>end()‎</code> نفس الموضع، ولا يمكن تحصيل أيّ منهما، انظر المثال التالي:
</p>

<pre class="ipsCode">
+---+
|      |
+-----+
    ↑
    |
   +- empty_sequence.begin()
   | 
  +- empty_sequence.end()
</pre>

<p>
	كذلك يمكن تصوّر المكرِّرات على أنها إشارات تحدد المواضع بين العناصر:
</p>

<pre class="ipsCode">
+---+---+---+
| A | B | C |
+---+---+---+
↑    ^    ^    ↑
|                 |
+- first       +- last
</pre>

<p>
	ووفقًا لهذا التصوّر فإنّ تحصيل المُكرِّر سيعيد مرجعًا إلى العنصر الذي يأتي بعد المُكرِّر، وهذا مفيد في العمليات التالية:
</p>

<ul>
<li>
		عمليات <code>insert</code> ستدرج عنصرًا في الموضع الذي يشير إليه المكرر.
	</li>
	<li>
		عمليات <code>erase</code> ستعيد مكررًا يتوافق مع نفس الموضع الذي تم المرور عليه.
	</li>
	<li>
		يتواجد المُكرّر، ومُكرّره المعكوس (Reverse Iterator) في نفس الموضع بين العناصر.
	</li>
</ul>
<h3>
	المكرِّرات غير الصالحة (Invalid Iterators)
</h3>

<p>
	يصير المكرر غيرَ صالحٍ إن لم يعد موضعُه جزءًا من التسلسل (مثال: أثناء عملية ما)، ولا يمكن تحصيل المكرر غير الصالح إلا بعد إسناده (Assign) إلى موضع آخر صالح. انظر المثال التالي الذي يكون فيه <code>first</code> صالحًا، ثم يخرج <code>foo</code> عن النطاق ويحذف، فيصير <code>first</code> بعد ذلك غير صالح.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1044_9" style="">
<span class="pln">std</span><span class="pun">::</span><span class="typ">vector</span><span class="str">&lt;int&gt;</span><span class="pun">::</span><span class="typ">iterator</span><span class="pln"> first</span><span class="pun">;</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    std</span><span class="pun">::</span><span class="typ">vector</span><span class="str">&lt;int&gt;</span><span class="pln"> foo</span><span class="pun">;</span><span class="pln">
    first </span><span class="pun">=</span><span class="pln"> foo</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">();</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	الخوارزميات ودوال توابع التسلسلات (sequence member functions) التي في مكتبة C++‎ القياسية لديها قواعد تضبط التعامل مع المكررات حين يتم إبطالها (invalidated)، ولكل خوارزمية طريقة مختلفة في التعامل مع المكررات وإبطالها.
</p>

<h3>
	التنقل باستخدام المكررات
</h3>

<p>
	تُستخدم المكررات للتنقل بين عناصر التسلسل إذ ينقل المكرر موضعه خلال التسلسل، ويستطيع أن يتحرك في كلا الاتجاهين، للأمام أو للخلف.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1044_11" style="">
<span class="kwd">auto</span><span class="pln"> first </span><span class="pun">=</span><span class="pln"> my_vector</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">();</span><span class="pln">

</span><span class="com">// تقديم المكرر بمَوضع واحد</span><span class="pln">
</span><span class="pun">++</span><span class="pln">first</span><span class="pun">;</span><span class="pln">                        

</span><span class="com">// تقديم المكرَر بموضع واحد</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">advance</span><span class="pun">(</span><span class="pln">first</span><span class="pun">,</span><span class="pln"> </span><span class="lit">1</span><span class="pun">);</span><span class="pln">         

</span><span class="com">// إعادة المكرَر إلى العنصر التالي</span><span class="pln">
first </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">next</span><span class="pun">(</span><span class="pln">first</span><span class="pun">);</span><span class="pln">         

</span><span class="com">// تأخير المكرَر بموضع واحد</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">advance</span><span class="pun">(</span><span class="pln">first</span><span class="pun">,</span><span class="pln"> </span><span class="pun">-</span><span class="lit">1</span><span class="pun">);</span><span class="pln">        

</span><span class="com">// إعادة المكرَر 20 موضعا إلى الأمام</span><span class="pln">
first </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">next</span><span class="pun">(</span><span class="pln">first</span><span class="pun">,</span><span class="pln"> </span><span class="lit">20</span><span class="pun">);</span><span class="pln">     

</span><span class="com">// إعادة المكرر 5 مواضع إلى الخلف</span><span class="pln">
first </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">prev</span><span class="pun">(</span><span class="pln">first</span><span class="pun">,</span><span class="pln"> </span><span class="lit">5</span><span class="pun">);</span><span class="pln">    

</span><span class="com">// إعادة المسافة بين مكرّرين</span><span class="pln">
</span><span class="kwd">auto</span><span class="pln"> dist </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">distance</span><span class="pun">(</span><span class="pln">my_vector</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">(),</span><span class="pln"> first</span><span class="pun">);</span></pre>

<p>
	يجب أن يكون الوصول من الوسيط الأول إلى الوسيط الثاني لـ <code>std::distance</code> ممكنًا، بمعنى أن يكون <code>first</code> أصغر من أو يساوي <code>second</code>. ورغم أنك تستطيع إجراء عمليات حسابية على المكررات إلا أن هذا لا يعني أن جميع العمليات قابلة للتطبيق على المكررات كلها، فقد تصلح العملية <code>a = b + 3;</code>‎ لمكررات الوصول العشوائي (Random Access Iterators)، لكنها لن تصلح مع المكررات الأمامية (Forward Iterators) أو ثنائية الاتجاه (Bidirectional) التي يمكن نقلها ثلاثة مواضع للأمام عبر التعليمة <code>b = a; ++b; ++b; ++b;</code>‎، لذلك يوصى باستخدام دوال خاصة إن لم تكن تعرف نوع المكرِّر، كما في حالة قوالب الدوال التي تقبل المكررات.
</p>

<h3>
	مفاهيم المُكرِّرات (Iterator Concepts)
</h3>

<p>
	يصف معيار C++‎ العديد من مفاهيم المكررات، وقد جُمعت معًا وفقًا لسلوكها في التسلسلات التي تشير إليها، فإن عرفت السلوك العام للمكرِّر، عرفتَ سلوكه في أي تسلسل يشير إليه. وتوصف مفاهيم المكررات تلك مرتبة من أكثرهًا تقييدًا إلى أقلها:
</p>

<ul>
<li>
		مكررات الدخل (Input Iterators): يمكن تحصيلها مرة واحدة فقط لكل موضع، ويمكن نقلها للأمام موضعًا واحدًا فقط في كل مرة، إذ لا تنتقل للوراء.
	</li>
	<li>
		مكررات التقدم (Forward Iterators): يمكن تحصيل هذه المكرّرات أيّ عدد من المرات.
	</li>
	<li>
		المكرّرات ثنائية الاتجاه (Bidirectional Iterators): هي مكررات تقدم تستطيع التحرك للخلف كذلك موضعًا واحدًا في كل مرة.
	</li>
	<li>
		المكرّرات العشوائية (Random Access Iterators): هي مكرّرات ثنائية الاتجاه تتحرك بحرية للأمام أو الخلف أي عدد من المواضع في كل مرة.
	</li>
	<li>
		المكرّرات المتجاورة (Contiguous Iterators) (منذ C++17): هي مكرّرات عشوائية تضمن أنّ البيانات التي تشير إليها متجاورة في الذاكرة. قد تختلف الخوارزميات وفقًا لمفاهيم المكرِّرات، فرغم إمكانية تقديم <code>random_shuffle</code> مثلًا للمكرِّرات الأماميّة إلا أن هناك بديلًا يتطلب مكرِّرات عشوائية يمكن توفيره، وسيكون أفضل.
	</li>
</ul>
<h3>
	سمات المُكرِّرات (Iterator traits)
</h3>

<p>
	توفّر سمات المكرّرات واجهة موحّدة لخصائص المكرِّرات. إذ تسمح لك بجلب نوع القيمة <code>value_type</code> ونوع الفرق <code>difference_type</code> وكذلك المؤشر <code>pointer</code> والمرجع <code>reference</code>، إضافة إلى فئة المكرر <code>iterator_category</code>، انظر المثال التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1044_13" style="">
<span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Iter</span><span class="pun">&gt;</span><span class="pln">
</span><span class="typ">Iter</span><span class="pln"> find</span><span class="pun">(</span><span class="typ">Iter</span><span class="pln"> first</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Iter</span><span class="pln"> last</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">iterator_traits</span><span class="pun">&lt;</span><span class="typ">Iter</span><span class="pun">&gt;::</span><span class="pln">value_type val</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
   </span><span class="kwd">while</span><span class="pln"> </span><span class="pun">(</span><span class="pln">first </span><span class="pun">!=</span><span class="pln"> last</span><span class="pun">)</span><span class="pln">
   </span><span class="pun">{</span><span class="pln">
       </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(*</span><span class="pln">first </span><span class="pun">==</span><span class="pln"> val</span><span class="pun">)</span><span class="pln">
           </span><span class="kwd">return</span><span class="pln"> first</span><span class="pun">;</span><span class="pln">
       </span><span class="pun">++</span><span class="pln">first</span><span class="pun">;</span><span class="pln">
   </span><span class="pun">}</span><span class="pln">
   </span><span class="kwd">return</span><span class="pln"> last</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	يمكن استخدام فئة المُكرِّر <code>iterator_category</code> لتخصيص الخوارزميات:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1044_15" style="">
<span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">BidirIt</span><span class="pun">&gt;</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> test</span><span class="pun">(</span><span class="typ">BidirIt</span><span class="pln"> a</span><span class="pun">,</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">bidirectional_iterator_tag</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"Bidirectional iterator is used"</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">ForwIt</span><span class="pun">&gt;</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> test</span><span class="pun">(</span><span class="typ">ForwIt</span><span class="pln"> a</span><span class="pun">,</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">forward_iterator_tag</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"Forward iterator is used"</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Iter</span><span class="pun">&gt;</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> test</span><span class="pun">(</span><span class="typ">Iter</span><span class="pln"> a</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    test</span><span class="pun">(</span><span class="pln">a</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">iterator_traits</span><span class="pun">&lt;</span><span class="typ">Iter</span><span class="pun">&gt;::</span><span class="pln">iterator_category</span><span class="pun">());</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	فئات المكرِّرات هي في الأساس مفاهيم مُكرّرات، باستثناء أنّ المكرّرات المتجاورة (Contiguous Iterators) ليس لها وسم (tag) خاص بها، إذ أنها مُخصّصة لإيقاف الشيفرة (break code).
</p>

<h2>
	المُكرِّر المُتّجِهي (Vector Iterator)
</h2>

<p>
	تعيد <code>begin</code> مكرّرًا <code>iterator</code> يشير إلى العنصر الأول في حاوية التسلسل (sequence container)، بينما تعيد <code>end</code> مكرّرًا يشير إلى العنصر الأول بعد النهاية.
</p>

<p>
	إذا كان الكائن المتّجهي (vector object) ثابتًا <code>const</code> فإنّ كلًّا من <code>begin</code> و <code>end</code> ستعيدان مُكّررًا ثابتًا <code>const_iterator</code>، وإن أردت أن يُعاد مكرّر ثابت حتى لو لم تكن المتجهة ثابتة، فاستخدم <code>cbegin</code> و <code>cend</code>. انظر المثال التالي حيث نهيئ متجهًا باستخدام <code>initializer_list</code>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1044_17" style="">
<span class="com">#include</span><span class="pln"> </span><span class="str">&lt;vector&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;iostream&gt;</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> main</span><span class="pun">()</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    std</span><span class="pun">::</span><span class="typ">vector</span><span class="str">&lt;int&gt;</span><span class="pln"> v </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3</span><span class="pun">,</span><span class="pln"> </span><span class="lit">4</span><span class="pun">,</span><span class="pln"> </span><span class="lit">5</span><span class="pun">};</span><span class="pln">
    </span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="typ">vector</span><span class="str">&lt;int&gt;</span><span class="pun">::</span><span class="typ">iterator</span><span class="pln"> it </span><span class="pun">=</span><span class="pln"> v</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">();</span><span class="pln"> it </span><span class="pun">!=</span><span class="pln"> v</span><span class="pun">.</span><span class="pln">end</span><span class="pun">();</span><span class="pln"> </span><span class="pun">++</span><span class="pln">it</span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="pun">*</span><span class="pln">it </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">" "</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	سيكون الخرج:
</p>

<pre class="ipsCode">
1 2 3 4 5 
</pre>

<h2>
	مكرّرات القواميس <code>map_iterator</code>
</h2>

<p>
	مكرّرات القواميس هي مكرّرات تشير إلى العنصر الأول في الحاوية. ستعيد الدالة مكررًا ثابتًا <code>const_iterator</code> إذا كان كائن الحاوية مؤهلًا ثبوتيًا (const_qualified)، أما إن كان خلاف ذلك فستعيد مكرّرًا عاديًا. انظر المثال التالي حيث ننشئ قاموسًا وندرج فيه بعض العناصر، ثم نكرره على جميع الأزواج:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1044_19" style="">
<span class="pln">std</span><span class="pun">::</span><span class="typ">map</span><span class="pun">&lt;</span><span class="kwd">char</span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pun">&gt;</span><span class="pln"> mymap</span><span class="pun">;</span><span class="pln">
mymap</span><span class="pun">[</span><span class="str">'b'</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">100</span><span class="pun">;</span><span class="pln">
mymap</span><span class="pun">[</span><span class="str">'a'</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">200</span><span class="pun">;</span><span class="pln">
mymap</span><span class="pun">[</span><span class="str">'c'</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">300</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="typ">map</span><span class="pun">&lt;</span><span class="kwd">char</span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pun">&gt;::</span><span class="typ">iterator</span><span class="pln"> it </span><span class="pun">=</span><span class="pln"> mymap</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">();</span><span class="pln"> it </span><span class="pun">!=</span><span class="pln"> mymap</span><span class="pun">.</span><span class="pln">end</span><span class="pun">();</span><span class="pln"> </span><span class="pun">++</span><span class="pln">it</span><span class="pun">)</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> it</span><span class="pun">-&gt;</span><span class="pln">first </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">" =&gt; "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> it</span><span class="pun">-&gt;</span><span class="pln">second </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">'\n'</span><span class="pun">;</span></pre>

<p>
	سيكون الخرج:
</p>

<pre class="ipsCode">
a =&gt; 200
b =&gt; 100
c =&gt; 300 
</pre>

<h2>
	المكرِّرات العكسيّة (Reverse Iterators)
</h2>

<p>
	تُستخدم المكررات العكسية <code>reverse_iterator</code> عندما نريد أن نحرِّك المكرِّر للخلف خلال قائمة أو متجه، ونحصل على تلك المكررات من مكرر ثنائي الاتجاه أو مكرر عشوائي، وهما يحتفظان بذلك المكرر كعضو يمكن الوصول إليه من خلال التابع <code>base()‎</code>. ولكي يتحرّك المُكرِّر للخلف، عليك استخدام <code>rbegin()‎</code> و <code>rend()‎</code> كمكرّرين يشيران إلى نهاية وبداية المجموعة على الترتيب. انظر المثال التالي الذي نكرر فيه إلى الخلف لنطبع (54321):
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1044_21" style="">
<span class="pln">std</span><span class="pun">::</span><span class="typ">vector</span><span class="str">&lt;int&gt;</span><span class="pln"> v</span><span class="pun">{</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3</span><span class="pun">,</span><span class="pln"> </span><span class="lit">4</span><span class="pun">,</span><span class="pln"> </span><span class="lit">5</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="typ">vector</span><span class="str">&lt;int&gt;</span><span class="pun">::</span><span class="pln">reverse_iterator it </span><span class="pun">=</span><span class="pln"> v</span><span class="pun">.</span><span class="pln">rbegin</span><span class="pun">();</span><span class="pln"> it </span><span class="pun">!=</span><span class="pln"> v</span><span class="pun">.</span><span class="pln">rend</span><span class="pun">();</span><span class="pln"> </span><span class="pun">++</span><span class="pln">it</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="pun">*</span><span class="pln">it</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	كذلك يمكن تحويل مكرّر عكسي إلى مكرّر أمامي من خلال التابع <code>base()‎</code>، ويشير المكرّر العكسي إلى العنصر الذي يلي المكرّر <code>base()‎</code>، انظر المثال التالي حيث تكون <code>assert(&amp;*r == &amp;*(i-1));</code>‎ صحيحة إن كان <code>r</code> و <code>(i-1)</code> يقبلان التحصيل (Dereferencing) ولم يكونا مكرريْن وكيلين (Proxy Iterators).
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1044_23" style="">
<span class="pln">std</span><span class="pun">::</span><span class="typ">vector</span><span class="str">&lt;int&gt;</span><span class="pun">::</span><span class="pln">reverse_iterator r </span><span class="pun">=</span><span class="pln"> v</span><span class="pun">.</span><span class="pln">rbegin</span><span class="pun">();</span><span class="pln">
std</span><span class="pun">::</span><span class="typ">vector</span><span class="str">&lt;int&gt;</span><span class="pun">::</span><span class="typ">iterator</span><span class="pln"> i </span><span class="pun">=</span><span class="pln"> r</span><span class="pun">.</span><span class="pln">base</span><span class="pun">();</span><span class="pln">
assert</span><span class="pun">(&amp;*</span><span class="pln">r </span><span class="pun">==</span><span class="pln"> </span><span class="pun">&amp;*(</span><span class="pln">i</span><span class="pun">-</span><span class="lit">1</span><span class="pun">));</span><span class="pln"> 
</span><span class="pun">+----+---+---+---+---+---+---+</span><span class="pln">
</span><span class="pun">|</span><span class="pln">      </span><span class="pun">|</span><span class="pln">  </span><span class="lit">1</span><span class="pln"> </span><span class="pun">|</span><span class="pln">  </span><span class="lit">2</span><span class="pln"> </span><span class="pun">|</span><span class="pln">  </span><span class="lit">3</span><span class="pln"> </span><span class="pun">|</span><span class="pln">  </span><span class="lit">4</span><span class="pln"> </span><span class="pun">|</span><span class="pln">  </span><span class="lit">5</span><span class="pln"> </span><span class="pun">|</span><span class="pln">    </span><span class="pun">|</span><span class="pln">
</span><span class="pun">+----+---+---+---+---+---+---+</span><span class="pln">
  </span><span class="pun">↑</span><span class="pln">      </span><span class="pun">↑</span><span class="pln">                     </span><span class="pun">↑</span><span class="pln">    </span><span class="pun">↑</span><span class="pln">
  </span><span class="pun">|</span><span class="pln">       </span><span class="pun">|</span><span class="pln">                      </span><span class="pun">|</span><span class="pln">     </span><span class="pun">|</span><span class="pln">
rend</span><span class="pun">()</span><span class="pln">  </span><span class="pun">|</span><span class="pln">              rbegin</span><span class="pun">()</span><span class="pln">     end</span><span class="pun">()</span><span class="pln">
          </span><span class="pun">|</span><span class="pln">                                  rbegin</span><span class="pun">().</span><span class="pln">base</span><span class="pun">()</span><span class="pln">
        begin</span><span class="pun">()</span><span class="pln">
       rend</span><span class="pun">().</span><span class="pln">base</span><span class="pun">()</span></pre>

<p>
	ستكون العلاقة أبسط إن عدنا إلى التصور السابق حيث تحدِّد المكرراتُ المواضع بين العناصر، انظر:
</p>

<pre class="ipsCode">
+---+---+---+---+---+
|  1 |  2 |  3 |  4 |  5 |
+---+---+---+---+---+
↑                           ↑
|                            |
|                        end()
|                       rbegin()
begin()              rbegin().base()
rend()
rend().base()
</pre>

<h2>
	مُكرِّر التدفق <code>istream_iterator</code>
</h2>

<p>
	مُكرِّرات التدفق مفيدة عندما نحتاج إلى قراءة تسلسل أو طباعة بيانات منسّقة (formatted) من الحاوية، لنضرب مثلًا ببرنامج يطبع أرقامًا صحيحة تفصل بين كل منها فاصلتين متتاليتين <code>--</code>، ولنفصله جزءًا جزءًا للتوضيح، فأول جزء يوضح تدفقًا للبيانات، يكون أي عدد من محارف المسافات البيضاء فيه مقبولًا.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1044_25" style="">
<span class="pln">std</span><span class="pun">::</span><span class="pln">istringstream istr</span><span class="pun">(</span><span class="str">"1\t 2     3 4"</span><span class="pun">);</span><span class="pln">
std</span><span class="pun">::</span><span class="typ">vector</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> v</span><span class="pun">;</span></pre>

<p>
	نبني الآن مكررات تدفق وننسخ البيانات من التدفق إلى متجه:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1044_27" style="">
<span class="pln">std</span><span class="pun">::</span><span class="pln">copy</span><span class="pun">(</span><span class="pln"> </span></pre>

<p>
	ونستخدم مكررًا يقرأ بيانات التدفق كأعداد صحيحة:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1044_29" style="">
<span class="pln">std</span><span class="pun">::</span><span class="pln">istream_iterator </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">(</span><span class="pln">istr</span><span class="pun">),</span></pre>

<p>
	ينتج الباني الافتراضي مكررًا يشير إلى نهاية التدفق:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1044_31" style="">
<span class="pln">std</span><span class="pun">::</span><span class="pln">istream_iterator </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">(),</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">back_inserter</span><span class="pun">(</span><span class="pln">v</span><span class="pun">));</span></pre>

<p>
	نطبع الآن محتوى المتجه الذي سيكون في مجرى الدخل القياسي كأعداد صحيحة مفصولة بفاصلتين متتاليتين (--):
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1044_33" style="">
<span class="pln">std</span><span class="pun">::</span><span class="pln">copy</span><span class="pun">(</span><span class="pln">v</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">(),</span><span class="pln"> v</span><span class="pun">.</span><span class="pln">end</span><span class="pun">(),</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">ostream_iterator </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">cout</span><span class="pun">,</span><span class="pln"> </span><span class="str">" -- "</span><span class="pun">));</span></pre>

<p>
	انظر الآن الشيفرة كاملة دون التعليقات التوضيحية:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1044_35" style="">
<span class="pln">std</span><span class="pun">::</span><span class="pln">istringstream istr</span><span class="pun">(</span><span class="str">"1\t 2     3 4"</span><span class="pun">);</span><span class="pln">
std</span><span class="pun">::</span><span class="typ">vector</span><span class="str">&lt;int&gt;</span><span class="pln"> v</span><span class="pun">;</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">copy</span><span class="pun">(</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">istream_iterator</span><span class="str">&lt;int&gt;</span><span class="pun">(</span><span class="pln">istr</span><span class="pun">),</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">istream_iterator</span><span class="str">&lt;int&gt;</span><span class="pun">(),</span><span class="pln">   
    std</span><span class="pun">::</span><span class="pln">back_inserter</span><span class="pun">(</span><span class="pln">v</span><span class="pun">));</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">copy</span><span class="pun">(</span><span class="pln">v</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">(),</span><span class="pln"> v</span><span class="pun">.</span><span class="pln">end</span><span class="pun">(),</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">ostream_iterator</span><span class="str">&lt;int&gt;</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">cout</span><span class="pun">,</span><span class="pln"> </span><span class="str">" -- "</span><span class="pun">));</span></pre>

<p>
	ويكون الناتج المطبوع للبرنامج أعلاه هو التالي:
</p>

<pre class="ipsCode">
1 -- 2 -- 3 -- 4 --
</pre>

<h2>
	مكرِّرات C (المؤشرات)
</h2>

<p>
	انظر المثال التالي لشيفرة ستُنتج الأرقام من 1 إلى 5 بحيث تطبع كل رقم على سطر منفصل:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1044_37" style="">
<span class="kwd">const</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> array</span><span class="pun">[]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3</span><span class="pun">,</span><span class="pln"> </span><span class="lit">4</span><span class="pun">,</span><span class="pln"> </span><span class="lit">5</span><span class="pun">};</span><span class="pln">
</span><span class="com">#ifdef</span><span class="pln"> BEFORE_CPP11

</span><span class="kwd">const</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">*</span><span class="pln">first </span><span class="pun">=</span><span class="pln"> array</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">const</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">*</span><span class="pln">afterLast </span><span class="pun">=</span><span class="pln"> first </span><span class="pun">+</span><span class="pln"> </span><span class="kwd">sizeof</span><span class="pun">(</span><span class="pln">array</span><span class="pun">)</span><span class="pln"> </span><span class="pun">/</span><span class="pln"> </span><span class="kwd">sizeof</span><span class="pun">(</span><span class="pln">array</span><span class="pun">[</span><span class="lit">0</span><span class="pun">]);</span><span class="pln">

</span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">*</span><span class="pln">i </span><span class="pun">=</span><span class="pln"> first</span><span class="pun">;</span><span class="pln"> i </span><span class="pun">&lt;</span><span class="pln"> afterLast</span><span class="pun">;</span><span class="pln"> </span><span class="pun">++</span><span class="pln">i</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
   std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="pun">*</span><span class="pln">i </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="com">#else</span><span class="pln">

</span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">auto</span><span class="pln"> i </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">begin</span><span class="pun">(</span><span class="pln">array</span><span class="pun">);</span><span class="pln"> i </span><span class="pun">!=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">end</span><span class="pun">(</span><span class="pln">array</span><span class="pun">);</span><span class="pln"> </span><span class="pun">++</span><span class="pln">i</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
   std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="pun">*</span><span class="pln">i </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="com">#endif</span></pre>

<p>
	الناتج:
</p>

<pre class="ipsCode">
1
2
3
4
5
</pre>

<h3>
	تحليل الشيفرة
</h3>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1044_39" style="">
<span class="kwd">const</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> array</span><span class="pun">[]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3</span><span class="pun">,</span><span class="pln"> </span><span class="lit">4</span><span class="pun">,</span><span class="pln"> </span><span class="lit">5</span><span class="pln"> </span><span class="pun">};</span></pre>

<p>
	ينشئ السطر السابق مصفوفة أعداد صحيحة (integer) فيها خمس قيَم، تذكر أن مصفوفات لغة C هي مجرد مؤشرات إلى مواضع في الذاكرة حيث تُخزَّن قيم المصفوفة بشكل متجاور.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1044_41" style="">
<span class="kwd">const</span><span class="pln"> </span><span class="typ">int</span><span class="pun">*</span><span class="pln"> first </span><span class="pun">=</span><span class="pln"> array</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">const</span><span class="pln"> </span><span class="typ">int</span><span class="pun">*</span><span class="pln"> afterLast </span><span class="pun">=</span><span class="pln"> first </span><span class="pun">+</span><span class="pln"> </span><span class="kwd">sizeof</span><span class="pun">(</span><span class="pln">array</span><span class="pun">)</span><span class="pln"> </span><span class="pun">/</span><span class="pln"> </span><span class="kwd">sizeof</span><span class="pun">(</span><span class="pln">array</span><span class="pun">[</span><span class="lit">0</span><span class="pun">]);</span></pre>

<p>
	هذان السّطران ينشئان مؤشّريْن اثنين، وقد أعطينا للمؤشر الأول قيمة مؤشّر المصفوفة <code>array</code> الذي يمثّل عنوان العنصر الأول فيها. ويعيد العامل <code>sizeof</code> حجم المصفوفة بالبايت عند استخدامه على مصفوفة في لغة C، وعندما نقسمه على حجم عنصر من المصفوفة سنحصل على عدد العناصر في المصفوفة، ومن ثم نستخدم ذلك لإيجاد عنوان الكتلة التالية للمصفوفة في الذاكرة.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1044_43" style="">
<span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> </span><span class="typ">int</span><span class="pun">*</span><span class="pln"> i </span><span class="pun">=</span><span class="pln"> first</span><span class="pun">;</span><span class="pln"> i </span><span class="pun">&lt;</span><span class="pln"> afterLast</span><span class="pun">;</span><span class="pln"> </span><span class="pun">++</span><span class="pln">i</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span></pre>

<p>
	في السّطر السابق أنشأنا مؤشرًا لاستخدامه كمكرّر، وقد هيّأناه عند عنوان العنصر الأول الذي نريد أن نبدأ التكرار منه، وسنستمر في التكرار ما دام <code>i</code> أصغر من <code>afterLast</code>، أي طالما يشير <code>i</code> إلى عنوانٍ داخل المصفوفة <code>array</code>.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1044_45" style="">
<span class="pln">std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="pun">*</span><span class="pln">i </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln"> </span></pre>

<p>
	أخيرًا، يمكننا الوصول إلى القيمة التي يشير إليها المُكرِّر <code>i</code> من خلال تحصيله، وذلك داخل الحلقة التكرارية. وهنا يعيد عاملُ التحصيل‏‏ <code>*</code> القيمةَ المخزّنة في العنوان <code>i</code>.
</p>

<h2>
	اكتب مُكرِّرك الخاص
</h2>

<p>
	يسود في لغات البرمجة الأخرى غير C++ أن توجد دالة تنتج تدفقًا (stream) من الكائنات مع استخدام حلقات تكرارية للمرور على عناصر ذلك التدفق، ويمكن تنفيذ ذلك في C++ أيضًا، انظر المثال التالي حيث نفصل عملية كتابة مكرر خاص بنا:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1044_47" style="">
<span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> T </span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">struct</span><span class="pln"> generator_iterator </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">using</span><span class="pln"> difference_type </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="typ">ptrdiff_t</span><span class="pun">;</span><span class="pln">
        </span><span class="kwd">using</span><span class="pln"> value_type </span><span class="pun">=</span><span class="pln"> T</span><span class="pun">;</span><span class="pln">
        </span><span class="kwd">using</span><span class="pln"> pointer </span><span class="pun">=</span><span class="pln"> T </span><span class="pun">*</span><span class="pln"> </span><span class="pun">;</span><span class="pln">
        </span><span class="kwd">using</span><span class="pln"> reference </span><span class="pun">=</span><span class="pln"> T</span><span class="pun">;</span><span class="pln">
        </span><span class="kwd">using</span><span class="pln"> iterator_category </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">input_iterator_tag</span><span class="pun">;</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">optional </span><span class="pun">&lt;</span><span class="pln"> T </span><span class="pun">&gt;</span><span class="pln"> state</span><span class="pun">;</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln"> function </span><span class="pun">&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">optional </span><span class="pun">&lt;</span><span class="pln"> T </span><span class="pun">&gt;</span><span class="pln"> </span><span class="pun">()</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> operation</span><span class="pun">;</span></pre>

<p>
	والآن سنخزن العنصر الحالي -إن كان موجودًا- في <code>state</code>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1044_49" style="">
<span class="pln">        T </span><span class="kwd">operator</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> </span><span class="pun">()</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">*</span><span class="pln">state</span><span class="pun">;</span><span class="pln">
        </span><span class="pun">}</span></pre>

<p>
	<br>
	نكمل الآن بأن نستدعي العملية، ونكون قد وصلنا للنهاية إن أعادت <code>nullopt</code>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1044_51" style="">
<span class="pln">        generator_iterator </span><span class="pun">&amp;</span><span class="pln"> </span><span class="kwd">operator</span><span class="pun">++()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
            state </span><span class="pun">=</span><span class="pln"> operation</span><span class="pun">();</span><span class="pln">
            </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">*</span><span class="kwd">this</span><span class="pun">;</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
        generator_iterator </span><span class="kwd">operator</span><span class="pun">++(</span><span class="typ">int</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">auto</span><span class="pln"> r </span><span class="pun">=</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> </span><span class="kwd">this</span><span class="pun">;</span><span class="pln">
            </span><span class="pun">++(</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> </span><span class="kwd">this</span><span class="pun">);</span><span class="pln">
            </span><span class="kwd">return</span><span class="pln"> r</span><span class="pun">;</span><span class="pln">
        </span><span class="pun">}</span></pre>

<p>
	لا يتساوى مكرران مدعومان بالمولِّدات (Generator Iterators) إلا إن كانا في حالة <code>end</code>.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1044_53" style="">
<span class="pln">        </span><span class="kwd">friend</span><span class="pln"> </span><span class="kwd">bool</span><span class="pln"> </span><span class="kwd">operator</span><span class="pln"> </span><span class="pun">==</span><span class="pln"> </span><span class="pun">(</span><span class="pln">generator_iterator
            </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> lhs</span><span class="pun">,</span><span class="pln"> generator_iterator
            </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> rhs</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(!</span><span class="pln">lhs</span><span class="pun">.</span><span class="pln">state </span><span class="pun">&amp;&amp;</span><span class="pln"> </span><span class="pun">!</span><span class="pln">rhs</span><span class="pun">.</span><span class="pln">state</span><span class="pun">)</span><span class="pln"> </span><span class="kwd">return</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">;</span><span class="pln">
            </span><span class="kwd">return</span><span class="pln"> </span><span class="kwd">false</span><span class="pun">;</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
        </span><span class="kwd">friend</span><span class="pln"> </span><span class="kwd">bool</span><span class="pln"> </span><span class="kwd">operator</span><span class="pln"> </span><span class="pun">!=</span><span class="pln"> </span><span class="pun">(</span><span class="pln">generator_iterator
            </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> lhs</span><span class="pun">,</span><span class="pln"> generator_iterator
            </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> rhs</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
            </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">!(</span><span class="pln">lhs </span><span class="pun">==</span><span class="pln"> rhs</span><span class="pun">);</span><span class="pln">
        </span><span class="pun">}</span></pre>

<p>
	سننشئ دالة بشكل مباشر من <code>std::function</code> مع إعطائها البصمة المناسبة.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1044_55" style="">
<span class="pln">generator_iterator</span><span class="pun">(</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">function</span><span class="pun">&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">optional</span><span class="pun">()</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> f </span><span class="pun">):</span><span class="pln">operation</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">move</span><span class="pun">(</span><span class="pln">f</span><span class="pun">))</span><span class="pln"> 
</span><span class="pun">{</span><span class="pln"> 
</span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">operation</span><span class="pun">)</span><span class="pln">
                state </span><span class="pun">=</span><span class="pln"> operation</span><span class="pun">();</span><span class="pln">
</span><span class="pun">}</span><span class="pln"> </span></pre>

<p>
	نهيئ كل دوال التوابع الخاصة إلى القيمة <code>default</code>.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1044_57" style="">
<span class="pln"> generator_iterator</span><span class="pun">(</span><span class="pln"> generator_iterator </span><span class="pun">&amp;&amp;</span><span class="pln"> </span><span class="pun">)</span><span class="pln"> </span><span class="pun">=</span><span class="kwd">default</span><span class="pun">;</span><span class="pln">
 generator_iterator</span><span class="pun">(</span><span class="pln"> generator_iterator </span><span class="kwd">const</span><span class="pun">&amp;</span><span class="pln"> </span><span class="pun">)</span><span class="pln"> </span><span class="pun">=</span><span class="kwd">default</span><span class="pun">;</span><span class="pln">
 generator_iterator</span><span class="pun">&amp;</span><span class="pln"> </span><span class="kwd">operator</span><span class="pun">=(</span><span class="pln"> generator_iterator </span><span class="pun">&amp;&amp;</span><span class="pln"> </span><span class="pun">)</span><span class="pln"> </span><span class="pun">=</span><span class="kwd">default</span><span class="pun">;</span><span class="pln">
 generator_iterator</span><span class="pun">&amp;</span><span class="pln"> </span><span class="kwd">operator</span><span class="pun">=(</span><span class="pln"> generator_iterator </span><span class="kwd">const</span><span class="pun">&amp;</span><span class="pln"> </span><span class="pun">)</span><span class="pln"> </span><span class="pun">=</span><span class="kwd">default</span><span class="pun">;</span><span class="pln">
 generator_iterator</span><span class="pun">()</span><span class="pln"> </span><span class="pun">=</span><span class="kwd">default</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span></pre>

<p>
	<a data-ss1617022345="1" href="coliru.stacked-crooked.com/a/cbb93f9ff193cdba" rel="">يمكنك مشاهدة هذا المثال الحيّ</a>. كذلك فإننا سنخزّن العنصر المُنشأ مبكرًا لمعرفة إن كنا وصلنا للنهاية أم لا، ونظرًا لعدم استخدام الدالة الخاصّة بمكرر المولِّد النهائي (end generator iterator)، فنستطيع إنشاء مجموعة من مكررات المولدات عن طريق نسخ <code>std::function</code> مرة واحدة فقط، ويكون مكرر المولد المنشأ افتراضيًا مساويًا لنفسه ولجميع مكررات المولدات النهائية.
</p>

<p>
	هذا الدرس جزء من <a data-ss1617022345="1" href="https://academy.hsoub.com/tags/%D8%B3%D9%84%D8%B3%D9%84%D8%A9%20++c%20%D9%84%D9%84%D9%85%D8%AD%D8%AA%D8%B1%D9%81%D9%8A%D9%86/" rel="">سلسلة مقالات عن C++‎</a>.
</p>

<p>
	ترجمة -بتصرّف- للفصل Chapter 9: Iterators من كتاب <a data-ss1617022345="1" href="https://goalkickercom/CPlusPlusBook/CPlusPlusNotesForProfessionals.pdf" rel="external nofollow">C++ Notes for Professionals</a>
</p>
]]></description><guid isPermaLink="false">892</guid><pubDate>Wed, 10 Jun 2020 18:02:00 +0000</pubDate></item><item><title>&#x627;&#x644;&#x645;&#x635;&#x641;&#x648;&#x641;&#x627;&#x62A; &#x641;&#x64A; Cpp</title><link>https://academy.hsoub.com/programming/cpp/%D8%A7%D9%84%D9%85%D8%B5%D9%81%D9%88%D9%81%D8%A7%D8%AA-%D9%81%D9%8A-cpp-r891/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2020_06/7.png.369ec2697b4d08b087b97726fada9387.png" /></p>

<p>
	المصفوفة (Array) هي مجموعة من عناصر تنتمي إلى نفس النوع، وموضوعة في أماكن متجاورة في الذاكرة، ويمكن الرجوع إلى كل عنصر من عناصر المصفوفة على حدة عبر مُعرِّف فريد يُسمَّى الفهرس. ويسمح ذلك بالتصريح عن قيم متعددة لمتغير ما ومن ثم الوصول إلى كل واحدة منها بشكل منفرد دون الحاجة إلى التصريح عن متغير لكل قيمة.
</p>

<h2>
	تهيئة المصفوفة
</h2>

<p>
	المصفوفة هي كتلة مكوّنة من مواقع متسلسلة في الذاكرة والمخصصة لنوع معيّن من المتغيرات. تخصيص المصفوفات يشبه تخصيص المتغيرات العادية، ولكن مع إضافة قوسين مربّعين إلى اسمها <code>[]</code> يحتويان على عدد يمثل عدد العناصر التي يمكن أن تحتويها ذاكرة المصفوفة.
</p>

<p>
	يستخدم المثال التالي مصفوفة تستخدم نوع <code>int</code>، واسم المتغير <code>arrayOfInts</code>، وعدد عناصرها هو <code>[ 5 ]</code>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5805_6" style="">
<span class="typ">int</span><span class="pln"> arrayOfInts</span><span class="pun">[</span><span class="lit">5</span><span class="pun">];</span></pre>

<p>
	يمكن التصريح عن المصفوفة وتهيئتها في نفس الوقت على النحو التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5805_8" style="">
<span class="typ">int</span><span class="pln"> arrayOfInts</span><span class="pun">[</span><span class="lit">5</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="lit">10</span><span class="pun">,</span><span class="pln"> </span><span class="lit">20</span><span class="pun">,</span><span class="pln"> </span><span class="lit">30</span><span class="pun">,</span><span class="pln"> </span><span class="lit">40</span><span class="pun">,</span><span class="pln"> </span><span class="lit">50</span><span class="pun">};</span></pre>

<p>
	إذا هيّأت مصفوفة بسرد جميع عناصرها فلا يلزمك تضمين عدد عناصر المصفوفة داخل القوسين المعقوفين، إذ سيحسُبه المُصرّف تلقائيًا. في المثال التالي، تعداد المصفوفة هو 5:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5805_10" style="">
<span class="typ">int</span><span class="pln"> arrayOfInts</span><span class="pun">[]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="lit">10</span><span class="pun">,</span><span class="pln"> </span><span class="lit">20</span><span class="pun">,</span><span class="pln"> </span><span class="lit">30</span><span class="pun">,</span><span class="pln"> </span><span class="lit">40</span><span class="pun">,</span><span class="pln"> </span><span class="lit">50</span><span class="pun">};</span></pre>

<p>
	كذلك نستطيع تهيئة العناصر الأولى فقط، مع تخصيص مساحة للمزيد من العناصر، وفي هذه الحالة يلزمك كتابة طول المصفوفة بين القوسين المعقوفين. انظر الشيفرة التالية حيث نخصص مصفوفةً خماسية (تحتوي 5 عناصر) مع تهيئتها جزئيًّا، سيُهيّئ المصرّف بقية العناصر بالقيمة الافتراضية لنوع العنصر (في هذه الحالة، تلك القيمة هي 0).
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5805_12" style="">
<span class="typ">int</span><span class="pln"> arrayOfInts</span><span class="pun">[</span><span class="lit">5</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="lit">10</span><span class="pun">,</span><span class="lit">20</span><span class="pun">};</span><span class="pln">    </span></pre>

<p>
	أي أن عناصر المصفوفة السابقة هي (10, 20, 0, 0, 0). كذلك يمكن تهيئة مصفوفات أنواع البيانات الأساسية الأخرى بالطريقة نفسها. انظر المثال التالي للتصريح عن مصفوفة وتخصيص مساحة ذاكرة لها دون تهيئتها:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5805_16" style="">
<span class="kwd">char</span><span class="pln"> arrayOfChars</span><span class="pun">[</span><span class="lit">5</span><span class="pun">];</span></pre>

<p>
	أو للتصريح عنها مع تهيئتها:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5805_18" style="">
<span class="kwd">char</span><span class="pln"> arrayOfChars</span><span class="pun">[</span><span class="lit">5</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="str">'a'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'b'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'c'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'d'</span><span class="pun">,</span><span class="pln"> </span><span class="str">'e'</span><span class="pln"> </span><span class="pun">}</span><span class="pln"> </span><span class="pun">;</span><span class="pln"> 
</span><span class="kwd">double</span><span class="pln"> arrayOfDoubles</span><span class="pun">[</span><span class="lit">5</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="lit">1.14159</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2.14159</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3.14159</span><span class="pun">,</span><span class="pln"> </span><span class="lit">4.14159</span><span class="pun">,</span><span class="pln"> </span><span class="lit">5.14159</span><span class="pun">};</span><span class="pln">
string arrayOfStrings</span><span class="pun">[</span><span class="lit">5</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="str">"C++"</span><span class="pun">,</span><span class="pln"> </span><span class="str">"is"</span><span class="pun">,</span><span class="pln"> </span><span class="str">"super"</span><span class="pun">,</span><span class="pln"> </span><span class="str">"duper"</span><span class="pun">,</span><span class="pln"> </span><span class="str">"great!"</span><span class="pun">};</span></pre>

<p>
	<strong>لاحظ</strong> أنه عند الوصول إلى عناصر المصفوفة فإن فهرس المصفوفة (أو موضعها) يبدأ عند القيمة 0. انظر المثال التالي، حيث يكون العنصر 10 هو العنصر رقم 0، و20 هو العنصر رقم 1، وهكذا.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5805_20" style="">
<span class="typ">int</span><span class="pln"> array</span><span class="pun">[</span><span class="lit">5</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="lit">10</span><span class="pun">,</span><span class="pln"> </span><span class="lit">20</span><span class="pun">,</span><span class="pln"> </span><span class="lit">30</span><span class="pun">,</span><span class="pln"> </span><span class="lit">40</span><span class="pun">,</span><span class="pln"> </span><span class="lit">50</span><span class="pun">};</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> array</span><span class="pun">[</span><span class="lit">4</span><span class="pun">];</span><span class="pln"> </span><span class="com">// 50</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> array</span><span class="pun">[</span><span class="lit">0</span><span class="pun">];</span><span class="pln"> </span><span class="com">// 10</span></pre>

<h2>
	المصفوفات متعددة الأبعاد ذات الحجم الثابت
</h2>

<p>
	يشير الفهرس <code>m[y]</code>‎ في المثال أدناه إلى الصف رقم <code>y</code>من المصفوفة <code>m</code>، حيث <code>y</code> مؤشرٌ يبدأ من الصفر، ويمكن فهرسة هذا الصف على النحو التالي <code>my</code> ‎ والذي يشير إلى العنصر/العمود <code>x</code> من الصف <code>y</code>، وذلك يعني أن الفهرس الأخير هو الأسرع تغيرًا، ونطاقه في التصريح -حيث النطاق هنا هو رقم الأعمدة لكل صف- هو آخر و"أعمق" حجم محدَّد.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5805_22" style="">
<span class="com">#include</span><span class="pln"> </span><span class="str">&lt;iostream&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;iomanip&gt;</span><span class="pln">
</span><span class="kwd">using</span><span class="pln"> </span><span class="kwd">namespace</span><span class="pln"> std</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">auto</span><span class="pln"> main</span><span class="pun">()</span><span class="pln"> </span><span class="pun">-&gt;</span><span class="pln"> </span><span class="typ">int</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> n_rows </span><span class="pun">=</span><span class="pln"> </span><span class="lit">3</span><span class="pun">;</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> n_cols </span><span class="pun">=</span><span class="pln"> </span><span class="lit">7</span><span class="pun">;</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> m</span><span class="pun">[</span><span class="pln">n_rows</span><span class="pun">][</span><span class="pln">n_cols</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> 
    </span><span class="pun">{</span><span class="pln">
        </span><span class="pun">{</span><span class="pln"> </span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3</span><span class="pun">,</span><span class="pln"> </span><span class="lit">4</span><span class="pun">,</span><span class="pln"> </span><span class="lit">5</span><span class="pun">,</span><span class="pln"> </span><span class="lit">6</span><span class="pun">,</span><span class="pln"> </span><span class="lit">7</span><span class="pln"> </span><span class="pun">},</span><span class="pln">
        </span><span class="pun">{</span><span class="pln"> </span><span class="lit">8</span><span class="pun">,</span><span class="pln"> </span><span class="lit">9</span><span class="pun">,</span><span class="pln"> </span><span class="lit">10</span><span class="pun">,</span><span class="pln"> </span><span class="lit">11</span><span class="pun">,</span><span class="pln"> </span><span class="lit">12</span><span class="pun">,</span><span class="pln"> </span><span class="lit">13</span><span class="pun">,</span><span class="pln"> </span><span class="lit">14</span><span class="pln"> </span><span class="pun">},</span><span class="pln">
        </span><span class="pun">{</span><span class="pln"> </span><span class="lit">15</span><span class="pun">,</span><span class="pln"> </span><span class="lit">16</span><span class="pun">,</span><span class="pln"> </span><span class="lit">17</span><span class="pun">,</span><span class="pln"> </span><span class="lit">18</span><span class="pun">,</span><span class="pln"> </span><span class="lit">19</span><span class="pun">,</span><span class="pln"> </span><span class="lit">20</span><span class="pun">,</span><span class="pln"> </span><span class="lit">21</span><span class="pln"> </span><span class="pun">},</span><span class="pln">
    </span><span class="pun">};</span><span class="pln">

    </span><span class="kwd">for</span><span class="pun">(</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> y </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln"> y </span><span class="pun">&lt;</span><span class="pln"> n_rows</span><span class="pun">;</span><span class="pln"> </span><span class="pun">++</span><span class="pln">y </span><span class="pun">)</span><span class="pln">
    </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">for</span><span class="pun">(</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> x </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln"> x </span><span class="pun">&lt;</span><span class="pln"> n_cols</span><span class="pun">;</span><span class="pln"> </span><span class="pun">++</span><span class="pln">x </span><span class="pun">)</span><span class="pln">
        </span><span class="pun">{</span><span class="pln">
 </span><span class="com">// m[y,x] لا تستخدم</span><span class="pln">
            cout </span><span class="pun">&lt;&lt;</span><span class="pln"> setw</span><span class="pun">(</span><span class="pln"> </span><span class="lit">4</span><span class="pln"> </span><span class="pun">)</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> m</span><span class="pun">[</span><span class="pln">y</span><span class="pun">][</span><span class="pln">x</span><span class="pun">];</span><span class="pln">
        </span><span class="pun">}</span><span class="pln">
        cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">'\n'</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	يكون الناتج:
</p>

<pre class="ipsCode">
 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 
</pre>

<p>
	لا تدعم C++‎ صياغة خاصة لفهرسة المصفوفة متعددة الأبعاد، وإنما تتعامل معها على أنها مصفوفة مكونة من مصفوفات أخرى داخلها، وتستخدم الفهرسة العادية لكل مستوى.
</p>

<p>
	وبما أن C++‎ لا توفر دعمًا بشكل افتراضي للمصفوفات ذات الحجم المتغير أو المصفوفات الديناميكية (Dynamic Size Arrays) ما عدا التخصيص الديناميكي (Dynamic Allocation)، فإن المصفوفة الديناميكية تُستخدم غالبًا كصنف (Class).
</p>

<p>
	لكن هناك بعض التعقيدات المرتبطة بصياغة الفهرسة <code>m[y][x]‎</code>، إما بكشف الاستخدام ليستحيل عرض منقول المصفوفة مثلًا (Transposed Matrix) أو بإضافة حمل زائد على البرنامج عند تنفيذه بإعادة كائن وكيل (Proxy Object) من عامل الفهرسة <code>operator[OD1][]‎</code>، وعليه قد تكون صياغة الفهرسة مختلفة سواء في الشكل أو في ترتيب الفهارس، كما هو الحال في <code>m(x,y)‎</code> أو <code>m.at(x,y)‎</code> أو <code>m.item(x,y)‎</code>.
</p>

<h2>
	المصفوفات الديناميكية (Dynamically sized raw array)
</h2>

<p>
	انظر المثال التالي كمثال على مصفوفة ديناميكية، واعلم أن الأفضل عمومًا هو استخدام <code>std::vector</code>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5805_24" style="">
<span class="com">#include</span><span class="pln"> </span><span class="str">&lt;algorithm&gt;</span><span class="pln">            </span><span class="com">// std::sort</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;iostream&gt;</span><span class="pln">
</span><span class="kwd">using</span><span class="pln"> </span><span class="kwd">namespace</span><span class="pln"> std</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">auto</span><span class="pln"> int_from</span><span class="pun">(</span><span class="pln"> istream</span><span class="pun">&amp;</span><span class="pln"> in </span><span class="pun">)</span><span class="pln"> </span><span class="pun">-&gt;</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> x</span><span class="pun">;</span><span class="pln"> in </span><span class="pun">&gt;&gt;</span><span class="pln"> x</span><span class="pun">;</span><span class="pln"> </span><span class="kwd">return</span><span class="pln"> x</span><span class="pun">;</span><span class="pln"> </span><span class="pun">}</span><span class="pln">
</span><span class="kwd">auto</span><span class="pln"> main</span><span class="pun">()</span><span class="pln">
       </span><span class="pun">-&gt;</span><span class="pln"> </span><span class="typ">int</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"Sorting n integers provided by you.\\n"</span><span class="pun">;</span><span class="pln">
cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"n? "</span><span class="pun">;</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> n </span><span class="pun">=</span><span class="pln"> int_from</span><span class="pun">(</span><span class="pln"> cin </span><span class="pun">);</span><span class="pln">
</span><span class="com">// n تخصيص مصفوفة عدد عناصرها </span><span class="pln">
</span><span class="typ">int</span><span class="pun">*</span><span class="pln"> a </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">int</span><span class="pun">[</span><span class="pln">n</span><span class="pun">];</span><span class="pln">

     </span><span class="kwd">for</span><span class="pun">(</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">1</span><span class="pun">;</span><span class="pln"> i </span><span class="pun">&lt;=</span><span class="pln"> n</span><span class="pun">;</span><span class="pln"> </span><span class="pun">++</span><span class="pln">i </span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"The #"</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> i </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">" number, please: "</span><span class="pun">;</span><span class="pln">
a</span><span class="pun">[</span><span class="pln">i</span><span class="pun">-</span><span class="lit">1</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> int_from</span><span class="pun">(</span><span class="pln"> cin </span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
sort</span><span class="pun">(</span><span class="pln"> a</span><span class="pun">,</span><span class="pln"> a </span><span class="pun">+</span><span class="pln"> n </span><span class="pun">);</span><span class="pln">
</span><span class="kwd">for</span><span class="pun">(</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln"> i </span><span class="pun">&lt;</span><span class="pln"> n</span><span class="pun">;</span><span class="pln"> </span><span class="pun">++</span><span class="pln">i </span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> cout </span><span class="pun">&lt;&lt;</span><span class="pln"> a</span><span class="pun">[</span><span class="pln">i</span><span class="pun">]</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">' '</span><span class="pun">;</span><span class="pln"> </span><span class="pun">}</span><span class="pln">
cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">'\\n'</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">delete</span><span class="pun">[]</span><span class="pln"> a</span><span class="pun">;</span><span class="pln">    
</span><span class="pun">}</span></pre>

<p>
	في بعض المُصرِّفات التي تدعم المصفوفات ذات الطول المتغير وفق معيار C99 ‏(variadic length arrays أو VLAs) كإضافة للّغة، يمكن تصريف برنامج يعلن عن مصفوفة <code>T a[n];‎</code>، حيث لا تُحدَّد <code>n</code> حتى وقت التشغيل (run-time). لكنّ C++‎ القياسية لا تدعم تلك المصفوفات، لذا يمكن استخدام تعبير <code>new[]‎</code> لتخصيص مصفوفة ديناميكية بشكل يدوي، انظر المثال التالي حيث نخصص مصفوفة مكونة من n عنصر:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5805_26" style="">
<span class="typ">int</span><span class="pun">*</span><span class="pln">   a   </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">int</span><span class="pun">[</span><span class="pln">n</span><span class="pun">];</span><span class="pln"> </span></pre>

<p>
	تستطيع إلغاء تخصيص المصفوفة بعد استخدامها عبر <code>delete[]‎</code>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5805_28" style="">
<span class="kwd">delete</span><span class="pun">[]</span><span class="pln"> a</span><span class="pun">;</span></pre>

<p>
	قيم المصفوفة التي صرّحنا عنها أعلاه غير محددة، ولكن يمكن تهيئة عناصرها عند القيمة صفر عبر إضافة قوسين فارغين <code>()</code> هكذا: <code>new int[n]()‎</code>، وعمومًا فإنه لأي نوع من أنواع البيانات، يهيئ هذا التعبير قيمَ المصفوفة بالقيمة الافتراضية لذلك النوع.
</p>

<p>
	لن تكون هذه الشيفرة آمنة للتنفيذ كجزء من دالة في أسفل هرمية الاستدعاء، ذلك أنه قد يحدث تسريب للذاكرة في حالة وجود استثناء قبل تعبير <code>delete[]</code>‎‎، (أو بعد ‎<code>new[]</code>‎)، وحل ذلك يكون بأتمتة عملية التنظيف عبر استخدام المؤشر الذكي <code>std::unique_ptr</code>، رغم أن الأفضل هو استخدام متجه (<code>std::vector</code>) إذ تلك هي وظيفته الأساسية.
</p>

<h2>
	حجم المصفوفة
</h2>

<p>
	انظر المثال التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5805_30" style="">
<span class="com">#include</span><span class="pln">      </span><span class="com">// size_t, ptrdiff_t</span><span class="pln">
 </span><span class="com">//-----------------------------------:</span><span class="pln">
</span><span class="kwd">using</span><span class="pln"> </span><span class="typ">Size</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="typ">ptrdiff_t</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Item</span><span class="pun">,</span><span class="pln"> </span><span class="typ">size_t</span><span class="pln"> n </span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">constexpr</span><span class="pln"> </span><span class="kwd">auto</span><span class="pln"> n_items</span><span class="pun">(</span><span class="typ">Item</span><span class="pun">(</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> </span><span class="pun">)[</span><span class="pln">n</span><span class="pun">])</span><span class="pln"> noexcept 
    </span><span class="pun">-&gt;</span><span class="pln"> </span><span class="typ">Size</span><span class="pln"> 
   </span><span class="pun">{</span><span class="pln"> </span><span class="kwd">return</span><span class="pln"> n</span><span class="pun">;</span><span class="pln"> </span><span class="pun">}</span><span class="pln">
</span><span class="com">//----------------------------------- الاستخدام:</span><span class="pln">
</span><span class="com">#include</span><span class="pln">
</span><span class="kwd">using</span><span class="pln"> </span><span class="kwd">namespace</span><span class="pln"> std</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">auto</span><span class="pln"> main</span><span class="pun">()</span><span class="pln">
</span><span class="pun">-&gt;</span><span class="pln"> </span><span class="typ">int</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> a</span><span class="pun">[]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="lit">3</span><span class="pun">,</span><span class="pln"> </span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">4</span><span class="pun">,</span><span class="pln"> </span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">5</span><span class="pun">,</span><span class="pln"> </span><span class="lit">9</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">,</span><span class="pln"> </span><span class="lit">6</span><span class="pun">,</span><span class="pln"> </span><span class="lit">5</span><span class="pun">,</span><span class="pln"> </span><span class="lit">4</span><span class="pun">};</span><span class="pln">
</span><span class="typ">Size</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> n </span><span class="pun">=</span><span class="pln"> n_items</span><span class="pun">(</span><span class="pln"> a </span><span class="pun">);</span><span class="pln">
        </span><span class="typ">Size</span><span class="pln">
        </span><span class="kwd">const</span><span class="pln"> n </span><span class="pun">=</span><span class="pln"> n_items</span><span class="pun">(</span><span class="pln">a</span><span class="pun">);</span><span class="pln">
        </span><span class="typ">int</span><span class="pln"> b</span><span class="pun">[</span><span class="pln">n</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{};</span><span class="pln"> </span><span class="com">// a مصفوفة لها نفس حجم  </span><span class="pln">
        </span><span class="pun">(</span><span class="kwd">void</span><span class="pun">)</span><span class="pln"> b</span><span class="pun">;</span><span class="pln">
        cout </span><span class="pun">&lt;}</span></pre>

<p>
	يمكن الحصول على حجم المصفوفة في لغة C عبر: <code>sizeof(a)‎</code> أو <code>sizeof(a[0])‎</code>، في حال تمرير مؤشر كوسيط، لكن تكون النتيجة بشكل عام غير دقيقة. أما في C++11، يمكنك الحصول على حجم المصفوفة بالتعبير التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5805_32" style="">
<span class="pln">std</span><span class="pun">::</span><span class="pln">extent</span><span class="pun">&lt;</span><span class="kwd">decltype</span><span class="pun">(</span><span class="typ">MyArray</span><span class="pun">)&gt;::</span><span class="pln">value</span><span class="pun">;</span></pre>

<p>
	مثال:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5805_34" style="">
<span class="kwd">char</span><span class="pln"> </span><span class="typ">MyArray</span><span class="pun">[]</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="str">'X'</span><span class="pun">,</span><span class="str">'o'</span><span class="pun">,</span><span class="str">'c'</span><span class="pun">,</span><span class="str">'e'</span><span class="pln"> </span><span class="pun">};</span><span class="pln">
</span><span class="kwd">const</span><span class="pln"> </span><span class="kwd">auto</span><span class="pln"> n </span><span class="pun">=</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">extent</span><span class="pun">&lt;</span><span class="kwd">decltype</span><span class="pun">(</span><span class="typ">MyArray</span><span class="pun">)&gt;::</span><span class="pln">value</span><span class="pun">;</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> n </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"\n"</span><span class="pun">;</span><span class="pln"> </span><span class="com">// يطبع 4</span></pre>

<p>
	لم يكن في أي إصدار من C++‎ إلى الإصدار C++17 أي آلية أو مكتبة قياسية مضمَّنة فيها للحصول على أحجام المصفوفات، وإنما نحصل على ذلك بتمرير مرجع يشير للمصفوفة إلى قالب دالة (function template) كما هو موضح أعلاه.
</p>

<p>
	معامل حجم القالب (template size parameter) هو <code>size_t</code>، وهو غير متوافق مع النوع المؤشَّر (signed type) للقيمة المعادة من الدّالة <code>Size</code>، وذلك لأجل التوافق مع المُصرّف g++‎ الذي يصر أحيانًاعلى <code>size_t</code> من أجل مطابقة القوالب. كبديل عن ذلك، يمكن استخدام <code>std::size</code> في C++17 والإصدارات اللاحقة لها، إذ هو تابع مخصص للمصفوفات.
</p>

<h2>
	توسيع المصفوفات الديناميكية باستخدام المتجهات
</h2>

<p>
	انظر المثال التالي الذي يوضح استخدام متجه <code>std::vector</code> كمصفوفة ديناميكية قابلة للتوسع:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5805_36" style="">
<span class="com">#include</span><span class="pln"> </span><span class="str">&lt;algorithm&gt;</span><span class="pln">            </span><span class="com">// std::sort</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;iostream&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;vector&gt;</span><span class="pln">               </span><span class="com">// std::vector</span><span class="pln">
</span><span class="kwd">using</span><span class="pln"> </span><span class="kwd">namespace</span><span class="pln"> std</span><span class="pun">;</span><span class="pln">

</span><span class="typ">int</span><span class="pln"> int_from</span><span class="pun">(</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">istream</span><span class="pun">&amp;</span><span class="pln"> in </span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> x </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln"> in </span><span class="pun">&gt;&gt;</span><span class="pln"> x</span><span class="pun">;</span><span class="pln"> </span><span class="kwd">return</span><span class="pln"> x</span><span class="pun">;</span><span class="pln"> </span><span class="pun">}</span><span class="pln"> 
</span><span class="typ">int</span><span class="pln"> main</span><span class="pun">()</span><span class="pln"> 
</span><span class="pun">{</span><span class="pln">     cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"Sorting integers provided by you.\n"</span><span class="pun">;</span><span class="pln">
    cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"You can indicate EOF via F6 in Windows or Ctrl+D in Unix-land.\n"</span><span class="pun">;</span><span class="pln">
    </span><span class="typ">vector</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">&gt;</span><span class="pln"> a</span><span class="pun">;</span><span class="pln"> </span><span class="com">// ← الحجم يساوي 0 افتراضيا</span><span class="pln">
</span><span class="kwd">while</span><span class="pun">(</span><span class="pln"> cin </span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"One number, please, or indicate EOF: "</span><span class="pun">;</span><span class="pln">
        </span><span class="typ">int</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> x </span><span class="pun">=</span><span class="pln"> int_from</span><span class="pun">(</span><span class="pln"> cin </span><span class="pun">);</span><span class="pln">
        </span><span class="kwd">if</span><span class="pun">(</span><span class="pln"> </span><span class="pun">!</span><span class="pln">cin</span><span class="pun">.</span><span class="pln">fail</span><span class="pun">()</span><span class="pln"> </span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> a</span><span class="pun">.</span><span class="pln">push_back</span><span class="pun">(</span><span class="pln"> x </span><span class="pun">);</span><span class="pln"> </span><span class="pun">}</span><span class="pln">          </span><span class="com">// التوسيع بحسب الضرورة</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
    sort</span><span class="pun">(</span><span class="pln"> a</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">(),</span><span class="pln"> a</span><span class="pun">.</span><span class="pln">end</span><span class="pun">()</span><span class="pln"> </span><span class="pun">);</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> n </span><span class="pun">=</span><span class="pln"> a</span><span class="pun">.</span><span class="pln">size</span><span class="pun">();</span><span class="pln">
    </span><span class="kwd">for</span><span class="pun">(</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln"> i </span><span class="pun">&lt;</span><span class="pln"> n</span><span class="pun">;</span><span class="pln"> </span><span class="pun">++</span><span class="pln">i </span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> cout </span><span class="pun">&lt;&lt;</span><span class="pln"> a</span><span class="pun">[</span><span class="pln">i</span><span class="pun">]</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">' '</span><span class="pun">;</span><span class="pln"> </span><span class="pun">}</span><span class="pln">
    cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">'\n'</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	<code>std::vector</code> هو قالب صنف في المكتبة القياسية التي توفر مفهوم المصفوفة ذات الحجم المتغير (الديناميكية)، وتتكفل تلك المكتبة بإدارة الذاكرة، كما أنّ المخزن المؤقت (buﬀer) متصل (contiguous)، لذا يمكن تمرير مؤشر يشير إلى المخزن المؤقت (على سبيل المثال <code>‎&amp;v[0]‎</code> أو <code>v.data()‎</code>) إلى دوال الواجهة البرمجية (<abbr title="Application Programming Interface | واجهة برمجية">API</abbr>) التي تتطلّب مصفوفةً خام (raw array). يمكن توسيع المتجهة <code>vector</code> في وقت التشغيل عبر التابع <code>push_back</code> الذي يضيف عنصرًا إلى المصفوفة.
</p>

<p>
	يُحدَّد تعقيد سلسلة عمليات <code>push_back</code> عددها n، بما في ذلك عمليات النسخ والنقل المستخدمتين في توسيعات المتجهات، في المتوسط من خلال O(n)، ويُنفّذ ذلك داخليًا عبر مضاعفة حجم المخزن المؤقّت للمتجهة <code>vector</code> وسِعتها عند الحاجة إلى حجم أكبر.
</p>

<p>
	فمثلًا، إذا كان المخزن المؤقّت يبدأ بالحجم 1، ثم يتضاعف حجمه بشكل متكرر حسب الحاجة، فإنّه في مقابل n=17 عملية استدعاءً للتابع <code>push_back</code>، ستكون هناك 1 + 2 + 4 + 8 + 16 = 31 عملية نسخ، أي أقل من 2 × n = 34. لكن بشكل عام فلا يمكن أن يتجاوز مجموع هذا التسلسل القيمة 2 × n.
</p>

<p>
	مقارنةً بمثال المصفوفة الديناميكيّة، فإنّ هذه الشيفرة المستندة إلى المتجهات لا تتطلب من المستخدم أن يحدد (أو يعرف) عدد العناصر مقدّمًا، وإنما تُوسَّع المتجهة حسب الضرورة بدلًا من ذلك.
</p>

<h2>
	استخدام <code>std::vector</code> في المصفوفة الديناميكية للتخزين
</h2>

<p>
	بدءًا من الإصدار C++14 لم يعد هناك أي صنف (Class) مخصص للمصفوفات الديناميكية في المكتبة القياسية، وإنما ستجد مثل تلك الأصناف التي تدعم الحجم المتغير في بعض مكتبات الطرف الثالث، بما في ذلك مكتبة Boost Matrix (مكتبة فرعية داخل مكتبة Boost). وإن لم ترد الاعتماد على Boost أو أيّ مكتبة أخرى، فيمكنك كتابة المصفوفات متعددة الأبعاد الديناميكية في ++C على نحو ما في المثال التالي، حيث <code>vector</code> هي متجهة من النوع <code>std::vector</code>.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5805_38" style="">
<span class="typ">vector</span><span class="pun">&lt;</span><span class="typ">vector</span><span class="str">&lt;int&gt;</span><span class="pun">&gt;</span><span class="pln"> m</span><span class="pun">(</span><span class="pln"> </span><span class="lit">3</span><span class="pun">,</span><span class="pln"> </span><span class="typ">vector</span><span class="str">&lt;int&gt;</span><span class="pun">(</span><span class="pln"> </span><span class="lit">7</span><span class="pln"> </span><span class="pun">)</span><span class="pln"> </span><span class="pun">);</span></pre>

<p>
	تُنشأ المصفوفة هنا عن طريق نسخ متجه صفِّي (row vector) عددًا من المرات قدره n مرة، حيث n هو عدد الصفوف الذي يساوي 3 في مثالنا أعلاه. تمتاز تلك الطريقة بدعمها لصيغة الفهرسة <code>m[y][x]</code>‎ كما في المصفوفة متعددة الأبعاد ثابتة الحجم، لكنها غير فعّالة من جهة أخرى إذ تتطلّب تخصيص ذاكرة ديناميكيّ لكل صفّ، كما أنّها غير آمنة بسبب إمكانية تغيير حجم الصف عن غير عمد.
</p>

<p>
	وعلى أي حال توجد طريقة أخرى أفضل وهي استخدام متجه واحد كتخزين للمصفوفة، وتوجيه شيفرة العميل (x,y) إلى فهرس مناسب في ذلك المتجه. انظر المثال التالي لمصفوفة متغير الحجم (ديناميكية) تستخدم <code>std::vector</code> للتخزين:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5805_40" style="">
<span class="com">//--------------------------------------------- الألية:</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="com">// std::copy</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="com">// assert</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="com">// std::initializer_list</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="com">// std::vector</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="com">// ptrdiff_t</span><span class="pln">
</span><span class="kwd">namespace</span><span class="pln"> my
</span><span class="pun">{</span><span class="pln">
   </span><span class="kwd">using</span><span class="pln"> </span><span class="typ">Size</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="typ">ptrdiff_t</span><span class="pun">;</span><span class="pln">
   </span><span class="kwd">using</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">initializer_list</span><span class="pun">;</span><span class="pln">
   </span><span class="kwd">using</span><span class="pln"> std</span><span class="pun">::</span><span class="typ">vector</span><span class="pun">;</span><span class="pln">
   </span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Item</span><span class="pun">&gt;</span><span class="pln">
   </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">Matrix</span><span class="pln">
   </span><span class="pun">{</span><span class="pln">
   </span><span class="kwd">private</span><span class="pun">:</span><span class="pln">
       </span><span class="typ">vector</span><span class="pln"> items_</span><span class="pun">;</span><span class="pln">
       </span><span class="typ">Size</span><span class="pln"> n_cols_</span><span class="pun">;</span><span class="pln">
       </span><span class="kwd">auto</span><span class="pln"> index_for</span><span class="pun">(</span><span class="typ">Size</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> x</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Size</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> y</span><span class="pun">)</span><span class="pln"> </span><span class="kwd">const</span><span class="pln">
           </span><span class="pun">-&gt;</span><span class="pln"> </span><span class="typ">Size</span><span class="pln">
       </span><span class="pun">{</span><span class="pln">
           </span><span class="kwd">return</span><span class="pln"> y </span><span class="pun">*</span><span class="pln"> n_cols_ </span><span class="pun">+</span><span class="pln"> x</span><span class="pun">;</span><span class="pln">
       </span><span class="pun">}</span><span class="pln">

   </span><span class="kwd">public</span><span class="pun">:</span><span class="pln">
       </span><span class="kwd">auto</span><span class="pln"> n_rows</span><span class="pun">()</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">-&gt;</span><span class="pln"> </span><span class="typ">Size</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="kwd">return</span><span class="pln"> items_</span><span class="pun">.</span><span class="pln">size</span><span class="pun">()</span><span class="pln"> </span><span class="pun">/</span><span class="pln"> n_cols_</span><span class="pun">;</span><span class="pln"> </span><span class="pun">}</span><span class="pln">
       </span><span class="kwd">auto</span><span class="pln"> n_cols</span><span class="pun">()</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">-&gt;</span><span class="pln"> </span><span class="typ">Size</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="kwd">return</span><span class="pln"> n_cols_</span><span class="pun">;</span><span class="pln"> </span><span class="pun">}</span><span class="pln">
       </span><span class="kwd">auto</span><span class="pln"> item</span><span class="pun">(</span><span class="typ">Size</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> x</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Size</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> y</span><span class="pun">)</span><span class="pln">
           </span><span class="pun">-&gt;</span><span class="pln"> </span><span class="typ">Item</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">
       </span><span class="pun">{</span><span class="pln">
           </span><span class="kwd">return</span><span class="pln"> items_</span><span class="pun">[</span><span class="pln">index_for</span><span class="pun">(</span><span class="pln">x</span><span class="pun">,</span><span class="pln"> y</span><span class="pun">)];</span><span class="pln">
       </span><span class="pun">}</span><span class="pln">
       </span><span class="kwd">auto</span><span class="pln"> item</span><span class="pun">(</span><span class="typ">Size</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> x</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Size</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> y</span><span class="pun">)</span><span class="pln"> </span><span class="kwd">const</span><span class="pln">
           </span><span class="pun">-&gt;</span><span class="pln"> </span><span class="typ">Item</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">
       </span><span class="pun">{</span><span class="pln">
           </span><span class="kwd">return</span><span class="pln"> items_</span><span class="pun">[</span><span class="pln">index_for</span><span class="pun">(</span><span class="pln">x</span><span class="pun">,</span><span class="pln"> y</span><span class="pun">)];</span><span class="pln">
       </span><span class="pun">}</span><span class="pln">
       </span><span class="typ">Matrix</span><span class="pun">()</span><span class="pln"> </span><span class="pun">:</span><span class="pln"> n_cols_</span><span class="pun">(</span><span class="lit">0</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{}</span><span class="pln">
       </span><span class="typ">Matrix</span><span class="pun">(</span><span class="typ">Size</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> n_cols</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Size</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> n_rows</span><span class="pun">)</span><span class="pln">
           </span><span class="pun">:</span><span class="pln"> items_</span><span class="pun">(</span><span class="pln">n_cols </span><span class="pun">*</span><span class="pln"> n_rows</span><span class="pun">),</span><span class="pln"> n_cols_</span><span class="pun">(</span><span class="pln">n_cols</span><span class="pun">)</span><span class="pln">
       </span><span class="pun">{</span><span class="pln">
       </span><span class="pun">}</span><span class="pln">
       </span><span class="typ">Matrix</span><span class="pun">(</span><span class="pln">initializer_list</span><span class="str">&lt;initializer_list&gt;</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">values</span><span class="pun">)</span><span class="pln">
           </span><span class="pun">:</span><span class="pln"> items_</span><span class="pun">(),</span><span class="pln"> n_cols_</span><span class="pun">(</span><span class="pln">values</span><span class="pun">.</span><span class="pln">size</span><span class="pun">()</span><span class="pln"> </span><span class="pun">==</span><span class="pln"> </span><span class="lit">0</span><span class="pln"> </span><span class="pun">?</span><span class="pln"> </span><span class="lit">0</span><span class="pln"> </span><span class="pun">:</span><span class="pln"> values</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">()-&gt;</span><span class="pln">size</span><span class="pun">())</span><span class="pln">
       </span><span class="pun">{</span><span class="pln">
           </span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">auto</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">row </span><span class="pun">:</span><span class="pln"> values</span><span class="pun">)</span><span class="pln">
           </span><span class="pun">{</span><span class="pln">
               assert</span><span class="pun">(</span><span class="typ">Size</span><span class="pun">(</span><span class="pln">row</span><span class="pun">.</span><span class="pln">size</span><span class="pun">())</span><span class="pln"> </span><span class="pun">==</span><span class="pln"> n_cols_</span><span class="pun">);</span><span class="pln">
               items_</span><span class="pun">.</span><span class="pln">insert</span><span class="pun">(</span><span class="pln">items_</span><span class="pun">.</span><span class="pln">end</span><span class="pun">(),</span><span class="pln"> row</span><span class="pun">.</span><span class="pln">begin</span><span class="pun">(),</span><span class="pln"> row</span><span class="pun">.</span><span class="pln">end</span><span class="pun">());</span><span class="pln">
           </span><span class="pun">}</span><span class="pln">
       </span><span class="pun">}</span><span class="pln">
   </span><span class="pun">};</span><span class="pln">
</span><span class="pun">}</span><span class="pln"> </span><span class="com">// namespace my</span><span class="pln">
</span><span class="com">//--------------------------------------------- الاستخدام:</span><span class="pln">
</span><span class="kwd">using</span><span class="pln"> my</span><span class="pun">::</span><span class="typ">Matrix</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">auto</span><span class="pln"> some_matrix</span><span class="pun">()</span><span class="pln">
   </span><span class="pun">-&gt;</span><span class="pln"> </span><span class="typ">Matrix</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
   </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
       </span><span class="pun">{</span><span class="lit">1</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3</span><span class="pun">,</span><span class="pln"> </span><span class="lit">4</span><span class="pun">,</span><span class="pln"> </span><span class="lit">5</span><span class="pun">,</span><span class="pln"> </span><span class="lit">6</span><span class="pun">,</span><span class="pln"> </span><span class="lit">7</span><span class="pun">},</span><span class="pln">
       </span><span class="pun">{</span><span class="lit">8</span><span class="pun">,</span><span class="pln"> </span><span class="lit">9</span><span class="pun">,</span><span class="pln"> </span><span class="lit">10</span><span class="pun">,</span><span class="pln"> </span><span class="lit">11</span><span class="pun">,</span><span class="pln"> </span><span class="lit">12</span><span class="pun">,</span><span class="pln"> </span><span class="lit">13</span><span class="pun">,</span><span class="pln"> </span><span class="lit">14</span><span class="pun">},</span><span class="pln">
       </span><span class="pun">{</span><span class="lit">15</span><span class="pun">,</span><span class="pln"> </span><span class="lit">16</span><span class="pun">,</span><span class="pln"> </span><span class="lit">17</span><span class="pun">,</span><span class="pln"> </span><span class="lit">18</span><span class="pun">,</span><span class="pln"> </span><span class="lit">19</span><span class="pun">,</span><span class="pln"> </span><span class="lit">20</span><span class="pun">,</span><span class="pln"> </span><span class="lit">21</span><span class="pun">}};</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="com">#include</span><span class="pln">
</span><span class="com">#include</span><span class="pln">
</span><span class="kwd">using</span><span class="pln"> </span><span class="kwd">namespace</span><span class="pln"> std</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">auto</span><span class="pln"> main</span><span class="pun">()</span><span class="pln"> </span><span class="pun">-&gt;</span><span class="pln"> </span><span class="typ">int</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
   </span><span class="typ">Matrix</span><span class="pln"> </span><span class="kwd">const</span><span class="pln"> m </span><span class="pun">=</span><span class="pln"> some_matrix</span><span class="pun">();</span><span class="pln">
   assert</span><span class="pun">(</span><span class="pln">m</span><span class="pun">.</span><span class="pln">n_cols</span><span class="pun">()</span><span class="pln"> </span><span class="pun">==</span><span class="pln"> </span><span class="lit">7</span><span class="pun">);</span><span class="pln">
   assert</span><span class="pun">(</span><span class="pln">m</span><span class="pun">.</span><span class="pln">n_rows</span><span class="pun">()</span><span class="pln"> </span><span class="pun">==</span><span class="pln"> </span><span class="lit">3</span><span class="pun">);</span><span class="pln">
   </span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="typ">int</span><span class="pln"> y </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">,</span><span class="pln"> y_end </span><span class="pun">=</span><span class="pln"> m</span><span class="pun">.</span><span class="pln">n_rows</span><span class="pun">();</span><span class="pln"> y </span><span class="pun">&lt;</span><span class="pln"> y_end</span><span class="pun">;</span><span class="pln"> </span><span class="pun">++</span><span class="pln">y</span><span class="pun">)</span><span class="pln">
   </span><span class="pun">{</span><span class="pln">
       </span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="typ">int</span><span class="pln"> x </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">,</span><span class="pln"> x_end </span><span class="pun">=</span><span class="pln"> m</span><span class="pun">.</span><span class="pln">n_cols</span><span class="pun">();</span><span class="pln"> x </span><span class="pun">&lt;</span><span class="pln"> x_end</span><span class="pun">;</span><span class="pln"> </span><span class="pun">++</span><span class="pln">x</span><span class="pun">)</span><span class="pln">
       </span><span class="pun">{</span><span class="pln">
           cout </span><span class="pun">&lt;←</span><span class="pln"> </span><span class="typ">Note</span><span class="pln"> </span><span class="pun">:</span><span class="pln"> not </span><span class="pun">`</span><span class="pln">m</span><span class="pun">[</span><span class="pln">y</span><span class="pun">][</span><span class="pln">x</span><span class="pun">]`!</span><span class="pln">
       </span><span class="pun">}</span><span class="pln">
       cout </span><span class="pun">&lt;</span><span class="pln">
   </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	يكون الخرج:
</p>

<pre class="ipsCode">
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 
</pre>

<p>
	الشيفرة أعلاه ليست مناسبة لا توافق معايير بيئات الإنتاج في الشركات، وإنما صُممت لتوضيح المبادئ الأساسية وخدمة احتياجات الطلاب الذي يتعلمون C++‎، فمثلًا يمكن تحديد التحميل الزائد لـ <code>()operator</code> لتبسيط صيغة الفهرسة.
</p>

<p>
	هذا الدرس جزء من <a data-ss1617022342="1" href="https://academy.hsoub.com/tags/%D8%B3%D9%84%D8%B3%D9%84%D8%A9%20++c%20%D9%84%D9%84%D9%85%D8%AD%D8%AA%D8%B1%D9%81%D9%8A%D9%86/" rel="">سلسلة دروس عن C++‎</a>.
</p>

<p>
	ترجمة -بتصرّف- للفصل Chapter 8: Arrays من كتاب <a data-ss1617022342="1" href="https://goalkickercom/CPlusPlusBook/CPlusPlusNotesForProfessionals.pdf" rel="external nofollow">C++ Notes for Professionals</a><em> </em>
</p>
]]></description><guid isPermaLink="false">891</guid><pubDate>Fri, 05 Jun 2020 18:04:00 +0000</pubDate></item><item><title>&#x645;&#x639;&#x627;&#x644;&#x62C;&#x629; &#x627;&#x644;&#x628;&#x62A;&#x627;&#x62A; &#x648;&#x627;&#x644;&#x62A;&#x644;&#x627;&#x639;&#x628; &#x628;&#x647;&#x627; &#x641;&#x64A; ++C</title><link>https://academy.hsoub.com/programming/cpp/%D9%85%D8%B9%D8%A7%D9%84%D8%AC%D8%A9-%D8%A7%D9%84%D8%A8%D8%AA%D8%A7%D8%AA-%D9%88%D8%A7%D9%84%D8%AA%D9%84%D8%A7%D8%B9%D8%A8-%D8%A8%D9%87%D8%A7-%D9%81%D9%8A-c-r807/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2020_06/6.png.4d080908fa57dd0aea7807ebc7311a2e.png" /></p>

<h2>
	تصفير البت الأيمن (Rightmost set bit)
</h2>

<p>
	ملاحظة: المقصود بتصفير بت أي جعل قيمته 0، والمقصود بتعيين قيمة بت أي جعل قيمته 1.
</p>

<h3>
	معالجة البتات وفق أسلوب لغة C
</h3>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_679_6" style="">
<span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">typename</span><span class="pln"> T </span><span class="pun">&gt;</span><span class="pln">
    T rightmostSetBitRemoved</span><span class="pun">(</span><span class="pln">T n</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  
        </span><span class="com">// وما بعدها c++11 لأجل</span><span class="pln">
        </span><span class="com">// static_assert(std::is_integral&lt;T&gt;::value &amp;&amp; !std::is_signed&lt;T&gt;::value, "type should   //be unsigned"); </span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> n </span><span class="pun">&amp;</span><span class="pln"> </span><span class="pun">(</span><span class="pln">n </span><span class="pun">-</span><span class="pln"> </span><span class="lit">1</span><span class="pun">);</span><span class="pln">
    </span><span class="pun">}</span></pre>

<h3>
	تفسير المثال
</h3>

<ul>
<li>
		إذا كان <code>n</code> يساوي الصفر، فسنحصل على <code>‎0‎ &amp; 0xFF..FF</code> والتي تساوي صفرًا.
	</li>
	<li>
		وإن كان غير ذلك فيمكن كتابة <code>n</code> على الصورة <code>0bxxxxxx10..00</code>، ومن ثم سيُكتب <code>n - 1</code> على الصورة <code>0bxxxxxx011..11</code>. وهكذا، فإنّ <code>n &amp; (n - 1)‎</code> ستساوي <code>0bxxxxxx000..00</code>.
	</li>
</ul>
<h2>
	ضبط كل البتات إلى القيمة 1 (Set all bits)
</h2>

<h3>
	معالجة البتات وفق أسلوب لغة C
</h3>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8538_9" style="">
<span class="pln">x </span><span class="pun">=</span><span class="pln"> </span><span class="pun">-</span><span class="lit">1</span><span class="pun">;</span><span class="pln"> </span><span class="com">// -1 == 1111 1111 ... 1111b</span></pre>

<p>
	(انظر <a data-ss1617022337="1" href="https://stackoverflow.com/questions/809227/is-it-safe-to-use-1-to-set-all-bits-to-true/809341#809341" rel="external nofollow">هذه الصفحة الأجنبية</a> للمزيد من التفاصيل).
</p>

<h3>
	استخدام <code>std::bitset</code>
</h3>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8538_11" style="">
<span class="pln">std</span><span class="pun">::</span><span class="typ">bitset</span><span class="pun">&lt;</span><span class="lit">10</span><span class="pun">&gt;</span><span class="pln"> x</span><span class="pun">;</span><span class="pln">
x</span><span class="pun">.</span><span class="typ">set</span><span class="pun">();</span><span class="pln"> </span><span class="com">// إسناد القيمة 1 إلى كل البتات </span></pre>

<h2>
	تبديل قيمة بت
</h2>

<h3>
	معالجة البتات وفق أسلوب لغة C
</h3>

<p>
	يمكن تبديل قيمة البت باستخدام معامِل XOR الثنائي (<code>^</code>) .
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8538_13" style="">
<span class="com">// عكس قيمتها الحالية x ستصبح قيمة البت.</span><span class="pln">
number </span><span class="pun">^=</span><span class="pln"> </span><span class="lit">1LL</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> x</span><span class="pun">;</span></pre>

<h3>
	استخدام <code>std::bitset</code>
</h3>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8538_15" style="">
<span class="pln">std</span><span class="pun">::</span><span class="typ">bitset</span><span class="pun">&lt;</span><span class="lit">4</span><span class="pun">&gt;</span><span class="pln"> num</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">string</span><span class="pun">(</span><span class="str">"0100"</span><span class="pun">));</span><span class="pln">
num</span><span class="pun">.</span><span class="pln">flip</span><span class="pun">(</span><span class="lit">2</span><span class="pun">);</span><span class="pln"> </span><span class="com">// num = 0000</span><span class="pln">
num</span><span class="pun">.</span><span class="pln">flip</span><span class="pun">(</span><span class="lit">0</span><span class="pun">);</span><span class="pln"> </span><span class="com">// num = 0001</span><span class="pln">
num</span><span class="pun">.</span><span class="pln">flip</span><span class="pun">();</span><span class="pln"> </span><span class="com">// يبدل جميع البتّات ،num = 1110</span></pre>

<h2>
	التحقق من قيمة البت
</h2>

<h3>
	معالجة البتات وفق أسلوب لغة C
</h3>

<p>
	يمكن الحصول على قيمة بت معيّنة في التمثيل الثنائي لعدد ما عن طريق إزاحته إلى اليمين بمقدار <code>x</code> - إذ x تشير إلى عدد المرات-، ثم تنفيذ عملية AND الثنائية <code>&amp;</code> عليه:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6994_8" style="">
<span class="pun">(</span><span class="pln">number </span><span class="pun">&gt;&gt;</span><span class="pln"> x</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> </span><span class="lit">1LL</span><span class="pun">;</span><span class="pln"> 
</span><span class="com">// تساوي 1، وإلا فسَيساوي 0 x الناتج سيساوي 1 في حال كانت البت رقم</span></pre>

<p>
	يمكن تنفيذ عملية الإزاحة اليمينية (right-shift operation) إما كإزاحة حسابية مُؤشرَّة (arithmetic signed shift) أو كإزاحة منطقية غير مؤشرة (logical unsigned shift). إن كان <code>number</code> في التعبير <code>number &gt;&gt; x</code> ذا نوعٍ مُؤشَّر (signed type) وله قيمة سالبة، فإنّ القيمة الناتجة تحدد وفق التطبيق (implementation-defined).
</p>

<p>
	وإن أردنا الحصول على قيمة تلك البت مباشرة في موضعها فيمكننا إزاحة القناع لليسار:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6994_15" style="">
<span class="pun">(</span><span class="pln">number </span><span class="pun">&amp;</span><span class="pln"> </span><span class="pun">(</span><span class="lit">1LL</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> x</span><span class="pun">));</span><span class="pln"> </span></pre>

<p>
	 الناتج سيساوي ‎1<code> &gt;&gt; x</code>  في حال كان البت رقم 1 يساوي 1 وإلا فسيساوي الصفر. يمكننا استخدامهما كشرط لأنّ جميع القيم المخالفة للصفر تُعدُّ صحيحة.
</p>

<h3>
	استخدام <code>std::bitset</code>
</h3>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8538_21" style="">
<span class="pln">std</span><span class="pun">::</span><span class="typ">bitset</span><span class="pun">&lt;</span><span class="lit">4</span><span class="pun">&gt;</span><span class="pln"> num</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">string</span><span class="pun">(</span><span class="str">"0010"</span><span class="pun">));</span><span class="pln">
</span><span class="kwd">bool</span><span class="pln"> bit_val </span><span class="pun">=</span><span class="pln"> num</span><span class="pun">.</span><span class="pln">test</span><span class="pun">(</span><span class="lit">1</span><span class="pun">);</span><span class="pln"> </span><span class="com">// true تساوي bit_val قيمة</span></pre>

<h2>
	عدّ البتات ذات القيمة 1
</h2>

<p>
	تزيد الحاجة لعد البتات الموجودة في سلسلة بتية (Bitstring) في علم التشفير وغيره، وقد دُرست تلك المشكلة على نطاق واسع، والطريقة البسيطة لعدها هي المرور على البتات فرادى:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6994_20" style="">
<span class="com">// n مراكمة العدد الإجمالي للوحدات في التمثيل الثنائي للعدد</span><span class="pln">
</span><span class="kwd">unsigned</span><span class="pln"> value </span><span class="pun">=</span><span class="pln"> </span><span class="lit">1234</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">unsigned</span><span class="pln"> bits </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln"> 

</span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="pln">bits </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln"> value</span><span class="pun">;</span><span class="pln"> value </span><span class="pun">&gt;&gt;=</span><span class="pln"> </span><span class="lit">1</span><span class="pun">)</span><span class="pln">
bits </span><span class="pun">+=</span><span class="pln"> value </span><span class="pun">&amp;</span><span class="pln"> </span><span class="lit">1</span><span class="pun">;</span></pre>

<p>
	بيْد أنّ هذه الطريقة أفضل (تعتمد على إزالة البت الأيمن ذا القيمة 1):
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6994_22" style="">
<span class="com">// n تراكم إجمالي عدد البتّات في التمثيل الثنائي للعدد</span><span class="pln">
</span><span class="kwd">unsigned</span><span class="pln"> bits </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(;</span><span class="pln"> value</span><span class="pun">;</span><span class="pln"> </span><span class="pun">++</span><span class="pln">bits</span><span class="pun">)</span><span class="pln">
   value </span><span class="pun">&amp;=</span><span class="pln"> value </span><span class="pun">-</span><span class="pln"> </span><span class="lit">1</span><span class="pun">;</span></pre>

<p>
	تُنفِّذ الشيفرة أعلاه عددًا من التكرارات يكافئ عدد البتات التي تأخذ القيمة 1، لذا فهي مناسبة إن كان في <code>value</code> عدد قليل من البتات غير الصفرية (non-zero bits).
</p>

<p>
	تم اقتراح هذه الطريقة للمرة الأولى من طرف بيتر فيجنيور (Peter Wegner) في عام <a data-ss1617022337="1" href="https://cacm.acm.org/" rel="external nofollow">CACM</a> 3/322 - 1960، وقد لقيت قبولًا وتبنيًا كثيرًا منذ ظهورها في كتاب لغة البرمجة C الذي كتبه برايان كرنيجن ودينيس ريتشي. وتتطلب تلك الطريقة 12 عملية حسابية، إحداها عملية متعددة:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6994_24" style="">
<span class="kwd">unsigned</span><span class="pln"> popcount</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="typ">uint64_t</span><span class="pln"> x</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">const</span><span class="pln"> std</span><span class="pun">::</span><span class="typ">uint64_t</span><span class="pln"> m1 </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0x5555555555555555</span><span class="pun">;</span><span class="pln"> </span><span class="com">// binary: 0101...</span><span class="pln">
    </span><span class="kwd">const</span><span class="pln"> std</span><span class="pun">::</span><span class="typ">uint64_t</span><span class="pln"> m2 </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0x3333333333333333</span><span class="pun">;</span><span class="pln"> </span><span class="com">// binary: 00110011..</span><span class="pln">
    </span><span class="kwd">const</span><span class="pln"> std</span><span class="pun">::</span><span class="typ">uint64_t</span><span class="pln"> m4 </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0x0f0f0f0f0f0f0f0f</span><span class="pun">;</span><span class="pln"> </span><span class="com">// binary: 0000111100001111</span><span class="pln">
  	
  	</span><span class="com">// وضع تعداد كل بتّيْن في هاتين البتّيْن</span><span class="pln">
    x </span><span class="pun">-=</span><span class="pln"> </span><span class="pun">(</span><span class="pln">x </span><span class="pun">&gt;&gt;</span><span class="pln"> </span><span class="lit">1</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> m1</span><span class="pun">;</span><span class="pln">
  
  	</span><span class="com">// وضع تعداد كل 4 بتات في تلك البتات الأربعة</span><span class="pln">
    x </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="pln">x </span><span class="pun">&amp;</span><span class="pln"> m2</span><span class="pun">)</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="pun">((</span><span class="pln">x </span><span class="pun">&gt;&gt;</span><span class="pln"> </span><span class="lit">2</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> m2</span><span class="pun">);</span><span class="pln">
  
  	</span><span class="com">//  وضع تعداد كل 8 بتات في تلك البتات الثمانية</span><span class="pln">
    x </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="pln">x </span><span class="pun">+</span><span class="pln"> </span><span class="pun">(</span><span class="pln">x </span><span class="pun">&gt;&gt;</span><span class="pln"> </span><span class="lit">4</span><span class="pun">))</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> m4</span><span class="pun">;</span><span class="pln">
  
  	</span><span class="com">// ... + (x&lt;&lt;24) + (x&lt;&lt;16) + (x&lt;&lt;8) + x البتات الثمانية على يسار</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">(</span><span class="pln">x </span><span class="pun">*</span><span class="pln"> h01</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&gt;&gt;</span><span class="pln"> </span><span class="lit">56</span><span class="pun">;</span><span class="pln"> 
</span><span class="pun">}</span></pre>

<p>
	هذا النوع من التطبيق لديه أفضل سلوك للحالة الأسوأ (Worst-Case) انظر <a data-ss1617022337="1" href="https://en.wikipedia.org/wiki/Hamming_weight" rel="external nofollow">Hamming weight</a> لمزيد من التفاصيل. يحتوي العديد من وحدات المعالجة المركزية CPUs على تعليمات محددة (مثل <code>popcnt</code> في x86)، ويمكن للمصرّف إنشاء دالة مخصصة (غير قياسية) مضمنة، فمثلًا في مصرّف ++g نجد التعليمة التالية‎:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8538_29" style="">
<span class="typ">int</span><span class="pln"> __builtin_popcount </span><span class="pun">(</span><span class="kwd">unsigned</span><span class="pln"> x</span><span class="pun">);</span></pre>

<h2>
	التحقق مما إذا كان عدد صحيح ما هو أس للعدد 2
</h2>

<p>
	تُعد طريقة <code>n &amp; (n - 1)‎</code> المُستعملة في مقالة إزالة بت التعيين اليمنى مفيدة لتحديد ما إذا كان عدد صحيح هو أس للرقم 2:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8538_31" style="">
<span class="kwd">bool</span><span class="pln"> power_of_2 </span><span class="pun">=</span><span class="pln"> n </span><span class="pun">&amp;&amp;</span><span class="pln"> </span><span class="pun">!(</span><span class="pln">n </span><span class="pun">&amp;</span><span class="pln"> </span><span class="pun">(</span><span class="pln">n </span><span class="pun">-</span><span class="pln"> </span><span class="lit">1</span><span class="pun">));</span></pre>

<p>
	لاحظ أنه بدون الجزء الأول من عملية التحقق (<code>n &amp;&amp;</code>)، فسيُعد العدد <code>0</code> أسًّا للرقم 2، وذلك خطأ.
</p>

<h2>
	تعيين بت محدَّد
</h2>

<h3>
	معالجة البتات وفق أسلوب لغة C
</h3>

<p>
	يمكن تعيين قيمة بت باستخدام عامل OR الثنائي (<code>|</code>).
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8538_33" style="">
<span class="com">// x تعيين قيمة البت رقم</span><span class="pln">
number </span><span class="pun">|=</span><span class="pln"> </span><span class="lit">1LL</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> x</span><span class="pun">;</span></pre>

<h3>
	استخدام std::bitset
</h3>

<p>
	التعبير <code>set(x)‎</code> أو ‎<code>set (x, true)‎</code>‎ يُسنِد القيمة 1 إلى البت الموجودة في الموضع <code>x</code>.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6994_26" style="">
<span class="pln">std</span><span class="pun">::</span><span class="typ">bitset</span><span class="pun">&lt;</span><span class="lit">5</span><span class="pun">&gt;</span><span class="pln"> num</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">string</span><span class="pun">(</span><span class="str">"01100"</span><span class="pun">));</span><span class="pln">
num</span><span class="pun">.</span><span class="typ">set</span><span class="pun">(</span><span class="lit">0</span><span class="pun">);</span><span class="pln"> </span><span class="com">// num = 01101</span><span class="pln">
num</span><span class="pun">.</span><span class="typ">set</span><span class="pun">(</span><span class="lit">2</span><span class="pun">);</span><span class="pln"> </span><span class="com">// 01101 يساوي num لا يزال</span><span class="pln">
num</span><span class="pun">.</span><span class="typ">set</span><span class="pun">(</span><span class="lit">4</span><span class="pun">,</span><span class="kwd">true</span><span class="pun">);</span><span class="pln"> </span><span class="com">// 11110 يساوي الآن num</span></pre>

<h2>
	تصفير بت محدَّد
</h2>

<h3>
	معالجة البتات وفق مقاربة لغة C
</h3>

<p>
	يمكن تصفير (إعطاء القيمة 0) بت محدَّد باستخدام معامِل AND الثنائي (<code>&amp;</code>).
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8538_37" style="">
<span class="com">// x مسح البت الموجودة عند الموضع</span><span class="pln">
number </span><span class="pun">&amp;=</span><span class="pln"> </span><span class="pun">~(</span><span class="lit">1LL</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> x</span><span class="pun">);</span></pre>

<h3>
	استخدام <code>std::bitset</code>
</h3>

<p>
	تصفر التعليمة <code>reset(x)‎</code> أو ‎<code>set (x, false))‎</code>‎ يمسح البت الموجودة في الموضع <code>x</code>.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8538_39" style="">
<span class="pln">std</span><span class="pun">::</span><span class="typ">bitset</span><span class="pun">&lt;</span><span class="lit">5</span><span class="pun">&gt;</span><span class="pln"> num</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">string</span><span class="pun">(</span><span class="str">"01100"</span><span class="pun">));</span><span class="pln">
num</span><span class="pun">.</span><span class="pln">reset</span><span class="pun">(</span><span class="lit">2</span><span class="pun">);</span><span class="pln"> </span><span class="com">// 01000  يساوي الآن  num</span><span class="pln">
num</span><span class="pun">.</span><span class="pln">reset</span><span class="pun">(</span><span class="lit">0</span><span class="pun">);</span><span class="pln"> </span><span class="com">// 01000  يساوي الآن  num</span><span class="pln">
num</span><span class="pun">.</span><span class="typ">set</span><span class="pun">(</span><span class="lit">3</span><span class="pun">,</span><span class="kwd">false</span><span class="pun">);</span><span class="pln"> </span><span class="com">// 00000  يساوي الآن  num</span></pre>

<h2>
	تغيير قيمة البت رقم n إلى x
</h2>

<h3>
	معالجة البتات وفق أسلوب لغة C
</h3>

<p>
	في المثال التالي، ستضبط قيمة البت رقم  n إلى القيمة 1 في حال كانت قيمة x تساوي 1 وستُصفَّر قيمتها في حال كانت قيمة x يساوي الصفر:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6994_31" style="">
<span class="pln">number </span><span class="pun">^=</span><span class="pln"> </span><span class="pun">(-</span><span class="pln">x </span><span class="pun">^</span><span class="pln"> number</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> </span><span class="pun">(</span><span class="lit">1LL</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> n</span><span class="pun">);</span></pre>

<h3>
	استخدام <code>std::bitset</code>
</h3>

<p>
	تعين التعليمة <code>set(n,val)‎</code> يعين القيمة <code>val</code> للبتّة <code>n</code>.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8538_43" style="">
<span class="pln">std</span><span class="pun">::</span><span class="typ">bitset</span><span class="pun">&lt;</span><span class="lit">5</span><span class="pun">&gt;</span><span class="pln"> num</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="pln">string</span><span class="pun">(</span><span class="str">"00100"</span><span class="pun">));</span><span class="pln">
num</span><span class="pun">.</span><span class="typ">set</span><span class="pun">(</span><span class="lit">0</span><span class="pun">,</span><span class="kwd">true</span><span class="pun">);</span><span class="pln"> </span><span class="com">// 00101 يساوي الآن num</span><span class="pln">
num</span><span class="pun">.</span><span class="typ">set</span><span class="pun">(</span><span class="lit">2</span><span class="pun">,</span><span class="kwd">false</span><span class="pun">);</span><span class="pln"> </span><span class="com">// 00001 يساوي الآن num</span></pre>

<h2>
	تطبيق على معالجة البتات: تغيير حالة الحروف
</h2>

<p>
	أحد التطبيقات على معالجة البتات والتلاعب بها هو تحويل الحروف الأجنبية من الحالة الصغرى (Small) إلى الحالة الكبرى (Capital) أو العكس، عن طريق اختيار <strong>قناع</strong> (mask) و <strong>عملية ثنائية</strong> (bit operation) مناسبة. فمثلًا، يكون التمثيل الثنائي للحرف a هو <code>‎01(1)00001</code>، وللحرف A هو <code>01‎(0)00001‎</code>. لا يختلف التمثيلان السابقان إلا في البت الموجودة بين القوسين. لذا فإنّ تحويل الحرف a من الحالة الصغرى إلى الحالة الكبرى يكافئ تعيين البت الموجودة بين قوسين على القيمة 1 على النحو التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8538_45" style="">
<span class="com">/****************************************
تكبير حرف صغير
========================================
a: 01100001
mask: 11011111  &lt;-- (0xDF)  11(0)11111
:---------
a&amp;mask: 01000001  &lt;-- A الحرف
*****************************************/</span></pre>

<p>
	شيفرة تكبير الحرف A هي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6994_33" style="">
<span class="com">#include</span><span class="pln"> </span><span class="str">&lt;cstdio&gt;</span><span class="pln">

</span><span class="typ">int</span><span class="pln"> main</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">char</span><span class="pln"> op1 </span><span class="pun">=</span><span class="pln"> </span><span class="str">'a'</span><span class="pun">;</span><span class="pln"> </span><span class="com">// "a" الحرف</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> mask </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0xDF</span><span class="pun">;</span><span class="pln"> </span><span class="com">// اختيار قناع مناسب</span><span class="pln">
  
    printf</span><span class="pun">(</span><span class="str">"a (AND) mask = A\n"</span><span class="pun">);</span><span class="pln">
    printf</span><span class="pun">(</span><span class="str">"%c   &amp;   0xDF = %c\n"</span><span class="pun">,</span><span class="pln"> op1</span><span class="pun">,</span><span class="pln"> op1 </span><span class="pun">&amp;</span><span class="pln"> mask</span><span class="pun">);</span><span class="pln">

    </span><span class="kwd">return</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	النتيجة:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8538_49" style="">
<span class="pln">$ g</span><span class="pun">++</span><span class="pln"> main</span><span class="pun">.</span><span class="pln">cpp </span><span class="pun">-</span><span class="pln">o test1
$ </span><span class="pun">./</span><span class="pln">test1
a </span><span class="pun">(</span><span class="pln">AND</span><span class="pun">)</span><span class="pln"> mask </span><span class="pun">=</span><span class="pln"> A
a   </span><span class="pun">&amp;</span><span class="pln"> </span><span class="lit">0xDF</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> A</span></pre>

<h2>
	حقول البتات
</h2>

<p>
	تحزِّم حقولُ البتات (Bit fields) بُنيات C و C++‎ لتصغير حجمها، إذ تحدد عدد البتات المخصصة لأعضاء البنية، ثم يدمج المصرّف (co-mingle) البتّات. السيء في هذا هو أنك لن تستطيع تحديد عنوان حقل البتة الخاص بعضو معين من البنية لأن المصرّف يدمجهما معًا. كذلك فإن الدالة <code>sizeof()‎</code> غير مسموح بها.
</p>

<p>
	أحد الجوانب السلبية الأخرى، هو أنّ الدخول إلى حقول البتات بطيء بسبب الحاجة لاسترجاع الذاكرة ثم تطبيق العمليات الثنائية لاستخراج أو تعديل قيم الأعضاء. قد تزيد هذه العمليات أيضًا في حجم البرنامج التنفيذي (executable).
</p>

<p>
	إليك المثال التالي لتوضيح كيفية التصريح والاستخدام:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1869_7" style="">
<span class="kwd">struct</span><span class="pln"> </span><span class="typ">FileAttributes</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">unsigned</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="typ">ReadOnly</span><span class="pun">:</span><span class="pln"> </span><span class="lit">1</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">unsigned</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="typ">Hidden</span><span class="pun">:</span><span class="pln"> </span><span class="lit">1</span><span class="pun">;</span><span class="pln">
</span><span class="pun">};</span></pre>

<p>
	في هذا المثال، سيشغل كلّ حقل من هذين الحقلين بتّة واحدة في الذاكرة، وعلامة ذلك العدد <code>1</code> الموجود بعد أسماء المتغيّرات.
</p>

<p>
	يمكن أن يكون حقل البتات من أيّ نوع عددي صحيح (من ‎8-bit int وحتى ‎64-bit‎ int‎). يُستحسن استخدام النوع <code>unsigned</code>، وإلا فقد تحصل على نتائج غير متوقعة. إذا كانت هناك حاجة إلى المزيد من البتات، فاستبدل "1" بعدد البتات المطلوب. مثلًا:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1869_9" style="">
<span class="kwd">struct</span><span class="pln"> </span><span class="typ">Date</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">unsigned</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="typ">Year</span><span class="pun">:</span><span class="pln"> </span><span class="lit">13</span><span class="pun">;</span><span class="pln"> </span><span class="com">// 2^13 = 8192</span><span class="pln">
    </span><span class="kwd">unsigned</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="typ">Month</span><span class="pun">:</span><span class="pln"> </span><span class="lit">4</span><span class="pun">;</span><span class="pln"> </span><span class="com">// 2^4 = 16</span><span class="pln">
    </span><span class="kwd">unsigned</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="typ">Day</span><span class="pun">:</span><span class="pln"> </span><span class="lit">5</span><span class="pun">;</span><span class="pln"> </span><span class="com">// 32</span><span class="pln">
</span><span class="pun">};</span></pre>

<p>
	البنية بأكملها لن تستخدم إلا 22 بت فقط، وفي إعدادات التصريف العادية، سيكون ناتج <code>sizeof</code> الخاص بهذه البنية هو 4 بايتات. استخدام حقول البتات سهل جدّا، فما عليك إلا التصريح عن المتغيّر ثم استخدامه كبنية عادية.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6994_36" style="">
<span class="typ">Date</span><span class="pln"> d</span><span class="pun">;</span><span class="pln">
d</span><span class="pun">.</span><span class="typ">Year</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">2016</span><span class="pun">;</span><span class="pln">
d</span><span class="pun">.</span><span class="typ">Month</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">7</span><span class="pun">;</span><span class="pln">
d</span><span class="pun">.</span><span class="typ">Day</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">22</span><span class="pun">;</span><span class="pln">

std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"Year:"</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> d</span><span class="pun">.</span><span class="typ">Year</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl </span><span class="pun">&lt;&lt;</span><span class="pln">
    </span><span class="str">"Month:"</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> d</span><span class="pun">.</span><span class="typ">Month</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl </span><span class="pun">&lt;&lt;</span><span class="pln">
    </span><span class="str">"Day:"</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> d</span><span class="pun">.</span><span class="typ">Day</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span></pre>

<p>
	هذا الدرس جزء من <a data-ss1617022337="1" href="https://academy.hsoub.com/tags/%D8%B3%D9%84%D8%B3%D9%84%D8%A9%20++c%20%D9%84%D9%84%D9%85%D8%AD%D8%AA%D8%B1%D9%81%D9%8A%D9%86/%D8%B1%D8%A7%D8%A8%D8%B7" rel="">سلسلة دروس عن C++‎</a>.
</p>

<p>
	ترجمة -وبتصرّف- للفصل Chapter 6: Bit Manipulation من كتاب <a data-ss1617022337="1" href="https://goalkicker.com/CPlusPlusBook/CPlusPlusNotesForProfessionals.pdf" rel="external nofollow">C++ Notes for Professionals</a>
</p>

<h2>
	اقرأ أيضا
</h2>

<ul>
<li>
		<a data-ss1617022337="1" href="https://academy.hsoub.com/programming/cpp/%D8%A7%D9%84%D8%AF%D8%B1%D8%B3-5-%D8%A7%D9%84%D8%B9%D9%85%D9%84%D9%8A%D8%A7%D8%AA-%D8%A7%D9%84%D8%A8%D8%AA%D9%91%D9%8A%D9%91%D8%A9-r806/" rel="">الدرس 5: العمليات البتية</a>
	</li>
</ul>
]]></description><guid isPermaLink="false">807</guid><pubDate>Wed, 12 Feb 2020 18:08:00 +0000</pubDate></item><item><title>&#x627;&#x644;&#x639;&#x645;&#x644;&#x64A;&#x627;&#x62A; &#x627;&#x644;&#x628;&#x62A;&#x64A;&#x629; (Bitwise Operators) &#x641;&#x64A; ++C</title><link>https://academy.hsoub.com/programming/cpp/%D8%A7%D9%84%D8%B9%D9%85%D9%84%D9%8A%D8%A7%D8%AA-%D8%A7%D9%84%D8%A8%D8%AA%D9%8A%D8%A9-bitwise-operators-%D9%81%D9%8A-c-r806/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2020_06/5.png.ac7d0d5d9d3429afe7f81cdeb790f6b4.png" /></p>

<p>
	تُنفَّذ العمليات البتية (أو الثنائية) على مستوى البت من البيانات وذلك باستعمال العوامل التالية:
</p>

<h2>
	<code>|</code> - عامِل OR البِتِّي (Bitwise OR)
</h2>

<p>
	إليك المثال التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7431_22" style="">
<span class="typ">int</span><span class="pln"> a </span><span class="pun">=</span><span class="pln"> </span><span class="lit">5</span><span class="pun">;</span><span class="pln"> </span><span class="com">// 0101b  (0x05)</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> b </span><span class="pun">=</span><span class="pln"> </span><span class="lit">12</span><span class="pun">;</span><span class="pln"> </span><span class="com">// 1100b  (0x0C)</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> c </span><span class="pun">=</span><span class="pln"> a </span><span class="pun">|</span><span class="pln"> b</span><span class="pun">;</span><span class="pln"> </span><span class="com">// 1101b  (0x0D)</span><span class="pln">

std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"a = "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> a </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">", b = "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> b </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">", c = "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> c </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span></pre>

<p>
	يكون ناتج الشيفرة السابقة هو:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3047_15" style="">
<span class="pln">a </span><span class="pun">=</span><span class="pln"> </span><span class="lit">5</span><span class="pun">,</span><span class="pln"> b </span><span class="pun">=</span><span class="pln"> </span><span class="lit">12</span><span class="pun">,</span><span class="pln"> c </span><span class="pun">=</span><span class="pln"> </span><span class="lit">13</span></pre>

<p>
	وسبب ذلك أن عامِل <code>OR</code> يعمل على مستوى البِتّْ (bit level)، ويستخدم جدول الصحة البوليني أو المنطقي (Boolean Truth Table) التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3047_17" style="">
<span class="kwd">true</span><span class="pln"> OR </span><span class="kwd">true</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">true</span><span class="pln">
</span><span class="kwd">true</span><span class="pln"> OR </span><span class="kwd">false</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">true</span><span class="pln">
</span><span class="kwd">false</span><span class="pln"> OR </span><span class="kwd">false</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">false</span></pre>

<p>
	عندما يُطبق عامل <code>OR</code> على القيمتين البتّيّتين ‎<code>a</code> ‎ (أي <code>0101</code>)‎ و ‎<code>b</code> ‎ (أي <code>1100</code>)‎ ، سنحصل على القيمة البتّيّة <code>1101</code>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3047_19" style="">
<span class="typ">int</span><span class="pln"> a </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln"> </span><span class="lit">1</span><span class="pln"> </span><span class="lit">0</span><span class="pln"> </span><span class="lit">1</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> b </span><span class="pun">=</span><span class="pln"> </span><span class="lit">1</span><span class="pln"> </span><span class="lit">1</span><span class="pln"> </span><span class="lit">0</span><span class="pln"> </span><span class="lit">0</span><span class="pln"> </span><span class="pun">|</span><span class="pln">
</span><span class="pun">---------</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> c </span><span class="pun">=</span><span class="pln"> </span><span class="lit">1</span><span class="pln"> </span><span class="lit">1</span><span class="pln"> </span><span class="lit">0</span><span class="pln"> </span><span class="lit">1</span></pre>

<p>
	لا يغير عامِل <code>OR</code> القيم الأصلية للمعامَلات إلا في حالة استخدام عامِل الإسناد البِتِّي المركَّب <code>=|</code> (Bitwise Assignment Compound Operator) لإسناد تغيير تلك القيم:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3047_21" style="">
<span class="typ">int</span><span class="pln"> a </span><span class="pun">=</span><span class="pln"> </span><span class="lit">5</span><span class="pun">;</span><span class="pln"> </span><span class="com">// 0101b  (0x05)</span><span class="pln">
a </span><span class="pun">|=</span><span class="pln"> </span><span class="lit">12</span><span class="pun">;</span><span class="pln"> </span><span class="com">// a = 0101b | 1101b</span></pre>

<h2>
	<code>^</code> - عامل XOR البِتِّي (Bitwise XOR)
</h2>

<p>
	إليك المثال التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7431_24" style="">
<span class="typ">int</span><span class="pln"> a </span><span class="pun">=</span><span class="pln"> </span><span class="lit">5</span><span class="pun">;</span><span class="pln"> </span><span class="com">// 0101b  (0x05)</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> b </span><span class="pun">=</span><span class="pln"> </span><span class="lit">9</span><span class="pun">;</span><span class="pln"> </span><span class="com">// 1001b  (0x09)</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> c </span><span class="pun">=</span><span class="pln"> a </span><span class="pun">^</span><span class="pln"> b</span><span class="pun">;</span><span class="pln"> </span><span class="com">// 1100b  (0x0C)</span><span class="pln">

std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"a = "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> a </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">", b = "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> b </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">", c = "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> c </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span></pre>

<p>
	يكون ناتج الشيفرة السابقة:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3047_25" style="">
<span class="pln">a </span><span class="pun">=</span><span class="pln"> </span><span class="lit">5</span><span class="pun">,</span><span class="pln"> b </span><span class="pun">=</span><span class="pln"> </span><span class="lit">9</span><span class="pun">,</span><span class="pln"> c </span><span class="pun">=</span><span class="pln"> </span><span class="lit">12</span></pre>

<p>
	وسبب ذلك أن عامِل <code>XOR</code> يعمل على مستوى البِتّْ (bit level)، ويستخدم جدول الصحة البولياني التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3047_28" style="">
<span class="kwd">true</span><span class="pln"> OR </span><span class="kwd">true</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">false</span><span class="pln">
</span><span class="kwd">true</span><span class="pln"> OR </span><span class="kwd">false</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">true</span><span class="pln">
</span><span class="kwd">false</span><span class="pln"> OR </span><span class="kwd">false</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">false</span></pre>

<p>
	لاحظ أنه في عملية XOR، يكون لدينا <code>true XOR true = false</code>، على خلاف العمليتين AND و OR، إذ تحققان: <code>true AND/OR true = true</code>، وذلك هو وصف الطبيعة الحصرية لعملية XOR. عندما يُطبّق عامِل <code>XOR</code> على القيمتين البتّيّتين ‎<code>a</code> ‎ (أي <code>0101</code>)‎ و ‎<code>b</code> ‎ (أي <code>1001</code>)‎ ، سنحصل على القيمة البتّيّة <code>1101</code>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3047_30" style="">
<span class="typ">int</span><span class="pln"> a </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln"> </span><span class="lit">1</span><span class="pln"> </span><span class="lit">0</span><span class="pln"> </span><span class="lit">1</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> b </span><span class="pun">=</span><span class="pln"> </span><span class="lit">1</span><span class="pln"> </span><span class="lit">0</span><span class="pln"> </span><span class="lit">0</span><span class="pln"> </span><span class="lit">1</span><span class="pln"> </span><span class="pun">^</span><span class="pln">
</span><span class="pun">---------</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> c </span><span class="pun">=</span><span class="pln"> </span><span class="lit">1</span><span class="pln"> </span><span class="lit">1</span><span class="pln"> </span><span class="lit">0</span><span class="pln"> </span><span class="lit">0</span></pre>

<p>
	لا يغير عامِل <code>XOR</code> القيم الأصلية للمعامَلات إلا في حالة استخدام عامِل الإسناد البِتِّي المركَّب <code>=^</code> (Bitwise Assignment Compound Operator) لإسناد تغيير تلك القيم:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3047_32" style="">
<span class="typ">int</span><span class="pln"> a </span><span class="pun">=</span><span class="pln"> </span><span class="lit">5</span><span class="pun">;</span><span class="pln"> </span><span class="com">// 0101b  (0x05)</span><span class="pln">
a </span><span class="pun">^=</span><span class="pln"> </span><span class="lit">9</span><span class="pun">;</span><span class="pln"> </span><span class="com">// a = 0101b ^ 1001b</span></pre>

<p>
	يمكن استخدام عامِل XOR بعدة طرق، وغالبًا ما يُستخدَم في عمليات البتات المُقنّعة (bit mask operations) لتشفير البيانات وضغطها.
</p>

<p>
	<strong>لاحظ</strong> أن المثال التالي توضيحي، ولا ينبغي أن يُستخدم في الشيفرة النهائية (هناك طرق أفضل لتحقيق نفس النتيجة، مثل <code>std::swap()‎</code>). تستطيع استخدام عملية XOR لمبادلة متغيرين:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7431_6" style="">
<span class="typ">int</span><span class="pln"> a </span><span class="pun">=</span><span class="pln"> </span><span class="lit">42</span><span class="pun">;</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> b </span><span class="pun">=</span><span class="pln"> </span><span class="lit">64</span><span class="pun">;</span><span class="pln">

</span><span class="com">// XOR المبادلة عبر</span><span class="pln">
a </span><span class="pun">^=</span><span class="pln"> b</span><span class="pun">;</span><span class="pln">
b </span><span class="pun">^=</span><span class="pln"> a</span><span class="pun">;</span><span class="pln">
a </span><span class="pun">^=</span><span class="pln"> b</span><span class="pun">;</span><span class="pln">

std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"a = "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> a </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">", b = "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> b </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"\n"</span><span class="pun">;</span></pre>

<p>
	لإنجاز هذا، تحتاج إلى التحقق من إمكانية استخدامه.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_5432_6" style="">
<span class="kwd">void</span><span class="pln"> doXORSwap</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> a</span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> b</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="com">// ينبغي إضافة عبارة للتحقق من أنك لا تبادل المتغير مع نفسه</span><span class="pln">
    </span><span class="com">// وإلا ستجعل القيمة صفرية</span><span class="pln">
  
    </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> a </span><span class="pun">!=</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> b</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        </span><span class="com">// XOR مبادلة</span><span class="pln">
        a </span><span class="pun">^=</span><span class="pln"> b</span><span class="pun">;</span><span class="pln">
        b </span><span class="pun">^=</span><span class="pln"> a</span><span class="pun">;</span><span class="pln">
        a </span><span class="pun">^=</span><span class="pln"> b</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	ورغم أنها تبدو طريقة مناسبة للعزل إلا أنها ليست مفيدة في شيفرة الإنتاج، ذلك أن xor ليس عملية منطقية أساسية، بل مزيج من عمليات أخرى: <code>a^c=~(a&amp;c)&amp;(a|c)‎</code>.
</p>

<p>
	كذلك ، فإن المُصرفات التي صدرت بعد 2015 أتاحت إسناد قيم ثنائية إلى المتغيرات:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3047_38" style="">
<span class="typ">int</span><span class="pln"> cn</span><span class="pun">=</span><span class="lit">0b0111</span><span class="pun">;</span></pre>

<h2>
	<code>&amp;</code> - عامل AND البتّيّ
</h2>

<p>
	إليك المثال التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7431_8" style="">
<span class="typ">int</span><span class="pln"> a </span><span class="pun">=</span><span class="pln"> </span><span class="lit">6</span><span class="pun">;</span><span class="pln"> </span><span class="com">// 0110b  (0x06)</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> b </span><span class="pun">=</span><span class="pln"> </span><span class="lit">10</span><span class="pun">;</span><span class="pln"> </span><span class="com">// 1010b  (0x0A)</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> c </span><span class="pun">=</span><span class="pln"> a </span><span class="pun">&amp;</span><span class="pln"> b</span><span class="pun">;</span><span class="pln"> </span><span class="com">// 0010b  (0x02)</span><span class="pln">

std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"a = "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> a </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">", b = "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> b </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">", c = "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> c </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span></pre>

<p>
	يكون ناتج الشيفرة السابقة:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3047_42" style="">
<span class="pln">a </span><span class="pun">=</span><span class="pln"> </span><span class="lit">6</span><span class="pun">,</span><span class="pln"> b </span><span class="pun">=</span><span class="pln"> </span><span class="lit">10</span><span class="pun">,</span><span class="pln"> c </span><span class="pun">=</span><span class="pln"> </span><span class="lit">2</span></pre>

<p>
	وسبب ذلك أن عامل <code>AND</code> يعمل على مستوى البت، ويستخدم جدول الصحة البوليني التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3047_47" style="">
<span class="pln">TRUE  AND TRUE  </span><span class="pun">=</span><span class="pln"> TRUE
TRUE  AND FALSE </span><span class="pun">=</span><span class="pln"> FALSE
FALSE AND FALSE </span><span class="pun">=</span><span class="pln"> FALSE</span></pre>

<p>
	عندما يُطبق عامِل <code>AND</code> على القيمتين البتّيّتين ‎<code>a</code> ‎ (أي <code>0110</code>)‎ و ‎<code>b</code> ‎ (أي <code>1010</code>)‎ ، سنحصل على القيمة البتّيّة <code>0010</code>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3047_49" style="">
<span class="typ">int</span><span class="pln"> a </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln"> </span><span class="lit">1</span><span class="pln"> </span><span class="lit">1</span><span class="pln"> </span><span class="lit">0</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> b </span><span class="pun">=</span><span class="pln"> </span><span class="lit">1</span><span class="pln"> </span><span class="lit">0</span><span class="pln"> </span><span class="lit">1</span><span class="pln"> </span><span class="lit">0</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln">
</span><span class="pun">---------</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> c </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pln"> </span><span class="lit">0</span><span class="pln"> </span><span class="lit">1</span><span class="pln"> </span><span class="lit">0</span></pre>

<p>
	لا يغير عامِل AND قيمة المعامَل الأصلي إلا عند استخدام عامِل الإسناد البِتِّي المركب <code>‎&amp;=‎</code>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3047_51" style="">
<span class="typ">int</span><span class="pln"> a </span><span class="pun">=</span><span class="pln"> </span><span class="lit">5</span><span class="pun">;</span><span class="pln"> </span><span class="com">// 0101b  (0x05)</span><span class="pln">
a </span><span class="pun">&amp;=</span><span class="pln"> </span><span class="lit">10</span><span class="pun">;</span><span class="pln"> </span><span class="com">// a = 0101b &amp; 1010b</span></pre>

<h2>
	<code>&lt;&lt;</code> - عملية الإزاحة اليسارية (left shift)
</h2>

<p>
	إليك المثال التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7431_10" style="">
<span class="typ">int</span><span class="pln"> a </span><span class="pun">=</span><span class="pln"> </span><span class="lit">1</span><span class="pun">;</span><span class="pln"> </span><span class="com">// 0001b</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> b </span><span class="pun">=</span><span class="pln"> a </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="lit">1</span><span class="pun">;</span><span class="pln"> </span><span class="com">// 0010b</span><span class="pln">

std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"a = "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> a </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">", b = "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> b </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span></pre>

<p>
	يكون ناتج ذلك هو:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3047_55" style="">
<span class="pln">a </span><span class="pun">=</span><span class="pln"> </span><span class="lit">1</span><span class="pun">,</span><span class="pln"> b </span><span class="pun">=</span><span class="pln"> </span><span class="lit">2</span></pre>

<p>
	وتفسير ذلك أن عامِل الإزاحة اليساري يزيح بتَّات القيمة الموجودة على الجانب الأيسر (<code>a</code>) بالعدد المحدد على اليمين (<code>1</code>)، مع ملأ البتات الأقل أهمية (least signiﬁcant bits) بأصفار، فمثلًا في حال إزاحة قيمة العدد <code>5</code> (تمثيله الثنائي <code>0000 0101</code>) إلى اليسار أربعة منازل (على سبيل المثال <code>‎5 &lt;&lt;‎4</code>)، سوف نحصل على القيمة 80 (تمثيلها الثنائي <code>0101 0000</code>). قد تلاحظ أنّ إزاحة قيمة إلى اليسار بمنزلة واحدة يكافئ ضرب تلك القيمة بالعدد 2، على سبيل المثال:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7431_12" style="">
<span class="typ">int</span><span class="pln"> a </span><span class="pun">=</span><span class="pln"> </span><span class="lit">7</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">while</span><span class="pln"> </span><span class="pun">(</span><span class="pln">a </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">200</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"a = "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> a </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
    a </span><span class="pun">&lt;&lt;=</span><span class="pln"> </span><span class="lit">1</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

a </span><span class="pun">=</span><span class="pln"> </span><span class="lit">7</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">while</span><span class="pln"> </span><span class="pun">(</span><span class="pln">a </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">200</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"a = "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> a </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
    a </span><span class="pun">*=</span><span class="pln"> </span><span class="lit">2</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	ولكن تجدر الإشارة إلى أنّ عملية الإزاحة اليسارية سوف تزيح جميع البتات إلى اليسار، بما في ذلك بتّ الإشارة، انظر إلى المثال التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7431_14" style="">
<span class="typ">int</span><span class="pln"> a </span><span class="pun">=</span><span class="pln"> </span><span class="lit">2147483647</span><span class="pun">;</span><span class="pln"> </span><span class="com">// 0111 1111 1111 1111 1111 1111 1111 1111</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> b </span><span class="pun">=</span><span class="pln"> a </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="lit">1</span><span class="pun">;</span><span class="pln"> </span><span class="com">// 1111 1111 1111 1111 1111 1111 1111 1110</span><span class="pln">

std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"a = "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> a </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">", b = "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> b </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span></pre>

<p>
	سيكون الناتج:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3047_61" style="">
<span class="pln">a </span><span class="pun">=</span><span class="pln"> </span><span class="lit">2147483647</span><span class="pun">,</span><span class="pln"> b </span><span class="pun">=</span><span class="pln"> </span><span class="pun">-</span><span class="lit">2</span></pre>

<p>
	وفي حين أنّ بعض المُصرِّفات ستعيد نتائج قد تبدو متوقعة غير أنه يجب ملاحظة أن إزاحة عددٍ ذا إشارة (signed number) بحيث تتأثر بتة الإشارة (sign bit)، فستكون النتيجة غير محددة (undefined). كذلك في حال كان عدد البتات التي ترغب في إزاحتها عددًا سالبًا، أو كان أكبر من عدد البتات التي يمكن أن يحملها النوع الموجود على اليسار، انظر:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7431_16" style="">
<span class="typ">int</span><span class="pln"> a </span><span class="pun">=</span><span class="pln"> </span><span class="lit">1</span><span class="pun">;</span><span class="pln">

</span><span class="typ">int</span><span class="pln"> b </span><span class="pun">=</span><span class="pln"> a </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="pun">-</span><span class="lit">1</span><span class="pun">;</span><span class="pln"> </span><span class="com">// سلوك غير محدد</span><span class="pln">
</span><span class="kwd">char</span><span class="pln"> c </span><span class="pun">=</span><span class="pln"> a </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="lit">20</span><span class="pun">;</span><span class="pln"> </span><span class="com">// سلوك غير محدد</span></pre>

<p>
	لا تغير الإزاحة البتّيّة اليسارية قيمة المعامَلات إلا في حال استخدام عامِل الإسناد البِتِّي المركب <code>‎&lt;&lt;=‎</code>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3047_65" style="">
<span class="typ">int</span><span class="pln"> a </span><span class="pun">=</span><span class="pln"> </span><span class="lit">5</span><span class="pun">;</span><span class="pln"> </span><span class="com">// 0101b</span><span class="pln">
a </span><span class="pun">&lt;&lt;=</span><span class="pln"> </span><span class="lit">1</span><span class="pun">;</span><span class="pln"> </span><span class="com">// a = a &lt;&lt; 1;</span></pre>

<h2>
	<code>&gt;&gt;</code> - الإزاحة اليمينية (right shift)
</h2>

<p>
	إليك المثال التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7431_18" style="">
<span class="typ">int</span><span class="pln"> a </span><span class="pun">=</span><span class="pln"> </span><span class="lit">2</span><span class="pun">;</span><span class="pln">        </span><span class="com">// 0010b</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> b </span><span class="pun">=</span><span class="pln"> a </span><span class="pun">&gt;&gt;</span><span class="pln"> </span><span class="lit">1</span><span class="pun">;</span><span class="pln">     </span><span class="com">// 0001b</span><span class="pln">

std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"a = "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> a </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">", b = "</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> b </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span></pre>

<p>
	سيكون الناتج:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3047_69" style="">
<span class="pln">a </span><span class="pun">=</span><span class="pln"> </span><span class="lit">2</span><span class="pun">,</span><span class="pln"> b </span><span class="pun">=</span><span class="pln"> </span><span class="lit">1</span></pre>

<p>
	وتفسير ذلك أن عامِل الإزاحة اليميني يزيح بتِّات القيمة الموجودة على الجانب الأيسر (<code>a</code>) بالعدد المحدد على اليمين (<code>1</code>)؛ وتجدر الإشارة إلى أنه رغم أنّ عملية الإزاحة اليمينية قياسية، فإنّ ما يحدث لبتات الإزاحة اليمينية في الأعداد السالبة ذات الإشارة (signed negative number) يختلف بحسب الاستخدام، ومن ثم لا يمكن ضمان كونها قابلة للنقل (portable)، انظر:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3047_71" style="">
<span class="typ">int</span><span class="pln"> a </span><span class="pun">=</span><span class="pln"> </span><span class="pun">-</span><span class="lit">2</span><span class="pun">;</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> b </span><span class="pun">=</span><span class="pln"> a </span><span class="pun">&gt;&gt;</span><span class="pln"> </span><span class="lit">1</span><span class="pun">;</span><span class="pln"> </span><span class="com">// على المصرّف b تعتمد قيمة</span></pre>

<p>
	كذلك سيكون ذلك السلوك غير محدد إن كان عدد البتات التي ترغب في إزاحتها سالبًا، على سبيل المثال:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3047_73" style="">
<span class="typ">int</span><span class="pln"> a </span><span class="pun">=</span><span class="pln"> </span><span class="lit">1</span><span class="pun">;</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> b </span><span class="pun">=</span><span class="pln"> a </span><span class="pun">&gt;&gt;</span><span class="pln"> </span><span class="pun">-</span><span class="lit">1</span><span class="pun">;</span><span class="pln"> </span><span class="com">// سلوك غير محدد</span></pre>

<p>
	لا يغيّر عامل الإزاحة اليميني قيمة المعامَل الأصلي إلا في حال استخدام عامِل الإسناد البِتِّي المركب <code>‎&gt;&gt;=‎</code>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3047_75" style="">
<span class="typ">int</span><span class="pln"> a </span><span class="pun">=</span><span class="pln"> </span><span class="lit">2</span><span class="pun">;</span><span class="pln"> </span><span class="com">// 0010b</span><span class="pln">
a </span><span class="pun">&gt;&gt;=</span><span class="pln"> </span><span class="lit">1</span><span class="pun">;</span><span class="pln"> </span><span class="com">// a = a &gt;&gt; 1;</span></pre>

<p>
	هذا الدرس جزء من <a data-ss1617022334="1" href="https://academy.hsoub.com/tags/%D8%B3%D9%84%D8%B3%D9%84%D8%A9%20++c%20%D9%84%D9%84%D9%85%D8%AD%D8%AA%D8%B1%D9%81%D9%8A%D9%86/" rel="">سلسلة دروس عن C++‎</a>.
</p>

<p>
	ترجمة -وبتصرّف- للفصل Chapter 5: Bit Operators من كتاب <a data-ss1617022334="1" href="https://goalkicker.com/CPlusPlusBook/CPlusPlusNotesForProfessionals.pdf" rel="external nofollow">C++ Notes for Professionals</a>
</p>

<h2>
	اقرأ أيضا
</h2>

<ul>
<li>
		<a data-ss1617022334="1" href="https://academy.hsoub.com/programming/cpp/%D8%A7%D9%84%D8%AF%D8%B1%D8%B3-6-%D9%85%D8%B9%D8%A7%D9%84%D8%AC%D8%A9-%D8%A7%D9%84%D8%A8%D8%AA%D8%A7%D8%AA-%D9%88%D8%A7%D9%84%D8%AA%D9%84%D8%A7%D8%B9%D8%A8-%D8%A8%D9%87%D8%A7-r807/" rel="">الدرس 6: معالجة البتات والتلاعب بها</a>
	</li>
	<li>
		<a data-ss1617022334="1" href="https://academy.hsoub.com/programming/cpp/%D8%A7%D9%84%D8%AF%D8%B1%D8%B3-4-%D8%AD%D8%B3%D8%A7%D8%A8%D9%8A%D9%91%D8%A7%D8%AA-%D8%A7%D9%84%D8%A3%D8%B9%D8%AF%D8%A7%D8%AF-%D8%A7%D9%84%D8%B9%D8%B4%D8%B1%D9%8A%D8%A9-r805/" rel="">الدرس 4: حسابيّات الأعداد العشرية</a>
	</li>
</ul>
]]></description><guid isPermaLink="false">806</guid><pubDate>Mon, 10 Feb 2020 18:08:00 +0000</pubDate></item><item><title>&#x62D;&#x633;&#x627;&#x628;&#x64A;&#x651;&#x627;&#x62A; &#x627;&#x644;&#x623;&#x639;&#x62F;&#x627;&#x62F; &#x627;&#x644;&#x639;&#x634;&#x631;&#x64A;&#x629; &#x641;&#x64A; ++C</title><link>https://academy.hsoub.com/programming/cpp/%D8%AD%D8%B3%D8%A7%D8%A8%D9%8A%D9%91%D8%A7%D8%AA-%D8%A7%D9%84%D8%A3%D8%B9%D8%AF%D8%A7%D8%AF-%D8%A7%D9%84%D8%B9%D8%B4%D8%B1%D9%8A%D8%A9-%D9%81%D9%8A-c-r805/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2020_06/4.png.9d64e78d9d303e5b3c1f4b4fb63a9701.png" /></p>

<p>
	يفترض كثير من المبرمجين خطأً أن الشيفرة التالية ستعمل كما هو مخطط لها:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4058_7" style="">
<span class="typ">float</span><span class="pln"> total </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">for</span><span class="pln"> </span><span class="pun">(</span><span class="typ">float</span><span class="pln"> a </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln"> a </span><span class="pun">!=</span><span class="pln"> </span><span class="lit">2</span><span class="pun">;</span><span class="pln"> a </span><span class="pun">+=</span><span class="pln"> </span><span class="lit">0.01f</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    total </span><span class="pun">+=</span><span class="pln"> a</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	إذ يفترض المبرمج المبتدئ أن تلك الشيفرة ستجمع كل الأعداد الموجودة في النطاق المحصور بين <code>0</code>، <code>0.01</code>، <code>0.02</code>، <code>0.03</code>، … ، <code>1.97</code>، <code>1.98</code>، <code>1.99</code>، للحصول في النهاية على <code>199</code> كنتيجة، وهي الإجابة الصحيحة. لكن لا يحدث ذلك لسببين:
</p>

<ol>
<li>
		لن ينتهي البرنامج أبدًا بهيئته الحالية، لأنّ <code>a</code> لن تساوي أبدًا القيمة <code>2</code>، والحلقة التكرارية لن تنتهي.
	</li>
	<li>
		إذا عدّلنا شرط الحلقة التكرارية وجعلناه <code>a &lt; 2</code>، فإنّ الحلقة التكرارية ستنتهي، لكن الإجمالي سيكون شيئًا غير <code>199</code> التي نريدها، وعلى الأغلب ستحصل على <code>201</code> على الأجهزة المتوافقة مع معيار IEEE754.
	</li>
</ol>
<p>
	سبب حدوث ذلك هو أنّ الأعداد العشرية (Floating Point Numbers) تمثِّل القيم بشكل تقريبي وحسب. كما في المثال التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_8767_9" style="">
<span class="pln">    </span><span class="kwd">double</span><span class="pln"> a </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0.1</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">double</span><span class="pln"> b </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0.2</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">double</span><span class="pln"> c </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0.3</span><span class="pun">;</span><span class="pln">

    </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">a </span><span class="pun">+</span><span class="pln"> b </span><span class="pun">==</span><span class="pln"> c</span><span class="pun">)</span><span class="pln">
        </span><span class="com">// IEEE754 لن يُطبع هذا على الأجهزة المتوافقة مع </span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"This Computer is Magic!"</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">else</span><span class="pln">
        std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"This Computer is pretty normal, all things considered."</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span></pre>

<p>
	برغم أننا كمبرمجين نرى ثلاثة أعداد مكتوبة وفق النظام العشري، إلا أن المصرِّف (Compiler) -والحاسوب الذي يعمل عليه- لا يرى إلا أرقامًا ثنائية، لذا يجب أن تخزَّن تلك الأعداد في صيغ تقريبية غير دقيقة كما في حالة العدد <code>1/3</code> إذ يخزن على الصورة <code>0.3333333333</code> في النظام العشري، وذلك لأن <code>0.1</code> و <code>0.2</code> و <code>0.3</code> تتطلب قسمة تامة على <code>10</code>، وهذا يسير في النظام العشري لكنه مستحيل في النظام الثنائي.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_6452_6" style="">
<span class="pln">    </span><span class="com">// الأعداد العشرية في نظام 64-بت لديها 53 خانة رقمية، بما في ذلك الجزء الصحيح من العدد</span><span class="pln">
    </span><span class="kwd">double</span><span class="pln"> a </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0011111110111001100110011001100110011001100110011001100110011010</span><span class="pun">;</span><span class="pln">

    </span><span class="com">// تمثيل تقريبي للعدد 0.1</span><span class="pln">
    </span><span class="kwd">double</span><span class="pln"> b </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0011111111001001100110011001100110011001100110011001100110011010</span><span class="pun">;</span><span class="pln">

    </span><span class="com">// تمثيل تقريبي للعدد 0.2</span><span class="pln">
    </span><span class="kwd">double</span><span class="pln"> c </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0011111111010011001100110011001100110011001100110011001100110011</span><span class="pun">;</span><span class="pln">

    </span><span class="com">// تمثيل تقريبي للعدد 0.3</span><span class="pln">
    </span><span class="kwd">double</span><span class="pln"> a </span><span class="pun">+</span><span class="pln"> b </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0011111111010011001100110011001100110011001100110011001100110100</span><span class="pun">;</span><span class="pln">
    </span><span class="com">// 0.3 لاحظ أن هذا العدد لا يساوي</span></pre>

<p>
	هذا الدرس جزء من <a data-ss1617022330="1" href="https://academy.hsoub.com/tags/%D8%B3%D9%84%D8%B3%D9%84%D8%A9%20++c%20%D9%84%D9%84%D9%85%D8%AD%D8%AA%D8%B1%D9%81%D9%8A%D9%86/" rel="">سلسلة دروس عن C++‎</a>.
</p>

<p>
	ترجمة -وبتصرّف- للفصل Chapter 4: Floating Point Arithmetic من كتاب <a data-ss1617022330="1" href="https://goalkicker.com/CPlusPlusBook/CPlusPlusNotesForProfessionals.pdf" rel="external nofollow">C++ Notes for Professionals</a>
</p>

<h2>
	اقرأ أيضًا
</h2>

<ul>
<li>
		<a data-ss1617022330="1" href="https://academy.hsoub.com/programming/cpp/%D8%A7%D9%84%D8%AF%D8%B1%D8%B3-5-%D8%A7%D9%84%D8%B9%D9%85%D9%84%D9%8A%D8%A7%D8%AA-%D8%A7%D9%84%D8%A8%D8%AA%D9%91%D9%8A%D9%91%D8%A9-r806/" rel="">الدرس 5: العمليات البتِّيّة (Bit Operators)</a>
	</li>
	<li>
		<a data-ss1617022330="1" href="https://academy.hsoub.com/programming/cpp/%D8%A7%D9%84%D8%AF%D8%B1%D8%B3-3-%D8%A3%D8%B3%D8%A8%D9%82%D9%8A%D8%A9-%D8%A7%D9%84%D8%B9%D9%85%D9%84%D9%8A%D8%A7%D8%AA-r804/" rel="">الدرس 3: أسبقية العمليات</a>
	</li>
</ul>
]]></description><guid isPermaLink="false">805</guid><pubDate>Fri, 07 Feb 2020 18:06:00 +0000</pubDate></item><item><title>&#x623;&#x633;&#x628;&#x642;&#x64A;&#x629; &#x627;&#x644;&#x639;&#x645;&#x644;&#x64A;&#x627;&#x62A; &#x641;&#x64A; ++C</title><link>https://academy.hsoub.com/programming/cpp/%D8%A3%D8%B3%D8%A8%D9%82%D9%8A%D8%A9-%D8%A7%D9%84%D8%B9%D9%85%D9%84%D9%8A%D8%A7%D8%AA-%D9%81%D9%8A-c-r804/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2020_06/3.png.2fa587acc9819c3fb3763368f76ff3cf.png" /></p>

<h2>
	العمليات المنطقية
</h2>

<p>
	العامل المنطقي <code>&amp;&amp;</code> له الأسبقية على <code>||</code>، وذلك يعني أن الأقواس توضع لتقييم ما سيتم تقييمه مع غيره، وتستخدم C++‎ تقييم الدارة القصيرة (short-circuit evaluation) في تقييم <code>&amp;&amp;</code> و <code>||</code> من أجل تجنّب إجراء العمليات غير الضرورية. أيضًا، إذا أعاد الجانب الأيسر من <code>||</code> القيمة <code>true</code>، فلن تكون هناك حاجة إلى تقييم الجانب الأيمن.
</p>

<p>
	في المثال التالي، سنقيّم ثلاثة قيم منطقية بالعامِليْن || و &amp;&amp; من أجل توضيح الأسبقية، لا تعني الأسبقية أن &amp;&amp; ستقيَّم أولًا وإنما توضح أين ستوضع الأقواس:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3748_6" style="">
<span class="com">#include</span><span class="pln"> </span><span class="str">&lt;iostream&gt;</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">&lt;string&gt;</span><span class="pln">

</span><span class="kwd">using</span><span class="pln"> </span><span class="kwd">namespace</span><span class="pln"> std</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">bool</span><span class="pln"> </span><span class="typ">True</span><span class="pun">(</span><span class="pln">string id</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"True"</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> id </span><span class="pun">&lt;&lt;</span><span class="pln"> endl</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="kwd">bool</span><span class="pln"> </span><span class="typ">False</span><span class="pun">(</span><span class="pln">string id</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"False"</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> id </span><span class="pun">&lt;&lt;</span><span class="pln"> endl</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> </span><span class="kwd">false</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="typ">int</span><span class="pln"> main</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">bool</span><span class="pln"> result</span><span class="pun">;</span><span class="pln">

    </span><span class="com">// حالة 1</span><span class="pln">
    result </span><span class="pun">=</span><span class="pln">
        </span><span class="typ">False</span><span class="pun">(</span><span class="str">"A"</span><span class="pun">)</span><span class="pln"> </span><span class="pun">||</span><span class="pln"> </span><span class="typ">False</span><span class="pun">(</span><span class="str">"B"</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&amp;&amp;</span><span class="pln"> </span><span class="typ">False</span><span class="pun">(</span><span class="str">"C"</span><span class="pun">);</span><span class="pln"> 
  		</span><span class="com">// eq. False("A") || (False("B") &amp;&amp; False("C"))</span><span class="pln">
    </span><span class="com">//FalseA</span><span class="pln">
    </span><span class="com">//FalseB</span><span class="pln">


	</span><span class="com">// حالة 2</span><span class="pln">
    result </span><span class="pun">=</span><span class="pln">
        </span><span class="typ">True</span><span class="pun">(</span><span class="str">"A"</span><span class="pun">)</span><span class="pln"> </span><span class="pun">||</span><span class="pln"> </span><span class="typ">False</span><span class="pun">(</span><span class="str">"B"</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&amp;&amp;</span><span class="pln"> </span><span class="typ">False</span><span class="pun">(</span><span class="str">"C"</span><span class="pun">);</span><span class="pln">
                </span><span class="com">// eq. True("A") || (False("B") &amp;&amp; False("C"))</span><span class="pln">
  
    cout </span><span class="pun">&lt;&lt;</span><span class="pln"> result </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">" :====================="</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> endl</span><span class="pun">;</span><span class="pln">
    </span><span class="com">//TrueA</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	في تقييم الدارة القصيرة، يجري تخطي C في الحالة الأولى، فبما أن A خطأ فيجب تقييم الجانب الأيمن من العامِل ||؛ تكون B خطأ أيضًا، لذا ليس هنالك حاجة إلى تقييم  C مهما كان تقييمها سواءً خطأ False أم صحيح True.
</p>

<p>
	في الحالة الثانية، يجري تخطي B و C وفقًا لتقييم الدارة القصيرة، إذ قيمة A هي True صحيحة فلا داع لتقييم الجانب الأيمن من المعامل ||. إن كان للعامِل || أسبقية على &amp;&amp; فإن التقييم المكافئ يكون: (True("A") || False("B")) &amp;&amp; False("C") والذي سيطبع TrueA للجزء الأول الموضوع بين أقواس والذي سيتخطى B فقط آنذاك في تقييم الدارة القصيرة ولكن بوجود العامل &amp;&amp; في الطرف الأيمن من الأقواس، ستكون النتيجة النهائية FalseC. بما أنّ الأقواس موضوعة بشكل مختلف، فإنّ الأجزاء التي ستُقيّم ستكون مختلفة ما يجعل النتيجة النهائية في هذه الحالة هي False، لأن تقييم C هو False.
</p>

<p>
	العاملان <code>AND</code> و <code>OR</code> لهما الأسبقية المعتادة في C++‎، أي أنّ <code>AND</code> تسبق <code>OR</code> دومًا.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1168_9" style="">
<span class="com">// يمكنك القيادة برخصة أجنبية لستِّين يوما</span><span class="pln">
</span><span class="kwd">bool</span><span class="pln"> can_drive </span><span class="pun">=</span><span class="pln"> has_domestic_license </span><span class="pun">||</span><span class="pln"> has_foreign_license </span><span class="pun">&amp;&amp;</span><span class="pln"> num_days </span><span class="pun">&lt;=</span><span class="pln"> </span><span class="lit">60</span><span class="pun">;</span></pre>

<p>
	هذه الشيفرة مكافئة لما يلي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1168_11" style="">
<span class="com">// يمكنك القيادة برخصة أجنبية لستّين يوما</span><span class="pln">
</span><span class="kwd">bool</span><span class="pln"> can_drive </span><span class="pun">=</span><span class="pln"> has_domestic_license </span><span class="pun">||</span><span class="pln"> </span><span class="pun">(</span><span class="pln">has_foreign_license </span><span class="pun">&amp;&amp;</span><span class="pln"> num_days </span><span class="pun">&lt;=</span><span class="pln"> </span><span class="lit">60</span><span class="pun">);</span></pre>

<p>
	لا تؤدي إضافة الأقواس إلى تغيير السلوك، ولكنها تحسّن إمكانية القراءة، وترفع اللُّبس عن نية كاتب الشيفرة.
</p>

<h2>
	العمليات الأحادية
</h2>

<p>
	تُطبَّق العمليات الأحادية على الكائن الذي استُدعيت عليه وسميت أحادية لأن العملية تطبَّق على طرف واحد فقط باستعمال عامل أحادي (Unary Operator)، ولها أسبقية عالية أي تأخذ الأولوية دومًا ضمن المعاملات. عند استخدام العامِل الأحادي بعد الكائن -أي postfix-، فلن يُتَّخذ إجراء إلا بعد تقييم العملية بأكملها، وهذا مفيد في بعض العمليات الحسابية. إليك المثال التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9355_14" style="">
<span class="typ">int</span><span class="pln"> a </span><span class="pun">=</span><span class="pln"> </span><span class="lit">1</span><span class="pun">;</span><span class="pln">
</span><span class="pun">++</span><span class="pln">a</span><span class="pun">;</span><span class="pln">                </span><span class="com">// 2</span><span class="pln">
a</span><span class="pun">--;</span><span class="pln">                </span><span class="com">// 1</span><span class="pln">

</span><span class="typ">int</span><span class="pln"> minusa </span><span class="pun">=</span><span class="pln"> </span><span class="pun">-</span><span class="pln">a</span><span class="pun">;</span><span class="pln">    </span><span class="com">// -1</span><span class="pln">
</span><span class="kwd">bool</span><span class="pln"> b </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">;</span><span class="pln">
</span><span class="pun">!</span><span class="pln">b</span><span class="pun">;</span><span class="pln">                 </span><span class="com">// true</span><span class="pln">

a </span><span class="pun">=</span><span class="pln"> </span><span class="lit">4</span><span class="pun">;</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> c </span><span class="pun">=</span><span class="pln"> a</span><span class="pun">++/</span><span class="lit">2</span><span class="pun">;</span><span class="pln">      </span><span class="com">// 4 / 2 = 2</span><span class="pln">
cout </span><span class="pun">&lt;&lt;</span><span class="pln"> a </span><span class="pun">&lt;&lt;</span><span class="pln"> endl</span><span class="pun">;</span><span class="pln">  </span><span class="com">// 5</span><span class="pln">

</span><span class="typ">int</span><span class="pln"> d </span><span class="pun">=</span><span class="pln"> </span><span class="pun">++</span><span class="pln">a </span><span class="pun">/</span><span class="pln"> </span><span class="lit">2</span><span class="pun">;</span><span class="pln">    </span><span class="com">// 6 / 2 = 3</span><span class="pln">

</span><span class="typ">int</span><span class="pln"> arr</span><span class="pun">[</span><span class="lit">4</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln">    </span><span class="pun">{</span><span class="lit">1</span><span class="pun">,</span><span class="lit">2</span><span class="pun">,</span><span class="lit">3</span><span class="pun">,</span><span class="lit">4</span><span class="pun">};</span></pre>

<p>
	إليك مثال آخر أكثر تتعقيدًا حول تطبيق عملية أحادية باستعمال العامل ++ على المؤشرات:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9355_18" style="">
<span class="typ">int</span><span class="pln"> arr</span><span class="pun">[</span><span class="lit">4</span><span class="pun">]</span><span class="pln"> </span><span class="pun">=</span><span class="pln">    </span><span class="pun">{</span><span class="lit">1</span><span class="pun">,</span><span class="lit">2</span><span class="pun">,</span><span class="lit">3</span><span class="pun">,</span><span class="lit">4</span><span class="pun">};</span><span class="pln">

</span><span class="typ">int</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> ptr1 </span><span class="pun">=</span><span class="pln"> </span><span class="pun">&amp;</span><span class="pln"> arr</span><span class="pun">[</span><span class="lit">0</span><span class="pun">];</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> ptr2 </span><span class="pun">=</span><span class="pln"> ptr1</span><span class="pun">++;</span><span class="pln">

std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> ptr1</span><span class="pun">++</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln"> </span><span class="com">// 2</span><span class="pln">

</span><span class="com">// قبل زيادته arr[0] الحصول على قيمة العنصر</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> e </span><span class="pun">=</span><span class="pln"> arr</span><span class="pun">[</span><span class="lit">0</span><span class="pun">]++;</span><span class="pln">      

std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> e </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">        </span><span class="com">// 1</span><span class="pln">
std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> ptr2 </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">   </span><span class="com">// 2</span></pre>

<p>
	يشير المؤشر ptr1 إلى عنوان [arr[0 والتي تخزن القيمة 1 بينما يشير المؤشر ptr2 إلى المؤشر prt1 ثم يزيد من قيمة الأخير مقدار 1 ليشير بذلك إلى العنصر [arr[1.
</p>

<h2>
	العمليات الحسابية
</h2>

<p>
	العمليات الحسابية في C++‎ لها نفس الأسبقية التي لها في الرياضيات. فعمليتا الضرب والقسمة لهما تجميع يساري (left associativity) -بمعنى أنهما تُقيَّمان من اليسار إلى اليمين-، ولهما أسبقية أعلى من الجمع والطرح، واللتان لهما تجميع يساري كذلك. كما يمكننا أيضًا التحكم في أسبقية التعابير باستخدام الأقواس <code>()</code> كما نفعل في الرياضيات العادية. إليك المثال التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9355_20" style="">
<span class="com">// 4 pi R^3 - 4 pi r^3 = حجم السطح الكروي</span><span class="pln">
</span><span class="kwd">double</span><span class="pln"> vol </span><span class="pun">=</span><span class="pln"> </span><span class="lit">4.0</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> pi </span><span class="pun">*</span><span class="pln"> R </span><span class="pun">*</span><span class="pln"> R </span><span class="pun">*</span><span class="pln"> R </span><span class="pun">/</span><span class="pln"> </span><span class="lit">3.0</span><span class="pln"> </span><span class="pun">-</span><span class="pln"> </span><span class="lit">4.0</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> pi </span><span class="pun">*</span><span class="pln"> r </span><span class="pun">*</span><span class="pln"> r </span><span class="pun">*</span><span class="pln"> r </span><span class="pun">/</span><span class="pln"> </span><span class="lit">3.0</span><span class="pun">;</span><span class="pln">

</span><span class="com">// الإضافة</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> a </span><span class="pun">=</span><span class="pln"> </span><span class="lit">2</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="lit">4</span><span class="pln"> </span><span class="pun">/</span><span class="pln"> </span><span class="lit">2</span><span class="pun">;</span><span class="pln">          </span><span class="com">// =    2+(4/2) = 4</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> b </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="lit">3</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="lit">3</span><span class="pun">)</span><span class="pln"> </span><span class="pun">/</span><span class="pln"> </span><span class="lit">2</span><span class="pun">;</span><span class="pln">        </span><span class="com">// =    (3+3)/2 = 3</span><span class="pln">

</span><span class="com">// مع الضرب</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> c </span><span class="pun">=</span><span class="pln"> </span><span class="lit">3</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="lit">4</span><span class="pln"> </span><span class="pun">/</span><span class="pln"> </span><span class="lit">2</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> </span><span class="lit">6</span><span class="pun">;</span><span class="pln">      </span><span class="com">// =    3+((4/2)*6) = 15</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> d </span><span class="pun">=</span><span class="pln"> </span><span class="lit">3</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> </span><span class="pun">(</span><span class="lit">3</span><span class="pln"> </span><span class="pun">+</span><span class="pln"> </span><span class="lit">6</span><span class="pun">)</span><span class="pln"> </span><span class="pun">/</span><span class="pln"> </span><span class="lit">9</span><span class="pun">;</span><span class="pln">    </span><span class="com">// =    (3*(3+6))/9 = 3</span><span class="pln">

</span><span class="com">// القسمة والباقي  </span><span class="pln">
</span><span class="typ">int</span><span class="pln"> g </span><span class="pun">=</span><span class="pln"> </span><span class="lit">3</span><span class="pln"> </span><span class="pun">-</span><span class="pln"> </span><span class="lit">3</span><span class="pln"> </span><span class="pun">%</span><span class="pln"> </span><span class="lit">1</span><span class="pun">;</span><span class="pln">          </span><span class="com">// =    3 % 1 = 0  3 - 0 = 3</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> h </span><span class="pun">=</span><span class="pln"> </span><span class="lit">3</span><span class="pln"> </span><span class="pun">-</span><span class="pln"> </span><span class="pun">(</span><span class="lit">3</span><span class="pln"> </span><span class="pun">%</span><span class="pln"> </span><span class="lit">1</span><span class="pun">);</span><span class="pln">        </span><span class="com">// =    3 % 1 = 0  3 - 0 = 3</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> i </span><span class="pun">=</span><span class="pln"> </span><span class="lit">3</span><span class="pln"> </span><span class="pun">-</span><span class="pln"> </span><span class="lit">3</span><span class="pln"> </span><span class="pun">/</span><span class="pln"> </span><span class="lit">1</span><span class="pln"> </span><span class="pun">%</span><span class="pln"> </span><span class="lit">3</span><span class="pun">;</span><span class="pln">      </span><span class="com">// =    3 / 1 = 3  3 % 3 = 0  3 - 0 = 3</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> l </span><span class="pun">=</span><span class="pln"> </span><span class="lit">3</span><span class="pln"> </span><span class="pun">-</span><span class="pln"> </span><span class="pun">(</span><span class="lit">3</span><span class="pln"> </span><span class="pun">/</span><span class="pln"> </span><span class="lit">1</span><span class="pun">)</span><span class="pln"> </span><span class="pun">%</span><span class="pln"> </span><span class="lit">3</span><span class="pun">;</span><span class="pln">    </span><span class="com">// =    3 / 1 = 3  3 % 3 = 0  3 - 0 = 3</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> m </span><span class="pun">=</span><span class="pln"> </span><span class="lit">3</span><span class="pln"> </span><span class="pun">-</span><span class="pln"> </span><span class="pun">(</span><span class="lit">3</span><span class="pln"> </span><span class="pun">/</span><span class="pln"> </span><span class="pun">(</span><span class="lit">1</span><span class="pln"> </span><span class="pun">%</span><span class="pln"> </span><span class="lit">3</span><span class="pun">));</span><span class="pln">  </span><span class="com">// =    1 % 3 = 1  3 / 1 = 3  3 - 3 = 0</span></pre>

<p>
	هذا الدرس جزء من <a data-ss1617022326="1" href="https://academy.hsoub.com/tags/%D8%B3%D9%84%D8%B3%D9%84%D8%A9%20++c%20%D9%84%D9%84%D9%85%D8%AD%D8%AA%D8%B1%D9%81%D9%8A%D9%86/" rel="">سلسلة دروس عن C++‎</a>.
</p>

<p>
	ترجمة -وبتصرّف- للفصل Chapter 3: operator precedence من كتاب <a data-ss1617022326="1" href="https://goalkicker.com/CPlusPlusBook/CPlusPlusNotesForProfessionals.pdf" rel="external nofollow">C++ Notes for Professionals</a>
</p>

<h2>
	اقرأ أيضا
</h2>

<ul>
<li>
		<a data-ss1617022326="1" href="https://academy.hsoub.com/programming/cpp/%D8%A7%D9%84%D8%AF%D8%B1%D8%B3-4-%D8%AD%D8%B3%D8%A7%D8%A8%D9%8A%D9%91%D8%A7%D8%AA-%D8%A7%D9%84%D8%A3%D8%B9%D8%AF%D8%A7%D8%AF-%D8%A7%D9%84%D8%B9%D8%B4%D8%B1%D9%8A%D8%A9-r805/" rel="">الدرس 4: حسابيات الأعداد العشرية</a>
	</li>
	<li>
		<a data-ss1617022326="1" href="https://academy.hsoub.com/programming/cpp/%D8%A7%D9%84%D8%AF%D8%B1%D8%B3-2-%D8%A7%D9%84%D9%82%D9%8A%D9%85-%D9%85%D8%B5%D9%86%D9%91%D9%8E%D9%81%D8%A9-%D8%A7%D9%84%D9%86%D9%88%D8%B9-r803/" rel="">الدرس 2: القيم مصنَّفة النوع</a>
	</li>
</ul>
]]></description><guid isPermaLink="false">804</guid><pubDate>Wed, 05 Feb 2020 08:06:00 +0000</pubDate></item><item><title>&#x627;&#x644;&#x642;&#x64A;&#x645; &#x645;&#x635;&#x646;&#x651;&#x64E;&#x641;&#x629; &#x627;&#x644;&#x646;&#x648;&#x639; &#x641;&#x64A; ++C</title><link>https://academy.hsoub.com/programming/cpp/%D8%A7%D9%84%D9%82%D9%8A%D9%85-%D9%85%D8%B5%D9%86%D9%91%D9%8E%D9%81%D8%A9-%D8%A7%D9%84%D9%86%D9%88%D8%B9-%D9%81%D9%8A-c-r803/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2020_06/2.png.a59b6235c05e01b6fea11984fc54c64e.png" /></p>

<p>
	القيم مصنَّفة النوع (Literals) هي عبارات تدل على ثابت تشير صياغته المحرفية إلى نوعه وقيمته، فمثلًا <code>42</code> هي قيمة مصنَّفة النوع بينما <code>x</code> ليست كذلك لأنك تحتاج إلى أن تنظر إلى تصريحها (declaration) لتعرف نوعها وتطالع الأسطر السابقة من الشيفرة لتعرف قيمتها. غير أن C++11 أتاحت للمستخدم إضافة قيم مصنَّفة النوع (User-Defined Literals)، وتُستخدم كاختصار لاستدعاءات الدوال.
</p>

<p>
	سنستَعرض في هذا الدرس بعض القيم مصنَّفة النوع في C++‎، بدءًا بالقيمة <code>this</code>، ثم نستعرض بقية القيم في الأقسام التالية.
</p>

<h2>
	الكلمة المفتاحية <code>this</code>
</h2>

<p>
	تشير الكلمة المفتاحية <code>this</code> داخل دالة تابعة (member function) إلى نسخة من الصنف التي استدعيّت الدالة عليها، ولا يمكن استخدامها -أي <code>this</code>- في دالة تابعة ساكنة (static member function).
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_3667_6" style="">
<span class="kwd">struct</span><span class="pln"> S </span><span class="pun">{</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> x</span><span class="pun">;</span><span class="pln">
    S </span><span class="pun">&amp;</span><span class="pln"> </span><span class="kwd">operator</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> S </span><span class="pun">&amp;</span><span class="pln"> other</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
        x </span><span class="pun">=</span><span class="pln"> other</span><span class="pun">.</span><span class="pln">x</span><span class="pun">;</span><span class="pln">
      
        </span><span class="com">// تعيد مرجعًا إلى الكائن الذي أسندَت إليه</span><span class="pln">
        </span><span class="kwd">return</span><span class="pln"> </span><span class="pun">*</span><span class="kwd">this</span><span class="pun">;</span><span class="pln">
    </span><span class="pun">}</span><span class="pln">
</span><span class="pun">};</span></pre>

<p>
	يعتمد نوع <code>‎this‎</code> على خاصية التأهيل الخاص بالتابع -سواء التأهيل المتطاير volatile أو الثابت constant- (بالإنجليزية اختصارًا: cv-qualiﬁcation). فمثلًا، إن كان التابع <code>‎X::f‎</code> ثابتًا (<code>‎const‎</code>)، فإنّ نوع <code>‎this‎</code> داخل <code>‎f‎</code> سيكون مؤشرًا ثابتًا إلى <code>‎X‎</code> (أي <code>‎‎‎const X*‎‎</code>)، لذلك لا يمكن استخدام <code>‎this‎</code> لتعديل الحقول غير الساكنة (non-static data members) من داخل دالة <code>const</code> تابعة. وبالمثل، يكتسب <code>‎this‎</code> التأهيل المتطاير (volatile qualification) من الدالة التي يظهر فيها. <strong>الإصدار ≥ C++11</strong>
</p>

<p>
	يمكن أيضًا استخدام <code>‎this‎</code> في المُهيِّئ المعقوص (brace-or-equal-initializer) للحقول غير الساكنة.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1572_9" style="">
<span class="kwd">struct</span><span class="pln"> S</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">struct</span><span class="pln"> T </span><span class="pun">{</span><span class="pln">
    T</span><span class="pun">(</span><span class="kwd">const</span><span class="pln"> S </span><span class="pun">*</span><span class="pln"> s</span><span class="pun">);</span><span class="pln">
    </span><span class="com">// ...</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
</span><span class="kwd">struct</span><span class="pln"> S </span><span class="pun">{</span><span class="pln">
    </span><span class="com">// ...</span><span class="pln">
    T t </span><span class="pun">{</span><span class="pln">
        </span><span class="kwd">this</span><span class="pln">
    </span><span class="pun">};</span><span class="pln">
</span><span class="pun">};</span></pre>

<p>
	<code>‎this‎</code> عبارة عن قيمة يمينيّة (rvalue)، أي أنّها تعبير لا يمكن أن يكون إلا في الطرف الأيمن من أيّ عملية إسناد (assignment)، لذلك لا يمكن إسناد قيمة لها.
</p>

<h2>
	الأعداد الصحيحة قيمةً ونوعًا (Integer literal)
</h2>

<p>
	تأخذ صياغة العدد الصحيح أحد الأشكال التالية:
</p>

<ul>
<li>
		نوع عشري (decimal-literal): وهو عدد مؤلف من رقم عشري يخالف الصفر (1، 2، 3، 4، 5، 6، 7، 8، 9)، متبوعًا برقم عشريّ واحد أو أكثر (0، 1، 2، 3، 4، 5، 6، 7، 8، 9)، مثلًا:
	</li>
</ul>
<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1572_11" style="">
<span class="typ">int</span><span class="pln"> d </span><span class="pun">=</span><span class="pln"> </span><span class="lit">42</span><span class="pun">;‎</span></pre>

<ul>
<li>
		نوع ثماني (octal-literal): وهو عدد يبدأ بالرقم صفر (0) متبوعًا برقم ثُمانيّ (octal) واحد أو أكثر (0، 1، 2، 3، 4، 5، 6، 7)، مثلًا:
	</li>
</ul>
<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1572_13" style="">
<span class="typ">int</span><span class="pln"> o </span><span class="pun">=</span><span class="pln"> </span><span class="lit">052</span><span class="pun">;</span></pre>

<ul>
<li>
		نوع ست عشري (hex-literal): وهو تسلسل الأحرف 0x أو 0X متبوعًا برقم واحد أو أكثر من الأرقام الست عشرية (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, a, A, b, B, c, C, d, D, e, E, f, F)، مثلًا:
	</li>
</ul>
<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1572_15" style="">
<span class="typ">int</span><span class="pln"> x </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0x2a</span><span class="pun">;</span><span class="pln"> 
</span><span class="typ">int</span><span class="pln"> X </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0X2A</span><span class="pun">;‎</span></pre>

<ul>
<li>
		نوع ثنائي (binary-literal): (منذ C ++ 14) هو تسلسل الأحرف 0b أو 0B متبوعًا برقم ثنائي واحد أو أكثر (0، 1)، مثلا:
	</li>
</ul>
<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1572_17" style="">
<span class="typ">int</span><span class="pln"> b </span><span class="pun">=</span><span class="pln"> </span><span class="lit">0b101010</span><span class="pun">;‎</span></pre>

<ul>
<li>
		الأعداد الصحيحة الملحوقة غير المؤشّرة (unsigned-suffix)، قد تحتوي على أحد أو كلا الأمرين التاليين -قد يظهرا بدون ترتيب محدد في حالة وجودهما معًا:
		<ul>
<li>
				الأعداد الملحوقة غير المُؤشرة (unsigned-suffix): هي أعداد ملحوقة بالحرف u أو U، مثلا:
			</li>
		</ul>
</li>
</ul>
<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1572_19" style="">
<span class="kwd">unsigned</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> u_1 </span><span class="pun">=</span><span class="pln"> </span><span class="lit">42u</span><span class="pun">;‎</span></pre>

<ul style="margin-right: 40px;">
<li>
		الأعداد الملحوقة الطويلة (long-suffix): هي أعداد ملحوقة بالحرف l أو L، أو الأعداد الملحوقة الطويلة المزدوجة (long-long-suffix)، وهي أعداد ملحوقة بالحرفين ll أو الحرفين LL (منذ C++11‎)
	</li>
</ul>
<p>
	تأخذ المتغيرات التالية نفس القيمة:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1572_21" style="">
<span class="kwd">unsigned</span><span class="pln"> </span><span class="kwd">long</span><span class="pln"> </span><span class="kwd">long</span><span class="pln"> l1 </span><span class="pun">=</span><span class="pln"> </span><span class="lit">18446744073709550592ull</span><span class="pun">;</span><span class="pln"> </span><span class="com">// C++11</span><span class="pln">
</span><span class="kwd">unsigned</span><span class="pln"> </span><span class="kwd">long</span><span class="pln"> </span><span class="kwd">long</span><span class="pln"> l2 </span><span class="pun">=</span><span class="pln"> </span><span class="lit">18</span><span class="str">'446'</span><span class="lit">744</span><span class="str">'073'</span><span class="lit">709</span><span class="str">'550'</span><span class="lit">592llu</span><span class="pun">;</span><span class="pln"> </span><span class="com">// C++14</span><span class="pln">
</span><span class="kwd">unsigned</span><span class="pln"> </span><span class="kwd">long</span><span class="pln"> </span><span class="kwd">long</span><span class="pln"> l3 </span><span class="pun">=</span><span class="pln"> </span><span class="lit">1844</span><span class="str">'6744'</span><span class="lit">0737</span><span class="str">'0955'</span><span class="lit">0592uLL</span><span class="pun">;</span><span class="pln"> </span><span class="com">// C++14</span><span class="pln">
</span><span class="kwd">unsigned</span><span class="pln"> </span><span class="kwd">long</span><span class="pln"> </span><span class="kwd">long</span><span class="pln"> l4 </span><span class="pun">=</span><span class="pln"> </span><span class="lit">184467</span><span class="str">'440737'</span><span class="lit">0</span><span class="str">'95505'</span><span class="lit">92LLU</span><span class="pun">;</span><span class="pln"> </span><span class="com">// C++14</span></pre>

<h3>
	<strong>ملاحظات</strong>
</h3>

<p>
	الأحرف الموجودة في الأعداد الصحيحة غير حساسة للحالة (case-insensitive): فتمثل الصيغتان 0xDeAdBaBeU و 0XdeadBABEu نفس العدد (الاستثناء الوحيد هو الأعداد الملحوقة الطويلة المزدوجة، والتي يمكن أن تكون إما ll أو LL، ولكن ليس lL أو Ll).
</p>

<p>
	لا توجد صياغة لأعداد سالبة، فمثلًا تطبق تعابير مثل <code>‎-1</code> عامل السالب الأحادي (unary minus operator) على القيمة المُمثّلة بالقيمة مصنفَّة النوع (Literal)، والتي قد تتضمن تحويلات ضمنية للنوع (implicit type conversions).
</p>

<p>
	في إصدارات C السابقة للإصدار C99 (ولكن ليس في C++‎)، يُسمح للقيم العشرية غير الملحوقة (unsuﬃxed decimal) من غير النوع <code>long int</code> أن تكون من النوع <code>unsigned long int </code>(عدد صحيح طويل عديم الإشارة).
</p>

<p>
	تتصرف جميع الثوابت الصحيحة المؤشَّرة (signed integer constants) عند استخدامها في التعبيرات الشرطية -مثل <code>‎#if</code> أو <code>‎#elif</code>- كما لو كانت من النوع <code>std::intmax_t</code>، فيما تتصرف الثوابت الصحيحة غير المؤشرة كما لو كانت من النوع <code>std::uintmax_t</code>.
</p>

<h2>
	القيم المنطقية
</h2>

<h3>
	الكلمة المفتاحية <code>true</code>
</h3>

<p>
	<code>true</code> هي كلمة مفتاحية تمثّل إحدى القيمتين المنطقيّتين المُمكنَتين للنوع <code>‎bool‎</code>.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1572_23" style="">
<span class="kwd">bool</span><span class="pln"> ok </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(!</span><span class="pln">f</span><span class="pun">())</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    ok </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">false</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">goto</span><span class="pln"> end</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<h3>
	الكلمة المفتاحية <code>false</code>
</h3>

<p>
	<code>false</code> هي كلمة مفتاحية تمثل إحدى القيمتين المنطقيّتين المُمكنتين للنوع <code>‎bool‎</code>.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1572_25" style="">
<span class="kwd">bool</span><span class="pln"> ok </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(!</span><span class="pln">f</span><span class="pun">())</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    ok </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">false</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">goto</span><span class="pln"> end</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<h2>
	الكلمة المفتاحية <code>nullptr</code>
</h2>

<p>
	<strong>الإصدار ≥ C++ 11</strong>
</p>

<p>
	<code>nullptr</code> هي كلمة مفتاحية تمثل مؤشرًا ثابتًا فارغًا (null pointer constant)، ويمكن تحويلها إلى أيّ نوع من المؤشرات (Pointers) أو المؤشرات إلى الأعضاء (pointer-to-member)، وتعيد مؤشرًا فارغًا يشير إلى النوع الناتج.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1572_27" style="">
<span class="typ">Widget</span><span class="pun">*</span><span class="pln"> p </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Widget</span><span class="pun">();</span><span class="pln">
</span><span class="kwd">delete</span><span class="pln"> p</span><span class="pun">;</span><span class="pln">
p </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">nullptr</span><span class="pun">;</span><span class="pln"> </span><span class="com">// تفريغ المؤشر بعد الحذف</span></pre>

<p>
	لاحظ أنّ <code>‎nullptr‎</code> ليست مؤشرًا بحد ذاتها، وإنّما هي نوع أساسي معروف باسم <code>‎std::nullptr_t‎</code>.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_1572_29" style="">
<span class="kwd">void</span><span class="pln"> f</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> p</span><span class="pun">);</span><span class="pln">
</span><span class="kwd">template</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> T </span><span class="pun">&gt;</span><span class="pln">
    </span><span class="kwd">void</span><span class="pln"> g</span><span class="pun">(</span><span class="pln">T </span><span class="pun">*</span><span class="pln"> p</span><span class="pun">);</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> h</span><span class="pun">(</span><span class="pln">std</span><span class="pun">::</span><span class="typ">nullptr_t</span><span class="pln"> p</span><span class="pun">);</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> main</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    f</span><span class="pun">(</span><span class="kwd">nullptr</span><span class="pun">);</span><span class="pln"> </span><span class="com">// ok</span><span class="pln">
    g</span><span class="pun">(</span><span class="kwd">nullptr</span><span class="pun">);</span><span class="pln"> </span><span class="com">// error</span><span class="pln">
    h</span><span class="pun">(</span><span class="kwd">nullptr</span><span class="pun">);</span><span class="pln"> </span><span class="com">// ok</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	هذا الدرس جزء من <a data-ss1617022302="1" href="https://academy.hsoub.com/tags/%D8%B3%D9%84%D8%B3%D9%84%D8%A9%20++c%20%D9%84%D9%84%D9%85%D8%AD%D8%AA%D8%B1%D9%81%D9%8A%D9%86/" rel="">سلسلة دروس عن C++‎</a>.
</p>

<p>
	ترجمة -وبتصرّف- للفصل Chapter 2: Literals من كتاب <a data-ss1617022302="1" href="https://goalkicker.com/CPlusPlusBook/CPlusPlusNotesForProfessionals.pdf" rel="external nofollow">C++ Notes for Professionals</a>
</p>

<h2>
	اقرأ أيضا
</h2>

<ul>
<li>
		<a data-ss1617022302="1" href="https://academy.hsoub.com/programming/cpp/%D8%A7%D9%84%D8%AF%D8%B1%D8%B3-3-%D8%A3%D8%B3%D8%A8%D9%82%D9%8A%D8%A9-%D8%A7%D9%84%D8%B9%D9%85%D9%84%D9%8A%D8%A7%D8%AA-r804/" rel="">الدرس 3: أسبقية العمليات</a>
	</li>
	<li>
		<a data-ss1617022302="1" href="https://academy.hsoub.com/programming/cpp/%D8%A7%D9%84%D8%AF%D8%B1%D8%B3-1-%D9%85%D8%AF%D8%AE%D9%84-%D8%A5%D9%84%D9%89-c-r802/" rel="">الدرس 1: مدخل إلى C++‎</a>
	</li>
</ul>
]]></description><guid isPermaLink="false">803</guid><pubDate>Mon, 03 Feb 2020 08:05:00 +0000</pubDate></item><item><title>&#x645;&#x62F;&#x62E;&#x644; &#x625;&#x644;&#x649; ++C</title><link>https://academy.hsoub.com/programming/cpp/%D9%85%D8%AF%D8%AE%D9%84-%D8%A5%D9%84%D9%89-c-r802/</link><description><![CDATA[
<p><img src="https://academy.hsoub.com/uploads/monthly_2020_06/1.png.d69c333f2624063ca15e3cbc705e9911.png" /></p>

<h2>
	مرحبا بالعالم
</h2>

<p>
	يطبع البرنامج التالي العبارة <code>مرحبًا بالعالم!</code> في مجرى الخرج القياسي (standard output stream):
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_10000_8" style="">
<span class="com">#include</span><span class="pln"> </span><span class="str">&lt;iostream&gt;</span><span class="pln">

</span><span class="typ">int</span><span class="pln"> main</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"مرحبا بالعالم!"</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	يمكنك رؤية التجربة الحية على <a data-ss1617022298="1" href="http://coliru.stacked-crooked.com/a/bb404260969e0b2c" rel="external nofollow">Coliru</a>.
</p>

<h3>
	تحليل البرنامج
</h3>

<p>
	لنحلل كل جزء من شيفرة البرنامج بالتفصيل:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9425_8" style="">
<span class="com">#include</span><span class="pln"> </span><span class="str">&lt;iostream&gt;</span></pre>

<p>
	هو <strong>موجّه معالجة مسبقة</strong> (preprocessor directive)، ويتضمن محتوى <code>iostream</code>، وهي ترويسة ملف C++‎ القياسي (standard C++ header file).
</p>

<p>
	<code>الكلمة iostream</code> هي ترويسة ملف مكتبة قياسية (standard library header file)، وتحتوي على تعريفات مُجريَا الدخل والخرج القياسيين (standard input and output streams). هذه التعريفات مُتضمنة في فضاء الاسم <code>std</code>، كما هو موضح أدناه.
</p>

<p>
	يوفر مُجريا الدخل/الخرج القياسيين (I/O) طريقة للبرامج يمكنه عبرها جلب مدخلات من مخرجات خاصة بنظام خارجي، والذي يكون طرفية في العادة.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9425_13" style="">
<span class="typ">int</span><span class="pln"> main</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="pun">...</span><span class="pln"> </span><span class="pun">}</span></pre>

<p>
	تُعرِّف هذه الشيفرة دالة جديدة باسم <code>main</code> تستدعى عند تنفيذ البرنامج. يجب أن تكون هناك دالة <code>main</code> واحدة لكل برنامج C++‎، ويجب أن تعيد دائمًا عددًا من النوع <code>int</code>. يمثل <code>int</code> نوع القيمة التي تعيدها الدالة والتي تمثل رمز الخروج (exit code) الخاص بالدالة <code>main</code>.
</p>

<p>
	البرامج ذات رمز الخروج المساوي للقيمة <code>0</code> أو <code>EXIT_SUCCESS</code> تُعد ناجحة من قبل النظام الذي ينفّذ ذلك البرنامج. ترتبط كل رموز الخروج الأخرى بأخطاء تحددها هي.
</p>

<p>
	في حال عدم استخدام التعليمة <code>return</code>، ستعيد الدالة <code>main</code> (وبالتالي البرنامج نفسه) القيمة <code>0</code> افتراضيًّا. في هذا المثال لا نحتاج إلى كتابة <code>;return 0</code>.
</p>

<p>
	جميع الدوال الأخرى، باستثناء تلك التي تُعيد النوع <code>void</code>، يجب أن تُعيد قيمة بشكل صريح من النوع الذي يُفترض أن تعيده، أو لا ينبغي أن تعيد أي قيمة على الإطلاق.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9425_16" style="">
<span class="pln">std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"مرحبا بالعالم!"</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> std</span><span class="pun">::</span><span class="pln">endl</span><span class="pun">;</span></pre>

<p>
	تطبع هذه التعليمة السلسلة النصية "مرحبا بالعالم!" في مجرى الخرج القياسي، وتتألف من الأجزاء التالية:
</p>

<ul>
<li>
		<strong><code>std</code></strong>: هي فضاء اسم، و <code>::</code> هو عامل تحليل النطاق (scope resolution operator) الذي يسمح بالبحث عن الكائنات بأسمائها ضمن فضاء الاسم. هناك العديد من فضاءات الاسم. هنا نستخدم <code>::</code> لإظهار أننا نريد استخدام <code>cout</code> من فضاء الاسم <code>std</code>. لمزيد من المعلومات، ارجع إلى المقال <a data-ss1617022298="1" href="https://docs.microsoft.com/en-us/cpp/cpp/scope-resolution-operator?view=vs-2019" rel="external nofollow">Scope Resolution Operator</a> في توثيق ميكروسوفت.
	</li>
	<li>
		<strong><code>std::cout</code></strong>: هو كائن <strong>مجرى الخرج القياسي </strong>(standard output)، وهو مُعرّف في <code>iostream</code>، ويُطبع أيّ شيء يُمرَّر إليه في مجرى الخرج القياسي (<code>stdout</code>).
	</li>
	<li>
		<strong><code>&gt;&gt;</code></strong>: هي، في هذا السياق، <strong>عامل الإدراج</strong> (stream insertion operator)، ويُسمى كذلك لأنه يدرج كائنًا في كائن المجرى (stream object). تُعرِّف المكتبة القياسية العامل <code>&gt;&gt;</code> لإدراج بعض أنواع البيانات في مجاري الخرج. تدرج التعليمة <code>stream &lt;&lt; content</code> المحتوى <code>content</code> في المجرى <code>stream</code> ثم تعيد المجرى نفسه بعد تحديثه. يسمح ذلك بإجراء الإدراجات المتسلسلة، مثلًا، تطبع التعليمة std::cout &lt;&lt; "Foo" &lt;&lt; " Bar";<code>‎</code> السلسة النصية "Foo Bar" في سطر الأوامر.
	</li>
	<li>
		<strong>"مرحبا بالعالم!"</strong>: هي سلسلة نصية حرفية (character string literal). عامل الإدراج الخاص بالسلاسل النصية مُعرّف في الملف <code>iostream</code>.
	</li>
	<li>
		<strong><code><a data-ss1617022298="1" href="https://en.cppreference.com/w/cpp/io/manip/endl" rel="external nofollow">std::endl</a></code></strong>: هو كائن خاص لمعالجة مجرى I/O، وهو مُعرّف في الملف <code>iostream</code>. إنّ إدراج معالج في مجرى ما يغير حالة ذلك المجرى. يقوم معالج المجرى <code>std::endl</code> بعملين: أولًا، يدرج محرف نهاية السطر (end-of-line character)، ثم ينقل البيانات (flushes) الموجودة في المخزن المؤقت (stream buffer) الخاص بالمجرى لجعل النص يظهر في سطر الأوامر. يضمن هذا أنّ البيانات المُدرجة في المجرى ستظهر بالفعل في وحدة التحكم. (تُخزنّ بيانات المجرى عادة في مخزن مؤقت، ثم تُنقَل على دفعات، إلا إذا أمرت بنقلها فوريًا.)
	</li>
</ul>
<p>
	هناك طريقة بديلة تُجنِّب نقل البيانات من المخزن المؤقت، وهي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9425_20" style="">
<span class="pln">std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"Hello World!\n"</span><span class="pun">;</span><span class="pln"> 
</span><span class="com">// سطرًا جديدًا \n يمثل</span></pre>

<ul>
<li>
		<code>الفاصلة المنقوطة <strong>;</strong></code>: تُخطر الفاصلة المنقوطة (<code>;</code>) المُصرّف (compiler) بأنّ التعليمة البرمجية قد انتهت. تتطلب كل عبارات C++‎ وتعريفات الأصناف استخدام فاصلة منقوطة في النهاية.
	</li>
</ul>
<h2>
	التعليقات
</h2>

<p>
	التعليقات هي جزء من الشيفرة يتجاهلها مصرف C++‎. تُستخدم التعليقات لتوضيح بعض الجوانب التي قد تكون غامضة بخصوص تصميم أو طريقة عمل البرنامج.
</p>

<p>
	هناك نوعان من التعليقات في C++‎:
</p>

<h3>
	التعليقات السطرية (Single-Line Comments)
</h3>

<p>
	تجعل الشرطتان المائِلتان <code>//</code> النص الذي يليها وحتى بداية السطر الجديد تعليقًا:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_10000_12" style="">
<span class="typ">int</span><span class="pln"> main</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="com">// هذا تعليق سطري</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> a</span><span class="pun">;</span><span class="pln"> </span><span class="com">// هذا تعليق سطري كذلك</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> i</span><span class="pun">;</span><span class="pln"> </span><span class="com">// هذا أيضا تعليق سطري</span><span class="pln">
</span><span class="pun">}</span></pre>

<h3>
	التعليقات الكُتلية (Block Comments)
</h3>

<p>
	يُستخدَم المحرفان <code>‎/*‎</code> للإعلان عن بداية تعليق كتلي، فيما يُستخدَم المحرفان <code>‎*/‎</code> للإعلان عن نهاية التعليق. يُفسَّر النص الموجود بين العبارتين على أنه تعليق، حتى لو كان النص الموجود بينهما شيفرة C++‎ صالحة. يسمى هذا النوع من التعليقات عادة تعليقات "C-style"، لأنّ صياغة هذ النوع من التعليقات موروثة من سلف C++‎، أي اللغة C:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_10000_14" style="">
<span class="typ">int</span><span class="pln"> main</span><span class="pun">()</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
    </span><span class="com">/*
     *  هذا تعليق كتلي
     */</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> a</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	يمكنك كتابة ما تشاء في التعليقات الكتلية لكن عندما يجد المصرّف رمز نهاية التعليق<code>‎*/‎</code>، فإنه ينهي التعليق الكتلي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9425_24" style="">
<span class="typ">int</span><span class="pln"> main</span><span class="pun">()</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
</span><span class="com">/* تعليق كتلي يمتد 
* على عدة أسطر 
* وينتهي في السطر التالي
*/</span><span class="pln"> 
  
</span><span class="typ">int</span><span class="pln"> a</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	يمكن أيضًا أن تبدأ التعليقاتُ الكتلية وتنتهي في سطر واحد. مثلا:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_10000_18" style="">
<span class="kwd">void</span><span class="pln"> </span><span class="typ">SomeFunction</span><span class="pun">(</span><span class="com">/* الوسيط الأول */</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> a</span><span class="pun">,</span><span class="pln"> </span><span class="com">/* الوسيط الثاني */</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> b</span><span class="pun">);</span></pre>

<h3>
	أهمية التعليقات
</h3>

<p>
	كما هو الحال مع جميع لغات البرمجة، توفر التعليقات العديد من الفوائد، منها:
</p>

<ul>
<li>
		توثيق ضمني للشيفرة البرمجية لتسهيل قراءتها وصيانتها
	</li>
	<li>
		شرح الغرض من الشيفرة البرمجية ودوالها
	</li>
	<li>
		توفير تفاصيل حول تاريخ الشيفرة أو المنطق وراءها
	</li>
	<li>
		وضع حقوق الطبع والنشر/التراخيص، أو ملاحظات حول المشروع، أو شكر خاص، أو التنويه بالمساهمين، وما إلى ذلك مباشرة في الشيفرة المصدرية (source code).
	</li>
</ul>
<p>
	من جهة أخرى، فإنّ للتعليقات جانبًا سلبيًا كذلك:
</p>

<ul>
<li>
		يجب تعديلها لتعكس أي تغييرات في الشيفرة
	</li>
	<li>
		الإفراط في إدراج التعليقات قد يؤثر سلبًا على مقروئية الشيفرة.
	</li>
</ul>
<p>
	يمكن تقليل الحاجة إلى التعليقات عبر كتابة شيفرة واضحة ومُوثقة ذاتيًا (self-documenting). أحد الأمثلة على ذلك هو استخدام أسماء توضيحية للمُتغيرات والدوال والأنواع. وتوزيع المهام المترابطة منطقيًا في دوال منفصلة.
</p>

<h3>
	تعليق الشيفرة واختبارها
</h3>

<p>
	أثناء التطوير، يمكن أيضًا استخدام التعليقات لتعطيل أجزاء من الشيفرة بسرعة دون حذفها. غالبًا ما يكون هذا مفيدًا في مرحلة الاختبار أو التنقيح (debugging)، ولكن ينبغي محو تلك التعليقات بعد الانتهاء. يشار إلى هذا غالبًا باسم "تعليق الشيفرة" (commenting out).
</p>

<p>
	بالمثل، الاحتفاظ بالإصدارات القديمة من أجزاء من الشيفرة في التعليقات لجعلها متاحة للمراجعة قد يكون مزعجًا، لأنّ ذلك يُراكم الكثير من الشيفرة غير المستخدمة، ولا يضيف قيمة تذكر موازنةً بالاطلاع على تاريخ الشيفرة عبر نظام إصدارات (versioning system).
</p>

<h2>
	عملية التصريف القياسية في C++‎‎
</h2>

<p>
	تُنتَج برامج C++‎ القابلة للتنفيذ عادة بواسطة <strong>المُصرّف</strong> (compiler)، وهو برنامج يترجم الشيفرة من لغة برمجة إلى شيفرة تنفيذية تفهمها الآلة وتُنفذ على الحاسوب من قبل المستخدم النهائي. استخدام المصرّف لتصريف الشيفرة يسمى عملية <strong>التصريف</strong> (compilation process‎).
</p>

<p>
	ورثت C++‎ آلية التصريف من سلفها، أي اللغة C. فيما يلي قائمة توضح الخطوات الرئيسية الأربع للتصريف في C++‎:
</p>

<ol>
<li>
		ينسخ المعالج الأولي (preprocessor) للغة C++‎ محتويات كل ملفات الترويسات (header ﬁles) المتضمنة في ملف الشيفرة المصدري، ويولد «شيفرة عملية بدل» (<a data-ss1617022298="1" href="https://www.computerhope.com/jargon/m/macro.htm#targetText=A%20macro%20(which%20stands%20for,a%20preset%20sequence%20of%20output.&amp;targetText=When%20the%20code%20is%20preprocessed,expanded%20each%20time%20it%20occurs.)" rel="external nofollow">macro code</a>، ويعوّض الثوابت الرمزية (symbolic constants) المعرفّة باستخدام ‎<code>#deﬁne</code>‎ بقِيمهما.
	</li>
	<li>
		تُصرَّف الشيفرة المصدرية الموسعة التي أُنتِجت بواسطة المعالج الأولي لـ C++‎ إلى لغة التجميع (assembly language) المناسبة لنظام التشغيل.
	</li>
	<li>
		تُصرَّف الشيفرة المجمّعة التي أُنتِجت بواسطة المصرّف إلى تعليمات مُصرّفة (object code) مناسبة لنظام التشغيل.
	</li>
	<li>
		تُربَط التعليمات المُصرَّفة المُولّدة من قبل المجمّع (assembler) مع ملفات التعليمات المُصرَّفة (object code files) الخاصة بدوال المكتبات المستخدمة لإنتاج الملف القابل للتنفيذ.
	</li>
</ol>
<p>
	<strong>ملاحظة</strong>: أحيانًا تُربط بعض الشيفرات المُصرَّفة معًا، ولكن ليس لغرض إنشاء برنامج نهائي، إذ يمكن تحزيم (packaging) الشيفرة "المربوطة" لأجل استخدامها من قبل برامج أخرى. الحزم الناتجة هي ما يشير إليه مبرمجو C++‎ بالمكتبات (libraries).
</p>

<p>
	تدمج العديد من مصرّفات C++‎ أو تفكّك بعض مراحل عملية التصريف لتسهيل العملية، أو لأجل التحليل الإضافي. يستخدم مُبرمجو C++‎ أدوات مختلفة، لكنها جميعًا تتبع المقاربة أعلاه.
</p>

<h2>
	الدوال
</h2>

<p>
	<strong>الدالة</strong> هي كتلة من الشيفرة تحتوي سلسلة من العبارات. يمكن للدوال قبول وسائط (arguments) أو قيم، ويمكن أن تعيد قيمة واحدة، أو قد لا تعيد أي قيمة. لاستخدام دالة، يجب استدعاؤها مع تمرير وسائط إليها، ثم تعيد قيمة.
</p>

<p>
	لكل دالة بصمة نوعيّة (type signature)، والتي تمثل أنواع وسائطها، ونوع القيمة المعادة. الدوال مستوحاة من مفهومَي الإجراء (procedure) والدالة في الرياضيات.
</p>

<p>
	<strong>ملاحظات:</strong>
</p>

<ul>
<li>
		دوال C++‎ هي إجراءات (procedures) بالأساس، ولا تتبع بدقة قواعد الدوال الرياضية وفق مفهوم علوم الرياضيات.
	</li>
	<li>
		تؤدي الدوال في العادة مهام محددة ويمكن استدعاؤها من أجزاء أخرى من البرنامج. كما يجب التصريح عن الدالة وتعرِيفها قبل استدعائها في البرنامج.
	</li>
	<li>
		قد تُخفى تعريفات الدوال الشائعة والمهمة في ملفات أخرى مُضمّنة، فذلك يسهِّل إعادة استخدامها في البرامج. وهذا أحد الاستخدامات الشائعة لملفات الترويسات (header files).
	</li>
</ul>
<h3>
	التصريح عن دالة
</h3>

<p>
	التصريح عن دالة (Function Declaration) هو عملية الإعلان عن وجود دالة، مع توضيح اسمها وبصمتها النوعيّة للمصرف. ويتبع الصياغة التالية:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9425_26" style="">
<span class="com">// الدالة التالية تقبل عددًا صحيحًا وتعيد عددًا صحيحًا</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> add2</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> i</span><span class="pun">);</span><span class="pln"> </span></pre>

<p>
	في المثال أعلاه، تخبر <code>int add2(int i)‎</code> المصرّف بالمعلومات التالية عن الدالة المُصرَّح عنها:
</p>

<ul>
<li>
		نوع القيمة المعادة هو <code>int</code>.
	</li>
	<li>
		اسم الدالة هو <code>add2</code>.
	</li>
	<li>
		عدد وسائط الدالة هو 1:
		<ul>
<li>
				الوسيط الأول من النوع <code>int</code>.
			</li>
			<li>
				سيُشار إلى الوسيط الأول داخل الدالة بالاسم <code>i</code>.
			</li>
		</ul>
</li>
</ul>
<p>
	اسم الوسيط اختياري؛ إذ يمكن التصريح بالدالة كما يلي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_10000_22" style="">
<span class="typ">int</span><span class="pln"> add2</span><span class="pun">(</span><span class="typ">int</span><span class="pun">);</span><span class="pln"> </span><span class="com">// يمكن حذف اسم الوسيط</span></pre>

<p>
	وفقًا <strong>لقاعدة التعريف الواحد</strong> (one-definition rule)، لا يمكن التصريح بدالة ذات بصمة (signature) نوعيّة معينة أو تعريفها أكثر من مرة واحدة في كامل شيفرة C++‎ المرئية للمصرّف. بمعنى آخر، لا يمكن إعادة تعريف دالة ذات بصمة نوعية معيّنة إلا مرة واحدة فقط. وبالتالي، فالشيفرة التالية غير صالحة في C++‎ وسيطلق المصرف خطأ عند تنفيذها:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7645_8" style="">
<span class="com">// int هي دالة من النوع add2 المصرف سيعلم أن</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> add2</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> i</span><span class="pun">);</span><span class="pln"> </span><span class="com">// (int) -&gt; int</span><span class="pln">

</span><span class="com">// لا يمكن إعادة تعريف نفس الدالة بنفس البصمة</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> add2</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> j</span><span class="pun">);</span><span class="pln"> </span><span class="com">// (int) -&gt; int</span></pre>

<p>
	إذا لم تُعِد الدالة أي قيمة، فإنّ نوع القيمة المعادة سيُكتب <code>void</code>. إذا لم تأخذ الدالة أيّ معاملات، فينبغي أن تكون قائمة المعاملات فارغة.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9425_30" style="">
<span class="com">// الدالة التالية لا تأخذ أي وسائط، ولا تعيد أي قيمة</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> do_something</span><span class="pun">();</span><span class="pln"> </span></pre>

<p>
	لاحظ أنه ما يزال بمقدور الدالة do_something التأثير في المتغيرات التي يمكنها الوصول إليها.
</p>

<h3>
	استدعاء الدالة
</h3>

<p>
	يمكن استدعاء الدالة بعد التصريح عنها. على سبيل المثال، يستدعي البرنامج التالي الدالة <code>add2</code> مع القيمة <code>2</code> داخل الدالة <code>main</code>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9425_34" style="">
<span class="com">#include</span><span class="pln"> </span><span class="str">&lt;iostream&gt;</span><span class="pln">

</span><span class="typ">int</span><span class="pln"> add2</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> i</span><span class="pun">);</span><span class="pln"> </span><span class="com">// add2 تعريف الدالة</span><span class="pln">

</span><span class="typ">int</span><span class="pln"> main</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  
    </span><span class="com">// في هذا الموضع add2(2) سيتم تقييم</span><span class="pln">
    std</span><span class="pun">::</span><span class="pln">cout </span><span class="pun">&lt;&lt;</span><span class="pln"> add2</span><span class="pun">(</span><span class="lit">2</span><span class="pun">)</span><span class="pln"> </span><span class="pun">&lt;&lt;</span><span class="pln"> </span><span class="str">"\n"</span><span class="pun">;</span><span class="pln">
    
    </span><span class="com">// وستُطبع النتيجة</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	بالنظر إلى الشيفرة السابقة، نجد أنَّه ما تزال الدالة add2 تحتاج إلى توفير طريقة تنفيذ لها بالإضافة إلى تعريفها (جسم الدالة)، رغم أن تنفيذ الدالة لا يظهر مباشرة في الشيفرة، إذ يمكن جلبه من ملف آخر بربط هذا الملف مع الشيفرة التي تستدعي الدالة.
</p>

<p>
	تمثل <code>add2(2)‎</code> صياغة استدعاء دالة.
</p>

<h3>
	تعريف الدالة
</h3>

<p>
	تعريف الدالة يشبه التصريح عنها، إلا أنه يحتوي أيضًا على الشيفرة الذي ستُنفّذ عند استدعاء الدالة، هذه الشيفرة تُسمى جسم الدالة (function body). فيما يلي مثال عن تعريف الدالة <code>add2</code>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4649_6" style="">
<span class="com">// i القيمة التي ستُمرر إلى الدالة سيشار إليها بالاسم </span><span class="pln">
</span><span class="typ">int</span><span class="pln"> add2</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> i</span><span class="pun">)</span><span class="pln"> 
</span><span class="pun">{</span><span class="pln">
  	</span><span class="com">// بين القوسين يمثل داخل نطاق أو جسم الدالة</span><span class="pln">

    </span><span class="typ">int</span><span class="pln"> j </span><span class="pun">=</span><span class="pln"> i </span><span class="pun">+</span><span class="pln"> </span><span class="lit">2</span><span class="pun">;</span><span class="pln"> 
    </span><span class="kwd">return</span><span class="pln"> j</span><span class="pun">;</span><span class="pln"> 
</span><span class="pun">}</span></pre>

<h3>
	زيادة تحميل الدوال
</h3>

<p>
	يمكنك إنشاء عدة دوال تشترك في نفس الاسم، ولكن مع اختلاف المعاملات، أي تختلف بصمة الدالة فقط، وهذا ما يعرف «بزيادة تحميل دالة» (Function Overloading).
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9425_40" style="">
<span class="com">// التنفيذ الأول</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> add2</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> i</span><span class="pun">)</span><span class="pln"> 
</span><span class="pun">{</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> j </span><span class="pun">=</span><span class="pln"> i </span><span class="pun">+</span><span class="pln"> </span><span class="lit">2</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> j</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="com">// التنفيذ الثاني</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> add2</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> i</span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> j</span><span class="pun">)</span><span class="pln"> 
</span><span class="pun">{</span><span class="pln">
    </span><span class="typ">int</span><span class="pln"> k </span><span class="pun">=</span><span class="pln"> i </span><span class="pun">+</span><span class="pln"> j </span><span class="pun">+</span><span class="pln"> </span><span class="lit">2</span><span class="pun">;</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> k</span><span class="pun">;</span><span class="pln"> </span><span class="com">//</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	كلتا الدالتين تحملان الاسم <code>add2</code>، بيْد أنّ الدالة المُنفّذة تعتمد على عدد وأنواع المعاملات المُمررة في الاستدعاء. في معظم الحالات، يمكن لمصرّف C++‎ أن يحدد الدالة المراد استدعاؤها. لكن في بعض الحالات يجب ذكر النوع بوضوح. فسيتم تقييم الشيفرة المحتواة في التعريف الأول عند استدعاء الدالة نع معامل واحد بالشكل add2(1)<code>‎</code>. وفي حال استدعاء الدالة مع معاملين بالشكل add2(1, 3)<code>‎</code>، فسيتم تقييم الشيفرة المتضمنة في التعريف الثاني بدلًا من التعريف الأول.
</p>

<h3>
	المعاملات الافتراضية
</h3>

<p>
	يمكن تحديد القيم الافتراضية لمعاملات الدالة (Default Parameters) في تعريفات الدوال فقط.
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9425_42" style="">
<span class="com">// 7 هي b القيمة الافتراضية للمعامل</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> multiply</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> a</span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> b </span><span class="pun">=</span><span class="pln"> </span><span class="lit">7</span><span class="pun">);</span><span class="pln">

</span><span class="com">// جسم الدالة</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> multiply</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> a</span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> b</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    </span><span class="kwd">return</span><span class="pln"> a </span><span class="pun">*</span><span class="pln"> b</span><span class="pun">;</span><span class="pln"> 
</span><span class="pun">}</span></pre>

<p>
	في هذا المثال، يمكن استدعاء <code>multiply()‎</code> مع معامل واحد أو مُعاملين. في حال تمرير معامل واحدة فقط، فستكون القيمة الافتراضية للمعامل <code>b</code> هي 7 وسيتم ضرب القيمة الممررة تلك بالمعامل الافتراضي 7 آنذاك. يجب وضع المعاملات الافتراضية في الأخير على النحو التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9425_46" style="">
<span class="com">// تعريف صحيح</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> multiply</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> a </span><span class="pun">=</span><span class="pln"> </span><span class="lit">10</span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> b </span><span class="pun">=</span><span class="pln"> </span><span class="lit">20</span><span class="pun">);</span><span class="pln"> 

</span><span class="com">// مُقدّمة int a تعريف غير صحيح لأن</span><span class="pln">
</span><span class="typ">int</span><span class="pln"> multiply</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> a </span><span class="pun">=</span><span class="pln"> </span><span class="lit">10</span><span class="pun">,</span><span class="pln"> </span><span class="typ">int</span><span class="pln"> b</span><span class="pun">);</span><span class="pln"> </span></pre>

<h3>
	استدعاءات خاصة للدوال - العوامل
</h3>

<p>
	توجد استدعاءات خاصة في C++‎ للدوال، وهي ذات صياغة مختلفة عن الصياغة التقليدية <code>name_of_function(value1, value2, value3)</code>‎. المثال الأكثر شيوعا هي العوامل (operators). وهي تسلسلات أحرف خاصة تحوَّل إلى استدعاءات دوال من طرف المصرّف، من أمثلة ذلك، <code>!</code> و <code>+</code> و <code>-</code> و <code>*</code> و <code>%</code> و <code>‎&lt;&lt;‎</code> وغيرها. عادةً ما ترتبط هذه المحارف الخاصة باستخدامات غير برمجية، أو تُستخدم للتبسيط (على سبيل المثال، المحرف <code>+</code> يمثل عادةً مفهوم الإضافة). تعالج C++‎ هذه التسلسلات؛ وتحوّل كل عامل إلى استدعاء الدالة المقابلة. على سبيل المثال، التعبير‎ التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_10000_38" style="">
<span class="lit">3</span><span class="pun">+</span><span class="lit">3</span></pre>

<p>
	يكافئ استدعاء الدالة التالية:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_10000_40" style="">
<span class="kwd">operator</span><span class="pun">+(</span><span class="lit">3</span><span class="pun">,</span><span class="pln"> </span><span class="lit">3</span><span class="pun">)</span></pre>

<p>
	تبدأ جميع أسماء دوال العوامل بـ <code>operator</code>. في لغة C، لا يمكن تعيين معان جديدة لأسماء دوال العوامل عبر كتابة تعريفات إضافية ذات بصمات نوعية مختلفة، في C++‎، هذا جائز. يشار إلى ربط تعريفات إضافية بنفس اسم الدالة باسم التحميل الزائد للعامل (operator overloading) في C++‎، وهو اصطلاح شائع نسبيًا، ولكنه غير عام في C++‎.
</p>

<h3>
	التصريح عن الدوال وقواعد مرئيتها
</h3>

<p>
	في C++‎، يجب التصريح عن الشيفرة أو تعريفها قبل استخدامها. على سبيل المثال، ينتج عن الشيفرة التالية خطأ في وقت التصريف:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_7645_6" style="">
<span class="typ">int</span><span class="pln"> main</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    foo</span><span class="pun">(</span><span class="lit">2</span><span class="pun">);</span><span class="pln"> </span><span class="com">// (*)</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> foo</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> x</span><span class="pun">)</span><span class="pln"> 
</span><span class="pun">{}</span></pre>

<p>
	سيطلق خطأ، لأن الدالة foo استُدعِيت في السطر (*) قبل أن تُعرّف، إذ لا ترى الدالة main هذا التعريف المتأخر للدالة foo بعد استدعائها ضمنها.
</p>

<p>
	هناك طريقتان لحل هذه المشكلة: إما التصريح عن <code>foo()‎</code> أو تعريفها قبل استخدامها في <code>main()‎</code>. هذا مثال على ذلك:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4970_6" style="">
<span class="com">// ووضع جسمها أولا foo التصريح عن الدالة</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> foo</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> x</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{}</span><span class="pln"> 
</span><span class="typ">int</span><span class="pln"> main</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
  
    </span><span class="com">// الآن foo يمكن استدعاء الدالة</span><span class="pln">
    foo</span><span class="pun">(</span><span class="lit">2</span><span class="pun">);</span><span class="pln"> 
</span><span class="pun">}</span></pre>

<p>
	من الممكن أيضًا التصريح المسبق (forward-declaration) عن الدالة عن طريق وضع تصريح عن قالبها (prototype declaration) قبل موضع استدعائها والذي يحدد نوع القيمة المعادة واسم الدالة وعدد وسائطها وأنواعها، ثم تعريف جسمها لاحقًا:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4970_8" style="">
<span class="com">// foo تصريح عن قالب لدالة باسم</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> foo</span><span class="pun">(</span><span class="typ">int</span><span class="pun">);</span><span class="pln"> 

</span><span class="typ">int</span><span class="pln"> main</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln">
    foo</span><span class="pun">(</span><span class="lit">2</span><span class="pun">);</span><span class="pln">  </span><span class="com">// (*)</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="com">// ينبغي أن تطابق تصريح القالب أعلاه</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> foo</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> x</span><span class="pun">)</span><span class="pln"> 
</span><span class="pun">{</span><span class="pln">
    </span><span class="com">// هنا foo تعريف جسم</span><span class="pln">
</span><span class="pun">}</span></pre>

<p>
	أصبحت الدالة foo مرئية، لذا يمكن استدعاؤها الآن ضمن الدالة main في السطر (*) رغم أنها لم تُعرّف بعد.
</p>

<p>
	يجب أن يحدد تصريح النموذج نوع القيمة المعادة (<code>void</code>)، واسم الدالة (<code>foo</code>)، وأنواع المتغيرات في قائمة الوسائط (<code>int</code>)، لكنّ أسماء الوسائط غير ضرورية.
</p>

<p>
	يمكن وضع تصريحات قوالب الدوال في ترويسة الملف:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_9425_61" style="">
<span class="com">// foo.h الملف</span><span class="pln">

</span><span class="com">// تصريح عن قالب دالة</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> foo</span><span class="pun">(</span><span class="typ">int</span><span class="pun">);</span><span class="pln"> </span></pre>

<p>
	ثم تقديم التعريف الكامل في موضع آخر:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4970_10" style="">
<span class="com">// foo.cpp --&gt; foo.o</span><span class="pln">

</span><span class="com">// foo تضمين الملف الذي يحوي قالب الدالة </span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">"foo.h"</span><span class="pln"> 
  
</span><span class="com">// foo تعريف جسم الدالة</span><span class="pln">
</span><span class="kwd">void</span><span class="pln"> foo</span><span class="pun">(</span><span class="typ">int</span><span class="pln"> x</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="pun">}</span><span class="pln"> </span></pre>

<p>
	ثم، بمجرد تصريف الشيفرة، يمكن ربط كائن الملف (object ﬁle) المقابل <code>foo.o</code> بالكائن المصرّف حيث يتم استخدامه في مرحلة الربط، <code>main.o</code>:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_4970_13" style="">
<span class="com">// main.cpp --&gt; main.o</span><span class="pln">

</span><span class="com">// foo تصريح عن قالب الدالة</span><span class="pln">
</span><span class="com">#include</span><span class="pln"> </span><span class="str">"foo.h"</span><span class="pln"> 
</span><span class="typ">int</span><span class="pln"> main</span><span class="pun">()</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> foo</span><span class="pun">(</span><span class="lit">2</span><span class="pun">);</span><span class="pln"> </span><span class="pun">}</span><span class="pln"> </span><span class="com">// (*)</span></pre>

<p>
	استدعاء الدالة foo ممكن هنا، لأنه سبق التصريح عنها، وتعريف قالب ومتن الدالة foo مربوط عبر كائنات الملفات (object files). 
</p>

<p>
	يحدث الخطأ "رمز خارجي غير محلول" (unresolved external symbol) إذا صادف المصرّف تصريحَ قالب واستدعاء لدالة، دون وجود لجسمها (body). قد يكون حل هذه الأخطاء معقدًا، لأنّ المصرّف لن يبلِّغ عن الخطأ حتى مرحلة الربط النهائية، ولن يعرف السطر الذي يجب الانتقال إليه في الشيفرة لإظهار الخطأ.
</p>

<h2>
	المعالج الأولي
</h2>

<p>
	المعالج الأولي (Preprocessor) هو جزء مهم من المصرّف إذ يقوم بتعديل الشيفرة المصدرية، وحذف بعض البتات، أو تغييرها، وإضافة أشياء أخرى.
</p>

<p>
	في الملفات المصدرية، يمكننا تضمين مُوجِّهات (directives) للمعالج الأولي. تخبر تلك الموجِّهات المعالج الأولي بتنفيذ إجراءات محددة. يبدأ الموجّه بالرمز <code>#</code> في سطر جديد مثل:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_10000_54" style="">
<span class="com">#define</span><span class="pln"> ZERO </span><span class="lit">0</span></pre>

<p>
	من أشهر مُوجهات المعالج الأولي، الموجهات التالية:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_10000_56" style="">
<span class="com">#include</span><span class="pln"> </span><span class="str">&lt;something&gt;</span></pre>

<p>
	يأخذ هذا الموجه <code>something</code> ويُدرجه في ملفك حيث يظهر الموجه. مثلا، يبدأ برنامج "مرحبا بالعالم!" بالسطر التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_10000_58" style="">
<span class="com">#include</span><span class="pln"> </span><span class="str">&lt;iostream&gt;</span></pre>

<p>
	يضيف هذا السطر الدوال والكائنات التي تتيح لك استخدام المدخلات والمخرجات القياسية. لا تحتوي اللغة C (والتي تستخدم أيضًا المُعالج الأولي) نفس القدر من ترويسات الملفات كخَلَفها C++‎، كما أنه يمكنك في C++‎ استخدام جميع ترويسات C.
</p>

<p>
	المُوجِّه الثاني في الأهمية هو على الأرجح الموجّه التالي:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_10000_60" style="">
<span class="com">#define</span><span class="pln"> something something_else</span></pre>

<p>
	يخبر هذا المُوجِّه المعالج الأولي بأنه يجب أن يبدِّل <code>something</code> مكان كل ظهور لـ <code>something_else</code> في الملف الحالي. يمكن أن يجعل هذا الموجّه بعض الأشياء تتصرف مثل دوال، لكنه مفهوم متقدم أشرنا إليه قبل قليل على أنه «شيفرة عملية بدل» (macro code)، ولن نتطرق إليه الآن.
</p>

<p>
	<code>something_else</code> ليس ضروريًا، ولكن في حال عدم إضافة <code>something</code>، سيُحذَف كل ظهور لـ <code>something</code>.
</p>

<p>
	هذا مفيد جدا، إذ يمكن استخدامه مع المُوجِّهات <code>‎#if</code> و <code>‎#else</code> و <code>‎#ifdef</code>. وفق الصياغة التالية:
</p>

<pre class="ipsCode prettyprint lang-c prettyprinted" id="ips_uid_10000_62" style="">
<span class="com">#if something == true</span><span class="pln">
    </span><span class="com">// شيفرة</span><span class="pln">
</span><span class="com">#else</span><span class="pln">
    </span><span class="com">// شيفرة أخرى</span><span class="pln">
</span><span class="com">#endif</span><span class="pln">

</span><span class="com">#ifdef</span><span class="pln"> thing_that_you_want_to_know_if_is_defined
    </span><span class="com">// شيفرة</span><span class="pln">
</span><span class="com">#endif</span></pre>

<p>
	تدرِج هذه الموجِّهات الشيفرة الموجودة في البت الصحيح، وتحذف الآخرين. يمكن استخدام هذا لتضمين أجزاء من الشيفرة حصرًا في أنظمة تشغيل معينة دون الحاجة إلى إعادة كتابة الشيفرة بالكامل.
</p>

<p>
	هذه المقالة جزء من <a data-ss1617022298="1" href="%D8%B1%D8%A7%D8%A8%D8%B7" rel="">سلسلة مقالات عن C++‎</a>.
</p>

<p>
	ترجمة -وبتصرّف- للفصل Chapter 1: Getting started with C++‎ من الكتاب <a data-ss1617022298="1" href="https://goalkicker.com/CPlusPlusBook/CPlusPlusNotesForProfessionals.pdf" rel="external nofollow">C++ Notes for Professionals</a>
</p>

<h2>
	اقرأ أيضًا
</h2>

<ul>
<li>
		ا<a data-ss1617022298="1" href="https://academy.hsoub.com/programming/cpp/%D8%A7%D9%84%D8%AF%D8%B1%D8%B3-2-%D8%A7%D9%84%D9%82%D9%8A%D9%85-%D9%85%D8%B5%D9%86%D9%91%D9%8E%D9%81%D8%A9-%D8%A7%D9%84%D9%86%D9%88%D8%B9-r803/" rel="">لدرس 2: القيم مصنَّفة النوع</a>
	</li>
</ul>
]]></description><guid isPermaLink="false">802</guid><pubDate>Sat, 01 Feb 2020 13:07:00 +0000</pubDate></item></channel></rss>
