คำถามติดแท็ก language-lawyer

สำหรับคำถามเกี่ยวกับความซับซ้อนของข้อกำหนดอย่างเป็นทางการหรือมีสิทธิ์ของภาษาโปรแกรมและสภาพแวดล้อม

13
ฉันจะสร้างลูปที่ไม่มีที่สิ้นสุดที่ไม่ได้รับการปรับให้เหมาะสมได้อย่างไร
มาตรฐาน C11 ดูเหมือนจะบ่งบอกว่างบการวนซ้ำที่มีการควบคุมการแสดงออกอย่างต่อเนื่องไม่ควรปรับให้เหมาะสม ฉันรับคำแนะนำจากคำตอบนี้ซึ่งอ้างอิงส่วน 6.8.5 จากร่างมาตรฐานโดยเฉพาะ: คำสั่งวนซ้ำซึ่งนิพจน์การควบคุมไม่ใช่นิพจน์คงที่ ... อาจถูกสันนิษฐานโดยการนำไปใช้เพื่อยุติ ในคำตอบนั้นระบุว่าการวนซ้ำเช่นwhile(1) ;นั้นไม่ควรมีการปรับให้เหมาะสม ดังนั้น ... ทำไม Clang / LLVM เพิ่มประสิทธิภาพลูปด้านล่าง (รวบรวมด้วยcc -O2 -std=c11 test.c -o test)? #include <stdio.h> static void die() { while(1) ; } int main() { printf("begin\n"); die(); printf("unreachable\n"); } บนเครื่องของฉันสิ่งนี้จะพิมพ์ออกมาbeginและเกิดปัญหากับคำสั่งที่ผิดกฎหมาย ( ud2กับดักวางไว้die()) เมื่อวันที่ godboltputsเราจะเห็นว่าไม่มีอะไรที่จะถูกสร้างขึ้นหลังจากการเรียกร้องให้ มันเป็นงานที่ยากอย่างน่าประหลาดใจที่ทำให้ Clang แสดงผลวนลูปไม่สิ้นสุดภายใต้-O2- ในขณะที่ฉันสามารถทดสอบvolatileตัวแปรซ้ำได้ซึ่งเกี่ยวข้องกับการอ่านหน่วยความจำที่ฉันไม่ต้องการ และถ้าฉันทำอะไรแบบนี้: …

5
การเข้าถึงสมาชิกสหภาพที่ไม่ได้ใช้งานและพฤติกรรมที่ไม่ได้กำหนด?
ฉันรู้สึกว่าการเข้าถึงไฟล์ unionสมาชิกนอกเหนือจากชุดสุดท้ายคือ UB แต่ดูเหมือนว่าฉันจะไม่พบข้อมูลอ้างอิงที่มั่นคง (นอกเหนือจากคำตอบที่อ้างว่าเป็น UB แต่ไม่ได้รับการสนับสนุนจากมาตรฐาน) ดังนั้นพฤติกรรมที่ไม่ได้กำหนดหรือไม่?

5
คำจำกัดความของโอเปอเรเตอร์“ ==” สำหรับ Double
ด้วยเหตุผลบางอย่างฉันแอบเข้าไปในซอร์ส. NET Framework สำหรับคลาสDoubleและพบว่าการประกาศ==คือ: public static bool operator ==(Double left, Double right) { return left == right; } ตรรกะเดียวกันนี้ใช้ได้กับทุกตัวดำเนินการ คำจำกัดความดังกล่าวคืออะไร? มันทำงานอย่างไร? เหตุใดจึงไม่สร้างการเรียกซ้ำแบบไม่สิ้นสุด
126 c#  .net  language-lawyer 

9
การ push_back องค์ประกอบจากเวกเตอร์เดียวกันปลอดภัยหรือไม่
vector<int> v; v.push_back(1); v.push_back(v[0]); หาก push_back ครั้งที่สองทำให้เกิดการจัดสรรใหม่การอ้างอิงถึงจำนวนเต็มแรกในเวกเตอร์จะใช้ไม่ได้อีกต่อไป อย่างนี้ไม่ปลอดภัยเหรอ? vector<int> v; v.push_back(1); v.reserve(v.size() + 1); v.push_back(v[0]); สิ่งนี้ทำให้ปลอดภัย?

