
هل أنت مستعد للتعمق في عالم البرمجة الشجاع؟ هل تريد أن ترى كيف يمكن أن تتصرف بعض الأسطر البسيطة من التعليمات البرمجية بشكل غير متوقع؟
إذا كانت إجابتك "نعم!" - مرحبا بكم في القطط.
ستجد العديد من المهام المسلية في لغة C أو C ++.
سيتم دائمًا إخفاء الإجابة الصحيحة مع شرح تحت المفسد.
حظ موفق
عن أقصر برنامج
main;
ماذا يحدث إذا جمعت هذا البرنامج مع مترجم لغة C؟
- لا جمعت.
- غير مرتبط.
- تم تجميعها وربطها.
الجواب:هذا رمز C صالح.
لماذا؟ في لغة C ، يمكنك حذف نوع إرجاع الدالات وعند الإعلان عن المتغيرات ، ستصبح int افتراضيًا. وأيضاً في لغة C لا يوجد فرق بين الوظائف والمتغيرات العالمية أثناء الربط. في هذه الحالة ، يعتقد الرابط أن الوظيفة تحت وظيفة main.
حول شوكة
#include <iostream> #include <unistd.h> int main() { for(auto i = 0; i < 1000; i++) std::cout << "Hello world!\n"; fork(); }
كم مرة ستطبع Hello World!
- 1000
- أقل
- المزيد
الجواب:يتم تخزين عمليات الإدخال / الإخراج مؤقتًا لتحسين الأداء.
سوف تؤدي fork()
الاتصال fork()
إلى عملية جديدة ، مع مساحة عنوان مكررة للنسخ عند الكتابة.
ستتم طباعة الخطوط العازلة في كل عملية.
حول الفهارس
#include <iostream> int main() { int array[] = { 1, 2, 3 }; std::cout << (4, (1, 2)[array]) << std::endl; }
ماذا سيطبع هذا الرمز؟
- 1
- 2
- 3
- 4
- خطأ في الترجمة
- غير محدد بالمعيار.
الجواب:يطبع بورغرام 3.
لماذا ذلك
أولاً ، انظر إلى الفهرس: array[index] == *(array + index) == *(index + array) == index[array]
بعد ذلك ، نحن نتعامل مع عامل فاصلة ثنائي. يتجاهل حجته اليسرى ويعيد قيمة اليمين.
حول التعبير العادي
#include <regex> #include <iostream> int main() { std::regex re { "(.*|.*)*O" }; std::string str { "0123456789" }; std::cout << std::regex_match(str, re); return 0; }
ما هو الحد الأدنى من الوقت الذي سيحصل عليه هذا الموسم العادي؟
- ~ 1 مللي ثانية.
- ~ 100 مللي ثانية.
- ~ 1 ثانية.
- ~ 1 دقيقة
- ~ ساعة واحدة.
- ~ سنة واحدة.
- حياة أطول للكون.
الجواب:هاها لم يتم التكهن بذلك. يعتمد على المترجم.
على جهاز الكمبيوتر المحمول ، تظهر clang نتيجة حوالي 100 مللي ثانية.
دول مجلس التعاون الخليجي 57 ثانية! دقيقة! حقاً ؟!
لماذا ذلك
هناك طريقتان لتطبيق التعبيرات العادية.
أحدهما هو تحويل التعبير العادي إلى آلة حالة في O(n**2)
، للتعبير العادي عن الأحرف الطويلة n.
صعوبة المطابقة بسلسلة من الأحرف m هي O(m)
. مثل هذا التعبير العادي لا يدعم التراجع.
والثاني هو نوع من البحث الجشع مع البحث العميق. يدعم التراجع.
ومع ذلك ، لم يتم تحديد تعقيد عمليات التعبير المنتظم في المحكمة الخاصة بلبنان على الإطلاق. من الجيد أنهم تمكنوا من ذلك في دقيقة واحدة.
حول التحرك وامدا
#include <iostream> struct Foo { Foo() { std::cout << "Foo()\n"; } Foo(Foo&&) { std::cout << "Foo(Foo&&)\n"; } Foo(const Foo&) { std::cout << "Foo(const Foo&)\n"; } }; int main() { Foo f; auto a = [f = std::move(f)]() { return std::move(f); }; Foo f2(a()); return 0; }
ما الخط الذي يطبعه البرنامج؟
Foo()
Foo(Foo&&)
Foo(const Foo&)
الجواب:Foo(const Foo&)
. بشكل افتراضي ، lambdas محصنة. يضاف const
ضمنيًا إلى جميع القيم المحددة في []
.
هذا يسمح لامداس أن تتصرف مثل الوظائف العادية. لنفس الوسيطات ، قم بإرجاع نفس القيم.
ماذا يحدث في هذه الحالة؟ عندما نحاول أن نتحرك f
من دالة ، نحصل على const Foo&&
.
هذا شيء غريب جدا ، المترجم لا يعرف كيف يعمل معه وينسخ Foo
. يمكنك إصلاحه بإعلان لامدا قابلة للتغيير:
auto a = [f = std::move(f)]() mutable { return std::move(f); };
أو اصنع منشئ من Foo(const Foo&&)
.
حول س وبار
#include <iostream> int x = 0; int bar(int(x)); int main() { std::cout << bar; }
ماذا يحدث إذا حاولت ترجمة وتشغيل هذا؟
- ستطبع
0
- ستطبع
1
- ستطبع
0x0
- لا جمعت
- غير مرتبط
الجواب:سيقوم البرنامج بطباعة 1
.
لماذا ذلك
int bar(int(x));
هو إعلان دالة ، وهو ما يعادل int bar(int x);
.
إذا كنت تريد كتابة من النوع ، فأنت بحاجة إلى الكتابة مثل int bar((int(x)));
هذا int bar((int(x)));
.
ثم نحاول إخراج عنوان الوظيفة ، سيتم طرحها ضمنيًا إلى منطقية ، ولا يمكن أن يكون عنوان الوظيفة صفرًا ، أي true
لا يتم استخدام وظيفة bar()
. لذلك ، عند الربط ، لن يكون هناك رمز غير مرجعي.
حول مضمنة
#include <iostream> inline size_t factorial(size_t n) { if (n == 0) return 1; return n * factorial(n - 1); } int main() { std::cout << factorial(5) << std::endl; }
يقوم البرنامج بتجميع الروابط والروابط دون أخطاء مثل هذا g++ -c main.cpp -o main.o && g++ foo.cpp -o foo.o && g++ foo.o main.o -o test
. ماذا يحدث إذا قمت بتشغيله؟
- سيتم طباعة 120.
- يمكن أن يحدث أي شيء.
الجواب:يمكن أن يحدث أي شيء. هذا C ++.
كل المصيد في الكلمة مضمنة. هذا مجرد إشارة إلى المترجم.
يمكنه ببساطة تجميع هذه الوظيفة في ملف كائن (على الأرجح ، سيفعل ذلك للوظائف العودية).
يمكن للرابط التخلص من التكرارات للوظائف المضمنة التي لم يتم تضمينها في التعليمات البرمجية.
ملف النتائج الذي يظهر عادة في الملف الأول هو الملف الذي تم العثور عليه في ملف الكائن الأول.
سيقوم البرنامج بطباعة 0
إذا كان في foo.cpp:
#include <cstddef> inline size_t factorial(size_t n) { if (n == 0) return 0; return 2 * n * factorial(n - 1); } int foo(size_t n) { return factorial(n); }
عن المصممين
#include <iostream> struct Foo { Foo() { std::cout << "Foo()\n"; } Foo(const Foo&) { std::cout << "Foo(const Foo&)\n"; } Foo(int) { std::cout << "Foo(int)\n"; } Foo(int, int) { std::cout << "Foo(int, int)\n"; } Foo(const Foo&, int) { std::cout << "Foo(const Foo&, int)\n"; } Foo(int, const Foo&) { std::cout << "Foo(int, const Foo&)\n"; } }; void f(Foo) {} struct Bar { int i, j; Bar() { f(Foo(i, j)); f(Foo(i)); Foo(i, j); Foo(i); Foo(i, j); } }; int main() { Bar(); }
ما الخط الذي ستتم طباعته آخر مرة؟
Foo(int, int)
Foo(const Foo&, int)
Foo(int, const Foo&)
Foo(int)
الجواب:سيكون السطر الأخير Foo(const Foo&, int)
.
Foo(i)
هو تعريف لمتغير ، وهو يعادل Foo i
، مما يعني أن مجال الفئة i
سيختفي من النطاق.
الخلاصة
أتمنى أن لا ترى هذا أبداً في الكود الحقيقي.