سؤال

أريد أن مبادلة اثنين من الاعداد الصحيحه, و أريد أن أعرف أي من هذين تطبيقات سيكون أسرع:طريقة واضحة مع متغير temp:

void swap(int* a, int* b)
{
    int temp = *a;
    *a = *b;
    *b = temp;
}

أو xor النسخة التي أنا متأكد من أن معظم الناس قد شهدت:

void swap(int* a, int* b)
{
    *a ^= *b;
    *b ^= *a;
    *a ^= *b;
}

يبدو أن أول من يستخدم إضافية السجل ، ولكن الثاني هو فعل ثلاثة الأحمال مخازن بينما الأولى فقط لا اثنين لكل منهما.يمكن أن تقولوا لي ما هو أسرع ولماذا ؟ لماذا تكون أكثر أهمية.

هل كانت مفيدة؟

المحلول

على XOR فشل أسلوب إذا كان a و b أشر إلى نفس العنوان.أول XOR سيتم مسح جميع البتات في عنوان الذاكرة إلى جانب كل من المتغيرات ، وذلك مرة واحدة ترجع الدالة (*a = = * = b= 0) ، بغض النظر عن القيمة الأولية.

مزيد من المعلومات على صفحة ويكي:XOR مبادلة الخوارزمية

على الرغم من أنه ليس من المرجح أن هذه المسألة سوف تأتي, كنت دائما يفضلون استخدام الأسلوب الذي يضمن أن العمل ليس ذكي الأسلوب الذي فشل في لحظات غير متوقعة.

نصائح أخرى

عدد 2 غالبا ما نقلت بأنها "ذكية" طريقة للقيام بذلك.بل هو في الواقع الأكثر احتمالا أبطأ كما يحجب الهدف واضح من مبرمج مبادلة اثنين من المتغيرات.وهذا يعني أن المترجم لا يمكن تحسين ذلك إلى الاستخدام الفعلي المجمع عمليات المبادلة.فإنه يفترض أيضا القدرة على القيام أحادي المعامل xor على الكائنات.

التمسك رقم 1 هو الأكثر عمومية والأكثر مفهوم المبادلة يمكن بسهولة قالب/genericized.

هذا ويكيبيديا يشرح القسم المسائل جيدا:http://en.wikipedia.org/wiki/XOR_swap_algorithm#Reasons_for_avoidance_in_practice

في حديث المعالج, هل يمكن استخدام ما يلي عند الفرز صفائف كبيرة و لا أرى أي فرق في سرعة:

void swap (int *a, int *b)
{
  for (int i = 1 ; i ; i <<= 1)
  {
    if ((*a & i) != (*b & i))
    {
      *a ^= i;
      *b ^= i;
    }
  }
}

حقا جزء مهم من السؤال هو 'لماذا ؟' جزء.والان عودة 20 عاما إلى 8086 الأيام المذكورة أعلاه يمكن أن يكون الأداء الحقيقي القاتل ، ولكن على أحدث بنتيوم ستكون مباراة سرعة الحكمة أن اثنين قمت بنشرها.

السبب هو محض وصولا إلى الذاكرة له علاقة مع وحدة المعالجة المركزية.

وحدة المعالجة المركزية سرعة بالمقارنة مع الذاكرة بسرعات قد ارتفعت فلكية.الوصول إلى الذاكرة أصبح عقبة رئيسية في أداء التطبيق.كل مبادلة خوارزميات سوف تنفق معظم وقتهم في انتظار البيانات التي يتم جلبها من الذاكرة.نظام التشغيل الحديثة يمكن أن يصل إلى 5 مستويات من الذاكرة:

  • ذاكرة التخزين المؤقت من المستوى 1 - يعمل بنفس سرعة وحدة المعالجة المركزية لم يذكر وقت الوصول ، ولكن هو صغير
  • ذاكرة التخزين المؤقت من المستوى 2 - يعمل أبطأ قليلا من L1 ولكن أكبر و أكبر النفقات العامة إلى الوصول إلى (عادة البيانات يحتاج إلى أن انتقل إلى L1 الأولى)
  • ذاكرة التخزين المؤقت من المستوى 3 - (ليس دائما موجودة) في كثير من الأحيان الخارجية إلى وحدة المعالجة المركزية ، أبطأ أكبر من L2
  • رام الرئيسية ذاكرة النظام ، وعادة ما تنفذ خط أنابيب لذلك هناك الكمون في قراءة طلبات (وحدة المعالجة المركزية طلبات البيانات ، رسالة أرسلت إلى رام RAM يحصل على البيانات من ذاكرة الوصول العشوائي يرسل البيانات إلى وحدة المعالجة المركزية)
  • القرص الصلب - عندما لا يوجد ما يكفي من ذاكرة الوصول العشوائي ، البيانات المقسمة إلى HD التي هي بطيئة حقا, ليس حقا تحت مراقبة وحدة المعالجة المركزية على هذا النحو.