2
แลมบ์ดาจับและพารามิเตอร์ที่มีชื่อเดียวกันใครเป็นเงาของอีกฝ่าย? (เสียงดังกับ gcc)
auto foo = "You're using g++!"; auto compiler_detector = [foo](auto foo) { std::puts(foo); }; compiler_detector("You're using clang++!"); เสียงดัง ++ 3.6.0และใหม่กว่าพิมพ์"คุณกำลังใช้เสียงดัง ++!" และเตือนเกี่ยวกับการจับภาพ fooที่ไม่ได้ใช้งาน g ++ 4.9.0และใหม่กว่าพิมพ์"คุณกำลังใช้ g ++!" และเตือนเกี่ยวกับพารามิเตอร์ fooที่ไม่ได้ใช้งาน คอมไพเลอร์ใดที่ทำตามมาตรฐาน C ++ ได้แม่นยำกว่าที่นี่ ตัวอย่าง Wandbox

6
แลมด้ากลับมาเอง: ถูกกฎหมายหรือไม่?
พิจารณาโปรแกรมที่ไร้ประโยชน์นี้: #include <iostream> int main(int argc, char* argv[]) { int a = 5; auto it = [&](auto self) { return [&](auto b) { std::cout << (a + b) << std::endl; return self(self); }; }; it(it)(4)(6)(42)(77)(999); } โดยพื้นฐานแล้วเราพยายามสร้างแลมด้าที่คืนค่าตัวเอง MSVC รวบรวมโปรแกรมและทำงาน gcc รวบรวมโปรแกรมและ segfaults เสียงดังปฏิเสธโปรแกรมด้วยข้อความ: error: function 'operator()<(lambda at lam.cpp:6:13)>' with deduced …

3
การใช้ if (0) เพื่อข้ามเคสในสวิตช์ควรจะใช้งานได้หรือไม่?
ฉันมีสถานการณ์ที่ฉันต้องการสองกรณีในคำสั่งสลับ C ++ ให้ทั้งสองตกไปอยู่ในกรณีที่สาม โดยเฉพาะกรณีที่สองจะตกไปสู่กรณีที่สามและกรณีแรกก็จะตกไปสู่กรณีที่สามโดยไม่ผ่านกรณีที่สอง ฉันมีความคิดโง่ ๆ ลองทำดูและได้ผล! ฉันห่อกรณีที่สองใน...if (0) { }ดูเหมือนว่า: #ifdef __cplusplus # include <cstdio> #else # include <stdio.h> #endif int main(void) { for (int i = 0; i < 3; i++) { printf("%d: ", i); switch (i) { case 0: putchar('a'); // @fallthrough@ if (0) { // …

2
เมื่อใดที่การเรียกใช้ฟังก์ชันสมาชิกบนอินสแตนซ์ว่างจะทำให้เกิดพฤติกรรมที่ไม่ได้กำหนด
พิจารณารหัสต่อไปนี้: #include <iostream> struct foo { // (a): void bar() { std::cout << "gman was here" << std::endl; } // (b): void baz() { x = 5; } int x; }; int main() { foo* f = 0; f->bar(); // (a) f->baz(); // (b) } เราคาดว่า(b)จะขัดข้องเนื่องจากไม่มีสมาชิกที่เกี่ยวข้องxสำหรับตัวชี้ค่าว่าง ในทางปฏิบัติ(a)ไม่ผิดพลาดเนื่องจากthisไม่เคยใช้ตัวชี้ เนื่องจาก(b)dereferences thisตัวชี้ ( …