خوارزميات الفرز سوف تجعل ذاكرة الوصول إلى أسوأ لأنها عادة الوصول إلى الذاكرة في مرتبة الطريق ، وبالتالي تكبد كفاءة النفقات العامة من جلب البيانات من L2, RAM أو HD.

لذا تحسين طريقة المبادلة من غير المجدي حقا - لو كان فقط اتصل عدة مرات ثم أي عدم الكفاءة مخفي بسبب قلة عدد المكالمات, لو انه دعا الكثير ثم أي عدم الكفاءة مخفي بسبب عدد من ذاكرة التخزين المؤقت يخطئ (حيث وحدة المعالجة المركزية يحتاج إلى الحصول على البيانات من L2 (1 دورات), L3 (10 دورات), ذاكرة الوصول العشوائي (100 دورات), HD (!)).

ما كنت حقا بحاجة إلى القيام به هو إلقاء نظرة على الخوارزمية التي يدعو طريقة المبادلة.هذه ليست عملية هينة.على الرغم من أن كبير-O التدوين مفيد O(n) يمكن أن تكون أسرع بكثير من a O(log n) الصغيرة n.(أنا متأكد من أن هناك CodingHorror المادة حول هذا الموضوع.) أيضا, العديد من خوارزميات تتحول الحالات التي يكون فيها رمز لا أكثر مما هو ضروري (باستخدام qsort على ما يقرب من طلب البيانات يمكن أن يكون أبطأ من نوع فقاعة مع مبكرة خارج الاختيار).لذا تحتاج إلى تحليل خوارزمية الخاص بك والبيانات انها تستخدم.

الأمر الذي يؤدي إلى كيفية تحليل التعليمات البرمجية.المحللون مفيدة ولكن كنت بحاجة إلى معرفة كيفية تفسير النتائج.أبدا استخدام شوط واحد لجمع النتائج دائما متوسط النتائج على العديد من عمليات الإعدام - لأن تطبيق الاختبار قد تم ترحيلها إلى القرص الثابت قبل التشغيل في منتصف الطريق من خلال.دائما الشخصي الإفراج عن محسن يبني التنميط رمز التصحيح لا طائل.

كما أن السؤال الأصلي - الذي هو أسرع ؟ - انها مثل محاولة لمعرفة إذا فيراري أسرع من Lambourgini من خلال النظر في حجم وشكل مرآة الجناح.

الأول هو أسرع لأن جميع العمليات مثل xor عادة ما تكون من الصعب جدا تصور للقارئ.

أسرع إلى فهم بالطبع ، وهو أهم جزء ;)

@هاري:قف في زاوية التفكير في ما كنت قد اقترحت.أعود عندما كنت قد أدركت خطأ من الطرق الخاصة بك.

ابدأ في تنفيذ مهام وحدات الماكرو للأسباب التالية:

  1. نوع الأمان.هناك لا شيء.التالية فقط يولد تحذير عند ترجمة ولكن فشل في وقت التشغيل:

    float a=1.5f,b=4.2f;
    swap (a,b);
    

    A قالب وظيفة سوف دائما تكون من النوع الصحيح (و لماذا لا علاج والتحذيرات الأخطاء؟).

    تحرير:كما لا يوجد في قوالب ج ، عليك أن تكتب منفصلة مبادلة لكل نوع أو استخدام بعض hacky الوصول إلى الذاكرة.

  2. إنها رسالة الاستبدال.التالية يفشل في وقت التشغيل (هذه المرة دون مترجم تحذيرات):

    int a=1,temp=3;
    swap (a,temp);
    
  3. انها ليست وظيفة.لذا لا يمكن استخدامه كحجة شيء مثل qsort.

  4. المجمعين هي ذكية.أعني ذكية حقا.أدلى ذكية حقا الناس.فإنها يمكن أن تفعل inlining من الوظائف.حتى في وقت الارتباط (الذي هو أكثر ذكي).لا ننسى أن inlining يزيد حجم التعليمات البرمجية.رمز كبير يعني أكثر من فرصة ذاكرة التخزين المؤقت تفوت عند جلب التعليمات ، مما يعني أبطأ رمز.
  5. الآثار الجانبية.وحدات الماكرو لها آثار جانبية!النظر:

    int &f1 ();
    int &f2 ();
    void func ()
    {
      swap (f1 (), f2 ());
    }
    

    هنا f1 و f2 سوف يطلق مرتين.

    تحرير:ج الإصدار مع آثار جانبية سيئة:

    int a[10], b[10], i=0, j=0;
    swap (a[i++], b[j++]);
    