5
เหตุใดตัวดำเนินการด้านท้ายที่มีเครื่องหมายจุลภาคจึงประเมินเพียงนิพจน์เดียวในกรณีจริง
ฉันกำลังเรียนรู้ C ++ ด้วยหนังสือ C ++ Primer และหนึ่งในแบบฝึกหัดในหนังสือเล่มนี้คือ: อธิบายว่านิพจน์ต่อไปนี้ใช้ทำอะไร: someValue ? ++x, ++y : --x, --y เรารู้อะไรบ้าง? เราทราบดีว่าตัวดำเนินการ ternary มีลำดับความสำคัญสูงกว่าตัวดำเนินการลูกน้ำ ด้วยตัวดำเนินการไบนารีสิ่งนี้ค่อนข้างเข้าใจได้ง่าย แต่สำหรับตัวดำเนินการด้านท้ายฉันกำลังดิ้นรนเล็กน้อย ด้วยตัวดำเนินการไบนารี "มีลำดับความสำคัญสูงกว่า" หมายความว่าเราสามารถใช้วงเล็บรอบนิพจน์ที่มีลำดับความสำคัญสูงกว่าและจะไม่เปลี่ยนแปลงการดำเนินการ สำหรับตัวดำเนินการ ternary ฉันจะทำ: (someValue ? ++x, ++y : --x, --y) ทำให้เกิดรหัสเดียวกันอย่างมีประสิทธิภาพซึ่งไม่ได้ช่วยฉันในการทำความเข้าใจว่าคอมไพเลอร์จะจัดกลุ่มโค้ดอย่างไร อย่างไรก็ตามจากการทดสอบกับคอมไพเลอร์ C ++ ฉันรู้ว่านิพจน์นั้นรวบรวมและฉันไม่รู้ว่าตัว:ดำเนินการใดสามารถยืนได้ด้วยตัวเอง ดังนั้นคอมไพเลอร์ดูเหมือนจะตีความตัวดำเนินการ ternary อย่างถูกต้อง จากนั้นฉันดำเนินการโปรแกรมด้วยสองวิธี: #include <iostream> int main() { bool …

2
โปรแกรมที่คอมไพล์แตกต่างกันในคอมไพเลอร์ C ++ หลัก 3 ตัว คนไหนที่ใช่?
จากการติดตามผลที่น่าสนใจ (ไม่ใช่เรื่องสำคัญในทางปฏิบัติ) สำหรับคำถามก่อนหน้าของฉัน: เหตุใด C ++ จึงอนุญาตให้เราล้อมรอบชื่อตัวแปรในวงเล็บเมื่อประกาศตัวแปร ฉันพบว่าการรวมการประกาศในวงเล็บกับคุณสมบัติชื่อคลาสที่ฉีดเข้าด้วยกันอาจนำไปสู่ผลลัพธ์ที่น่าประหลาดใจเกี่ยวกับพฤติกรรมของคอมไพเลอร์ ดูโปรแกรมต่อไปนี้: #include <iostream> struct B { }; struct C { C (){ std::cout << "C" << '\n'; } C (B *) { std::cout << "C (B *)" << '\n';} }; B *y = nullptr; int main() { C::C (y); } การคอมไพล์ด้วย g …

8
เมื่อใช้ส่วนหัว C ใน C ++ เราควรใช้ฟังก์ชันจาก std :: หรือ global namespace หรือไม่?
C ค่อนข้างไม่ตรงบางส่วนของ C ++ ดังนั้นเราจึงสามารถใช้ฟังก์ชัน / ส่วนหัว C ส่วนใหญ่ใน C ++ ได้โดยเปลี่ยนชื่อเล็กน้อย ( stdio.hto cstdio, stdlib.hto cstdlib) คำถามของฉันเป็นความหมายจริงๆ ในรหัส C ++ (โดยใช้คอมไพเลอร์ GCC เวอร์ชันใหม่ล่าสุด) ฉันสามารถโทรได้printf("Hello world!");และstd::printf("Hello world!");ทำงานได้เหมือนกันทุกประการ std::printf("Hello world!");และในการอ้างอิงฉันใช้มันก็จะปรากฏเป็น คำถามของฉันคือต้องการใช้std::printf();ใน C ++ หรือไม่? มีความแตกต่างหรือไม่?
113 c++  language-lawyer  std 

8
“ callback hell” คืออะไรและ RX แก้อย่างไรและทำไม?
ใครช่วยให้คำจำกัดความที่ชัดเจนพร้อมกับตัวอย่างง่ายๆที่อธิบายว่า "callback hell" คืออะไรสำหรับคนที่ไม่รู้จัก JavaScript และ node.js "ปัญหานรกเรียกกลับ" (ในการตั้งค่าแบบใด) เกิดขึ้นเมื่อใด ทำไมมันถึงเกิดขึ้น? "callback hell" เกี่ยวข้องกับการคำนวณแบบอะซิงโครนัสเสมอหรือไม่ หรือ "callback hell" สามารถเกิดขึ้นในแอปพลิเคชันเธรดเดียวได้หรือไม่? ฉันเข้าเรียนหลักสูตร Reactive ที่ Coursera และ Erik Meijer กล่าวในการบรรยายครั้งหนึ่งของเขาว่า RX ช่วยแก้ปัญหา "นรกเรียกกลับ" ได้ ฉันถามว่า "นรกเรียกกลับ" ในฟอรัม Coursera คืออะไร แต่ฉันไม่ได้รับคำตอบที่ชัดเจน หลังจากอธิบาย "callback hell" ในตัวอย่างง่ายๆคุณสามารถแสดงให้เห็นว่า RX แก้ปัญหา "callback hell" ในตัวอย่างง่ายๆนั้นได้อย่างไร