وحدات الماكرو: لا أقول فقط!

تحرير:هذا هو السبب في أنني أفضل أن تحدد أسماء الماكرو في أحرف كبيرة بحيث تبرز في المدونة بمثابة تحذير مع استخدام الرعاية.

EDIT2:الإجابة Leahn Novash تعليق:

لنفترض أن لدينا غير المضمنة الوظيفة ، و التي يتم تحويلها من قبل المترجم في سلسلة من البايتات ثم يمكننا تحديد عدد وحدات البايت وهكذا:

bytes = C(p) + C(f)

حيث C() يعطي عدد وحدات البايت المنتجة ، ج(و) هو بايت وظيفة C(p) هو بايت على 'الغرف' رمز الديباجة بعد التمهل المترجم يضيف إلى وظيفة (خلق وتدمير وظيفة هذا الإطار المكدس وهلم جرا).الآن استدعاء الدالة f يتطلب ج(c) بايت.إذا كان يتم استدعاء الدالة n مرات ثم إجمالي حجم الكود هو:

size = C(p) + C(f) + n.C(c)

الآن دعونا مضمنة وظيفة.ج(ف) ، وظيفة 'تنظيف', يصبح صفرا لأن وظيفة يمكن استخدام الإطار كومة من المتصل.ج(c) هو أيضا صفر حيث هناك الآن أي استدعاء شفرة التشغيل.لكن و هو تكرارها أينما كانت هناك دعوة.لذا ، فإن إجمالي حجم التعليمات البرمجية الآن:

size = n.C(f)

الآن, إذا ج(و) هو أقل من C من(c) ثم في العام القابل للتنفيذ حجم سيتم تخفيض.ولكن ، إذا ج(و) أكبر من C من(c) ثم رمز حجم هو الذهاب الى زيادة.إذا ج(و) و ج(c) هي مماثلة ثم تحتاج إلى النظر في C(ع) كذلك.

لذا كم بايت هل ج(و) و ج(c) تنتج.حسنا, أبسط C++ وظيفة أن يكون حاصل:

void GetValue () { return m_value; }

التي ربما تولد أربعة بايت التعليمات:

mov eax,[ecx + offsetof (m_value)]

وهو أربعة بايت.مكالمة instuction خمس بايت.لذلك هناك حجم إجمالي الادخار.إذا كانت وظيفة أكثر تعقيدا ، أقول المفهرس ("العودة m_value [فهرس];") أو حساب ("العودة m_value_a + m_value_b;") ثم رمز سوف يكون أكبر.

لمن يعثر على هذا السؤال و قررت استخدام XOR الأسلوب.يجب عليك أن تنظر في تضمين وظيفة الخاص بك أو استخدام ماكرو لتجنب الحمل من استدعاء دالة:

#define swap(a, b)   \
do {                 \
    int temp = a;    \
    a = b;           \
    b = temp;        \
} while(0)

هي الأمثل الشيء الخطأ ، سواء تلك يجب أن تكون سريعة بحيث سيكون لديك لتشغيل لهم المليارات من المرات فقط للحصول على أي قابلة للقياس الفرق.

ومجرد عن أي شيء سوف يكون لها أكبر تأثير على الأداء الخاص بك, على سبيل المثال, إذا كانت القيم هي مبادلة قريبة في الذاكرة إلى الماضي قيمة لمست هم ليلي في المعالج ذاكرة التخزين المؤقت, وإلا سيكون لديك الوصول إلى الذاكرة التي هي عدة أوامر من حجم أبطأ ثم أي عملية تقوم داخل المعالج.

بأي حال من عنق الزجاجة هو أكثر بكثير من المرجح أن تكون غير فعالة خوارزمية أو غير مناسب بنية البيانات (أو الاتصالات العامة) ثم كيف يمكنك تبادل الأرقام.

لم يفهم أكره على وحدات الماكرو.عندما تستخدم بشكل صحيح أنها يمكن أن تجعل رمز أكثر المدمجة للقراءة.أعتقد أن معظم المبرمجين يعرفون وحدات الماكرو ينبغي أن تستخدم بحذر, ما هو مهم هو مما يجعل من الواضح أن استدعاء ماكرو وليس استدعاء دالة (كل مباراة دولية).إذا SWAP(a++, b++); هو مصدر ثابت من المشاكل ، ربما البرمجة ليست لك.

باعتراف الجميع ، xor هو خدعة متقنة أول 5000 مرة ترى, ولكن كل ما يفعله هو حقا حفظ مؤقت واحد على حساب الموثوقية.تنظر الجمعية التي فوقه يحفظ سجل ولكن يخلق التبعيات.أيضا لا أنصح xchg منذ ضمني قفل البادئة.

في نهاية المطاف وصلنا إلى نفس المكان بعد ساعات لا تحصى يضيع على غير منتجة التحسين و التصحيح عن طريق معظم ذكي رمز يبقيه بسيط.

#define SWAP(type, a, b) \
    do { type t=(a);(a)=(b);(b)=t; } while (0)

void swap(size_t esize, void* a, void* b)
{
    char* x = (char*) a;
    char* y = (char*) b;
    char* z = x + esize;

    for ( ; x < z; x++, y++ )
        SWAP(char, *x, *y);
}

فإن الطريقة الوحيدة لمعرفة الحقيقة هو الاختبار و الجواب قد تختلف اعتمادا على ما مترجم و منصة كنت على.الحديث المجمعين هي حقا جيد في تحسين التعليمات البرمجية في هذه الأيام, و لا يجب أن اغلب المترجم إلا إذا كنت تستطيع أن تثبت أن طريقك هو حقا أسرع.

وقال مع ذلك, من الأفضل أن يكون لديك سبب وجيه لاختيار #2 #1.قانون رقم 1 هو أكثر قابلية للقراءة و بسبب ذلك ينبغي دائما أن يتم اختيار الأول.التبديل فقط على #2 إذا كنت تستطيع أن تثبت أنك تحتاج لجعل هذا التغيير, و إذا كنت تفعل - تعليق ذلك على تفسير ما يحدث و لماذا فعلت ذلك غير واضح الطريقة.

كما حكاية, أنا أعمل مع مجموعة من الناس أن الحب لتحسين قبل الأوان و يجعل حقا البشعة ، unmaintainable رمز.أنا أيضا على استعداد للمراهنة على أن أكثر الأحيان أنهم يطلقون النار على أنفسهم في القدم لأنها قد تعوق قدرة المترجم على تحسين التعليمات البرمجية عن طريق الكتابة في غير طريقة مباشرة.

وأود أن لا تفعل ذلك مع مؤشرات ما لم يكن لديك إلى.المترجم لا يمكن تحسين منهم بشكل جيد للغاية بسبب احتمال مؤشر التعرج (على الرغم من أن إذا كنت يمكن أن تضمن أن المؤشرات تشير إلى عدم تداخل مواقع خليجية على الأقل قد امتداد لتحسين هذا).

وأنا لن تفعل ذلك مع المهام على الإطلاق ، حيث إنها عملية بسيطة جدا و استدعاء دالة علوية كبيرة.

أفضل طريقة للقيام بذلك هي مع وحدات الماكرو إذا الخام سرعة وإمكانية الأمثل هو ما تحتاج.في دول مجلس التعاون الخليجي يمكنك استخدام typeof() مدمج لجعل مرنة الإصدار الذي يعمل على أي المدمج في نوع.

شيء من هذا القبيل:

#define swap(a,b) \
  do { \
    typeof(a) temp; \
    temp = a; \
    a = b; \
    b = temp; \
  } while (0)

...    
{
  int a, b;
  swap(a, b);
  unsigned char x, y;
  swap(x, y);                 /* works with any type */
}

مع المجمعين ، أو إذا كنت تحتاج إلى الامتثال الصارم مع معيار C89/99 ، سيكون لديك لجعل كلية منفصلة لكل نوع.

جيد المترجم تحسين هذا بقوة ممكن بالنظر إلى السياق ، إذا دعا مع المتغيرات العالمية كما الحجج.

كل الأعلى تصنيفا الأجوبة ليست في الواقع نهائية "الحقائق"...هم الناس الذين يتوقعون!