2
ซอร์สโค้ดมอบอำนาจ C ++ 20 ถูกเก็บไว้ในไฟล์หรือไม่
คำถามแปลก ๆ เล็กน้อยคือถ้าฉันจำไม่ผิดซอร์สโค้ด C ++ ไม่ต้องการระบบไฟล์ในการจัดเก็บไฟล์ การมีคอมไพเลอร์ที่สแกนเอกสารที่เขียนด้วยลายมือผ่านกล้องจะเป็นการใช้งานที่สอดคล้องกัน แม้ว่าในทางปฏิบัติจะไม่สมเหตุสมผลมากนัก อย่างไรก็ตาม C ++ 20 ตอนนี้เพิ่มตำแหน่งต้นทางด้วยfile_name. ตอนนี้หมายความว่าซอร์สโค้ดควรเก็บไว้ในไฟล์หรือไม่

4
อ้างอิงโมฆะได้หรือไม่?
รหัสชิ้นนี้ถูกต้อง (และพฤติกรรมที่กำหนด) หรือไม่ int &nullReference = *(int*)0; ทั้งสองกรัม ++ ++ และเสียงดังกราวรวบรวมไว้โดยไม่มีการเตือนใด ๆ แม้เมื่อใช้-Wall, -Wextra, -std=c++98, -pedantic, -Weffc++... แน่นอนว่าการอ้างอิงไม่ได้เป็นโมฆะเนื่องจากไม่สามารถเข้าถึงได้ (หมายถึงการยกเลิกการอ้างอิงตัวชี้ค่าว่าง) แต่เราสามารถตรวจสอบได้ว่าเป็นโมฆะหรือไม่โดยการตรวจสอบที่อยู่: if( & nullReference == 0 ) // null reference

2
Final vs Final อย่างมีประสิทธิภาพ - พฤติกรรมที่แตกต่างกัน
จนถึงตอนนี้ฉันคิดว่าขั้นสุดท้ายและขั้นสุดท้ายที่มีประสิทธิผลนั้นเทียบเท่ากันไม่มากก็น้อยและ JLS จะปฏิบัติต่อสิ่งเหล่านี้เหมือนกันหากไม่เหมือนกันในพฤติกรรมจริง จากนั้นฉันพบสถานการณ์ที่สร้างขึ้นนี้: final int a = 97; System.out.println(true ? a : 'c'); // outputs a // versus int a = 97; System.out.println(true ? a : 'c'); // outputs 97 เห็นได้ชัดว่า JLS สร้างความแตกต่างที่สำคัญระหว่างทั้งสองที่นี่และฉันไม่แน่ใจว่าทำไม ฉันอ่านกระทู้อื่น ๆ เช่น ความแตกต่างระหว่างขั้นสุดท้ายและขั้นสุดท้ายอย่างมีประสิทธิผล ตัวแปรสุดท้ายเทียบกับตัวแปรสุดท้ายอย่างมีประสิทธิภาพ ตัวแปรที่เป็น "ขั้นสุดท้ายอย่างมีประสิทธิภาพ" หมายความว่าอย่างไร แต่ไม่ได้ลงรายละเอียดดังกล่าว ท้ายที่สุดแล้วในระดับที่กว้างขึ้นพวกเขาดูเหมือนจะเทียบเท่ากันมาก แต่การขุดลึกลงไปเห็นได้ชัดว่าพวกเขาต่าง อะไรเป็นสาเหตุของพฤติกรรมนี้ใครสามารถให้คำจำกัดความ JLS ที่อธิบายสิ่งนี้ได้บ้าง แก้ไข: ฉันพบสถานการณ์อื่นที่เกี่ยวข้อง: …

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.