يمكنك نهائيا أعرف حقيقة وهو رمز يأخذ أقل الجمعية تعليمات تنفيذ لأنك يمكن أن ننظر في الجمعية الإخراج التي تم إنشاؤها بواسطة برنامج التحويل البرمجي و انظر الذي ينفذ في أقل تعليمات التجميع!

هنا هو رمز c جمعت مع أعلام "دول مجلس التعاون الخليجي -std=c99 -S -O3 lookingAtAsmOutput.ج":

#include <stdio.h>
#include <stdlib.h>

void swap_traditional(int * restrict a, int * restrict b)
{
    int temp = *a;
    *a = *b;
    *b = temp;
}

void swap_xor(int * restrict a, int * restrict b)
{
    *a ^= *b;
    *b ^= *a;
    *a ^= *b;
}

int main() {
    int a = 5;
    int b = 6;
    swap_traditional(&a,&b);
    swap_xor(&a,&b);
}

ASM إخراج swap_traditional() تحيط >>> 11 <<< تعليمات ( وليس بما في ذلك "ترك" ، "المتقاعد", "حجم"):

.globl swap_traditional
    .type   swap_traditional, @function
swap_traditional:
    pushl   %ebp
    movl    %esp, %ebp
    movl    8(%ebp), %edx
    movl    12(%ebp), %ecx
    pushl   %ebx
    movl    (%edx), %ebx
    movl    (%ecx), %eax
    movl    %ebx, (%ecx)
    movl    %eax, (%edx)
    popl    %ebx
    popl    %ebp
    ret
    .size   swap_traditional, .-swap_traditional
    .p2align 4,,15

ASM إخراج swap_xor() تحيط >>> 11 <<< تعليمات وليس بما في ذلك "ترك" و "المؤسسة":

.globl swap_xor
    .type   swap_xor, @function
swap_xor:
    pushl   %ebp
    movl    %esp, %ebp
    movl    8(%ebp), %ecx
    movl    12(%ebp), %edx
    movl    (%ecx), %eax
    xorl    (%edx), %eax
    movl    %eax, (%ecx)
    xorl    (%edx), %eax
    xorl    %eax, (%ecx)
    movl    %eax, (%edx)
    popl    %ebp
    ret
    .size   swap_xor, .-swap_xor
    .p2align 4,,15

ملخص الجمعية الإخراج:
swap_traditional() 11 يأخذ تعليمات
swap_xor() 11 يأخذ تعليمات

الخلاصة:
كلا أساليب استخدام نفس الكمية من تعليمات تنفيذ وبالتالي هي تقريبا نفس السرعة على منصة الأجهزة.

الدروس المستفادة:
عندما يكون لديك رمز صغير قصاصات ، وتبحث في asm إخراج مفيد بسرعة تكرار التعليمات البرمجية الخاصة بك والخروج مع أسرع ( أيعلى الأقل التعليمات ) التعليمات البرمجية.و يمكنك حفظ الوقت حتى لأن لم يكن لديك لتشغيل البرنامج لكل رمز التغيير.تحتاج فقط لتشغيل رمز التغيير في نهاية المطاف مع التعريف لإظهار أن تغييرات التعليمات البرمجية الخاصة بك أسرع.

يمكنني استخدام هذا الأسلوب الكثير الثقيلة DSP التعليمات البرمجية التي تحتاج السرعة.

للإجابة على سؤالك كما جاء يتطلب البحث في التعليمات أوقات معينة وحدة المعالجة المركزية أن هذا الرمز سوف تكون قيد التشغيل والتي ولذلك تتطلب إجراء مجموعة من الافتراضات حول الدولة من مخابئ في نظام الجمعية رمز المنبعثة من المجمع.سيكون ممارسة مثيرة للاهتمام ومفيدة من منظور فهم كيف المعالج من اختيار يعمل فعلا ولكن في العالم الحقيقي الفرق ستكون ضئيلة.

الحديث أبنية وحدة المعالجة المركزية, طريقة 1 سوف يكون أسرع أيضا مع ارتفاع القراءة من الأسلوب 2.

في الحديث أبنية وحدة المعالجة المركزية ، XOR التقنية هي أبطأ بكثير من استخدام متغير مؤقت للقيام مبادلة.سبب واحد هو أن وحدات المعالجة المركزية الحديثة تسعى إلى تنفيذ التعليمات بالتوازي التعليمات عبر خطوط الأنابيب.في XOR تقنية المدخلات لكل عملية تعتمد على نتائج العملية السابقة ، لذلك يجب أن يتم تنفيذها بدقة في ترتيب تسلسلي.إن الكفاءة هي قلق هائل, ينصح لاختبار سرعات كل XOR تقنية متغير مؤقت مبادلة على الهدف العمارة.تحقق من هنا للحصول على مزيد من المعلومات.


تحرير: الطريقة 2 هو وسيلة في مكان مبادلة (أيدون استخدام إضافية المتغيرات).لجعل هذا السؤال كاملة ، سيتم إضافة آخر في مكان مبادلة باستخدام +/-.

void swap(int* a, int* b)
{
    if (a != b) // important to handle a/b share the same reference
    {
        *a = *a+*b;
        *b = *a-*b;
        *a = *a-*b;
    }
}

x=x+y(y=x);

float x; cout << "X:"; cin >> x;
float y; cout << "Y:" ; cin >> y;

cout << "---------------------" << endl;
cout << "X=" << x << ", Y=" << y << endl;
x=x+y-(y=x);
cout << "X=" << x << ", Y=" << y << endl;

في رأيي المحلية التحسينات مثل هذا ينبغي إلا بإحكام ذات الصلة إلى المنصة.فإنه يجعل فرقا كبيرا إذا كنت تجميع هذا على 16 بت uC مترجم أو في دول مجلس التعاون الخليجي مع 64 هدفا.

إذا كان لديك هدف محدد في الاعتبار ثم مجرد محاولة كل منهما والنظر في إنشاء asm كود أو ملف التعريف الخاص بك applciation مع كل الأساليب ومعرفة من الذي هو في الواقع أسرع على النظام الأساسي الخاص بك.

إذا كان يمكنك استخدام بعض مضمنة المجمع ما يلي (الزائف المجمع):

PUSH A
A=B
POP B

سيوفر لك الكثير من المعلمة يمر وكومة إصلاح رمز الخ.

أنا فقط وضعت كل مقايضة (وحدات الماكرو) في ناحية مكتوب فرز سريع لقد لعب مع.على XOR النسخة أسرع بكثير (0.1 ثانية) ثم واحدة مع متغير مؤقت (0.6 sec).على XOR ومع ذلك لم الفاسدة البيانات في مجموعة (ربما نفس العنوان شيء النمل المذكور).

كما كان من الدهون محور فرز سريع ، XOR نسخة سرعة الأرجح من صنع أجزاء كبيرة من مجموعة نفس.حاولت الإصدار الثالث من المبادلة التي كان أسهل للفهم و كان نفس وقت واحد نسخة مؤقتة.


acopy=a;
bcopy=b;
a=bcopy;
b=acopy;

[أنا فقط وضعت وإذا البيانات حول كل مبادلة ، لذلك لا تحاول مبادلة مع نفسها ، XOR الآن يأخذ نفس الوقت مع الآخرين (0.6 sec)]

إذا كان المترجم يدعم مضمنة المجمع الهدف الخاص بك هو 32 بت x86 ثم XCHG التعليمات هو على الارجح أفضل طريقة للقيام بذلك...إذا كنت حقا لا يهتمون كثيرا عن الأداء.

هنا هو الطريقة التي تعمل مع MSVC++:

#include <stdio.h>

#define exchange(a,b)   __asm mov eax, a \
                        __asm xchg eax, b \
                        __asm mov a, eax               

int main(int arg, char** argv)
{
    int a = 1, b = 2;
    printf("%d %d --> ", a, b);
    exchange(a,b)
    printf("%d %d\r\n", a, b);
    return 0;
}

أدناه قطعة من التعليمات البرمجية سوف تفعل الشيء نفسه.هذا مقتطف هو الأمثل طريقة البرمجة كما أنه لا يستخدم أي 3rd متغير.

  x = x ^ y;
  y = x ^ y;
  x = x ^ y;
void swap(int* a, int* b)
{
    *a = (*b - *a) + (*b = *a);
}

// C بلدي قليلا صدئ ، لذلك آمل أن يكون لدي * حق :)

آخر بطريقة جميلة.

#define Swap( a, b ) (a)^=(b)^=(a)^=(b)

ميزة

لا تحتاج إلى استدعاء دالة ومفيد.

العيب:

فشل هذا عند كل المدخلات هي نفس المتغير.يمكن استخدامه فقط على عدد من المتغيرات.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top