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

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

8
สาขาที่มีพฤติกรรมที่ไม่ได้กำหนดสามารถถือว่าไม่สามารถเข้าถึงได้และปรับให้เหมาะสมเป็นรหัสตายได้หรือไม่
พิจารณาข้อความต่อไปนี้: *((char*)NULL) = 0; //undefined behavior มันก่อให้เกิดพฤติกรรมที่ไม่ได้กำหนดไว้อย่างชัดเจน การมีอยู่ของคำสั่งดังกล่าวในโปรแกรมที่กำหนดหมายความว่าโปรแกรมทั้งหมดไม่ได้กำหนดไว้หรือพฤติกรรมนั้นจะไม่ได้กำหนดก็ต่อเมื่อโฟลว์การควบคุมมาถึงคำสั่งนี้ โปรแกรมต่อไปนี้จะถูกกำหนดไว้อย่างดีในกรณีที่ผู้ใช้ไม่เคยป้อนหมายเลข3หรือไม่? while (true) { int num = ReadNumberFromConsole(); if (num == 3) *((char*)NULL) = 0; //undefined behavior } หรือเป็นพฤติกรรมที่ไม่ได้กำหนดโดยสิ้นเชิงไม่ว่าผู้ใช้จะเข้ามา? นอกจากนี้คอมไพเลอร์สามารถสันนิษฐานได้ว่าพฤติกรรมที่ไม่ได้กำหนดจะไม่ถูกดำเนินการในรันไทม์? ซึ่งจะช่วยให้สามารถใช้เหตุผลย้อนหลังได้: int num = ReadNumberFromConsole(); if (num == 3) { PrintToConsole(num); *((char*)NULL) = 0; //undefined behavior } ที่นี่คอมไพเลอร์อาจให้เหตุผลว่าในกรณีที่num == 3เรามักจะเรียกใช้พฤติกรรมที่ไม่ได้กำหนด ดังนั้นกรณีนี้จะต้องเป็นไปไม่ได้และไม่จำเป็นต้องพิมพ์หมายเลข ifคำสั่งทั้งหมดสามารถปรับให้เหมาะสมได้ …

6
เหตุใดการอ้างอิงจึงไม่ใช่ "const" ใน C ++
เราทราบว่า "ตัวแปร const" บ่งชี้ว่าเมื่อกำหนดแล้วคุณจะไม่สามารถเปลี่ยนตัวแปรได้เช่นนี้: int const i = 1; i = 2; โปรแกรมด้านบนจะไม่สามารถคอมไพล์ได้ gcc แจ้งข้อผิดพลาด: assignment of read-only variable 'i' ไม่มีปัญหาฉันเข้าใจได้ แต่ตัวอย่างต่อไปนี้อยู่นอกเหนือความเข้าใจของฉัน: #include<iostream> using namespace std; int main() { boolalpha(cout); int const i = 1; cout << is_const<decltype(i)>::value << endl; int const &ri = i; cout << is_const<decltype(ri)>::value << endl; …

2
เหตุใด C และ C ++ จึงอนุญาตให้ใช้นิพจน์ (int) + 4 * 5
(int) + 4*5; นี่คือเหตุผลที่(การเพิ่มชนิดที่มีค่า)ไปได้หรือไม่ (ลองใช้ g ++ และ gcc.) ฉันรู้ว่ามันไม่สมเหตุสมผล (และไม่มีผล) แต่ฉันอยากรู้ว่าทำไมถึงเป็นไปได้

5
C ++ - เหตุใดจึงไม่สามารถสร้างฟังก์ชันสมาชิกแบบคงที่ด้วยคุณสมบัติ 'const'
วันนี้ฉันมีปัญหา ฉันต้องการstaticฟังก์ชั่นสมาชิกconstไม่ใช่สิ่งที่จำเป็น แต่เป็นสิ่งที่ดีกว่า แต่ฉันไม่ประสบความสำเร็จในความพยายามของฉัน ใครสามารถพูดได้ว่าทำไมหรืออย่างไร?

2
เหตุใดจึงมีคลาส async state ของเครื่อง (และไม่ใช่โครงสร้าง) ใน Roslyn
ลองพิจารณาวิธีการ async ที่ง่ายมากนี้: static async Task myMethodAsync() { await Task.Delay(500); } เมื่อฉันรวบรวมสิ่งนี้ด้วย VS2013 (คอมไพเลอร์ก่อน Roslyn) สถานะเครื่องที่สร้างขึ้นจะเป็นโครงสร้าง private struct <myMethodAsync>d__0 : IAsyncStateMachine { ... void IAsyncStateMachine.MoveNext() { ... } } เมื่อฉันรวบรวมด้วย VS2015 (Roslyn) รหัสที่สร้างขึ้นคือ: private sealed class <myMethodAsync>d__1 : IAsyncStateMachine { ... void IAsyncStateMachine.MoveNext() { ... } } อย่างที่คุณเห็น Roslyn สร้างคลาส …

4
มันถูกกฎหมายหรือไม่สำหรับซอร์สโค้ดที่มีพฤติกรรมที่ไม่ได้กำหนดเพื่อทำให้คอมไพลเลอร์พัง?
สมมติว่าฉันไปรวบรวมซอร์สโค้ด C ++ ที่เขียนไม่ดีซึ่งเรียกใช้พฤติกรรมที่ไม่ได้กำหนดดังนั้น (ตามที่พวกเขาพูด) "อะไรก็เกิดขึ้นได้" จากมุมมองของข้อกำหนดภาษา C ++ ที่เห็นว่ายอมรับได้ในคอมไพเลอร์ "conformant" ทำ "อะไรก็ได้" ในสถานการณ์นี้รวมถึงคอมไพเลอร์ที่ขัดข้อง (หรือขโมยรหัสผ่านของฉันหรือทำงานผิดพลาดหรือเกิดข้อผิดพลาดในเวลาคอมไพล์) หรือเป็น ขอบเขตของพฤติกรรมที่ไม่ได้กำหนด จำกัด เฉพาะสิ่งที่สามารถเกิดขึ้นได้เมื่อเรียกใช้งานผลลัพธ์

6
ฟังก์ชั่นที่บริสุทธิ์:“ ไม่มีผลข้างเคียง” หมายถึง“ ผลลัพธ์เดียวกันเสมอให้อินพุตเดียวกัน” หรือไม่?
เงื่อนไขสองประการที่กำหนดฟังก์ชันpureดังต่อไปนี้: ไม่มีผลข้างเคียง (เช่นอนุญาตให้เปลี่ยนแปลงขอบเขตเฉพาะที่เท่านั้น) ส่งคืนเอาต์พุตเดียวกันเสมอโดยให้อินพุตเดียวกัน หากเงื่อนไขแรกเป็นจริงเสมอมีบางครั้งเงื่อนไขที่สองไม่เป็นจริงหรือไม่? คือจำเป็นจริงๆกับเงื่อนไขแรกหรือไม่?

7
ฉันสามารถใช้ NULL แทนค่า 0 ได้หรือไม่?
ฉันได้รับอนุญาตให้ใช้NULLตัวชี้แทนค่า0ใช่หรือไม่ หรือมีอะไรผิดปกติเกี่ยวกับการทำเช่นนั้น? ตัวอย่างเช่น: int i = NULL; เพื่อทดแทนสำหรับ: int i = 0; ในการทดลองฉันรวบรวมรหัสต่อไปนี้: #include <stdio.h> int main(void) { int i = NULL; printf("%d",i); return 0; } เอาท์พุท: 0 อันที่จริงมันทำให้ฉันเตือนนี้ซึ่งถูกต้องสมบูรณ์ด้วยตัวเอง: warning: initialization makes integer from pointer without a cast [-Wint-conversion] แต่ผลลัพธ์ยังคงเท่าเดิม ฉันกำลังเข้าสู่ "พฤติกรรมที่ไม่ได้กำหนด" กับสิ่งนี้หรือไม่? อนุญาตให้ใช้NULLในลักษณะนี้ได้ไหม มีอะไรผิดปกติNULLไหมในการใช้เป็นค่าตัวเลขในนิพจน์เชิงคณิตศาสตร์? และผลลัพธ์และพฤติกรรมใน C ++ สำหรับกรณีนี้คืออะไร ฉันได้อ่านคำตอบของอะไรคือความแตกต่างระหว่างโมฆะ …

5
ลำดับการประเมินดัชนีอาเรย์ (กับนิพจน์) ใน C
ดูรหัสนี้: static int global_var = 0; int update_three(int val) { global_var = val; return 3; } int main() { int arr[5]; arr[global_var] = update_three(2); } รายการอาร์เรย์ใดที่ได้รับการอัปเดต 0 หรือ 2 มีส่วนหนึ่งในสเปคของ C ที่บ่งบอกถึงความสำคัญของการดำเนินงานในกรณีนี้หรือไม่?

3
std :: vector (ab) ใช้ที่เก็บข้อมูลอัตโนมัติ
พิจารณาตัวอย่างต่อไปนี้: #include <array> int main() { using huge_type = std::array<char, 20*1024*1024>; huge_type t; } เห็นได้ชัดว่ามันจะผิดพลาดในแพลตฟอร์มส่วนใหญ่เนื่องจากขนาดสแต็คเริ่มต้นมักจะน้อยกว่า 20MB พิจารณารหัสต่อไปนี้: #include <array> #include <vector> int main() { using huge_type = std::array<char, 20*1024*1024>; std::vector<huge_type> v(1); } น่าแปลกที่มันเกิดปัญหาเช่นกัน! การย้อนกลับ (ด้วยหนึ่งในเวอร์ชันล่าสุดของ libstdc ++) นำไปสู่include/bits/stl_uninitialized.hไฟล์ซึ่งเราสามารถเห็นบรรทัดต่อไปนี้: typedef typename iterator_traits<_ForwardIterator>::value_type _ValueType; std::fill(__first, __last, _ValueType()); ตัวvectorสร้างปรับขนาดต้องเริ่มต้นองค์ประกอบและนี่คือวิธีการใช้งาน เห็นได้ชัดว่า_ValueType()ชั่วคราวเกิดปัญหาสแต็ก คำถามคือการใช้งานที่สอดคล้องหรือไม่ ถ้าใช่จริง ๆ …

2
การชนกันของเนมสเปซ C ++ ในตัวสร้างสำเนา
ฉันมีรหัสต่อไปนี้: namespace A { struct Foo { int a; }; } struct Foo { int b; }; struct Bar : public A::Foo { Bar(Foo foo) { c = foo.b; } int c; }; คอมไพเลอร์ C ++ บ่นที่ "c = foo.b" เนื่องจาก A :: Foo ไม่มีสมาชิกชื่อ b ถ้าฉันเปลี่ยนประเภทของพารามิเตอร์ Bar ด้วย :: …

3
C ++ decltype และวงเล็บ - ทำไม
มีการพูดถึง เรื่องนี้มาก่อนแต่นี่ไม่ได้ซ้ำกัน เมื่อมีคนถามถึงความแตกต่างระหว่างdecltype(a)และdecltype((a))คำตอบปกติคือ - aเป็นตัวแปร(a)คือการแสดงออก ฉันพบคำตอบนี้ไม่พอใจ อย่างแรกaคือการแสดงออกเช่นกัน ตัวเลือกสำหรับการแสดงออกหลักได้แก่ หมู่คนอื่น ๆ - (นิพจน์) ID-แสดงออก ที่สำคัญกว่านั้นการใช้ถ้อยคำสำหรับเดคไทป์จะพิจารณาวงเล็บอย่างชัดเจนมาก : For an expression e, the type denoted by decltype(e) is defined as follows: (1.1) if e is an unparenthesized id-expression naming a structured binding, ... (1.2) otherwise, if e is an unparenthesized id-expression naming a …

6
วิธีที่ถูกต้องในการแปลง 2 ไบต์เป็นจำนวนเต็ม 16 บิตที่ลงนามคืออะไร?
ในคำตอบนี้ , zwolทำให้การเรียกร้องนี้: วิธีที่ถูกต้องในการแปลงข้อมูลสองไบต์จากแหล่งข้อมูลภายนอกให้เป็นจำนวนเต็ม 16 บิตที่มีลายเซ็นคือฟังก์ชันผู้ช่วยเช่นนี้ #include <stdint.h> int16_t be16_to_cpu_signed(const uint8_t data[static 2]) { uint32_t val = (((uint32_t)data[0]) << 8) | (((uint32_t)data[1]) << 0); return ((int32_t) val) - 0x10000u; } int16_t le16_to_cpu_signed(const uint8_t data[static 2]) { uint32_t val = (((uint32_t)data[0]) << 0) | (((uint32_t)data[1]) << 8); return ((int32_t) val) - …

2
ทำไมไวยากรณ์ BNF ของ C อนุญาตการประกาศด้วยชุดคำสั่ง init ที่ว่างเปล่า
เมื่อมองผ่าน BNF ไวยากรณ์ของ C ฉันคิดว่ามันแปลกที่กฎการผลิตสำหรับการประกาศมีลักษณะเช่นนี้ (ตามhttps://cs.wmich.edu/~gupta/teaching/cs4850/sumII06/The%20syntax%20of% 20C% 20in% 20Backus-Naur% 20form.htm ): <declaration> ::= {<declaration-specifier>}+ {<init-declarator>}* ; ใช้ทำไม*ปริมาณ (หมายถึงศูนย์หรือมากกว่าเกิดขึ้น) สำหรับinit-declarator? สิ่งนี้อนุญาตให้ใช้ข้อความเช่นint;หรือvoid;เพื่อให้มีความถูกต้องทางไวยากรณ์แม้ว่าจะไม่ถูกต้องทางอรรถศาสตร์ พวกเขาไม่สามารถใช้ตัว+นับจำนวน (อย่างน้อยหนึ่งเหตุการณ์) แทน*กฎการผลิตได้หรือไม่ ฉันพยายามคอมไพล์โปรแกรมอย่างง่ายเพื่อดูว่าคอมไพเลอร์เอาท์พุทอะไรและมันทำอะไรเป็นคำเตือน การป้อนข้อมูล: int main(void) { int; } เอาท์พุท: test.c: In function ‘main’: test.c:2:5: warning: useless type name in empty declaration int; ^~~

2
ทำไม std :: hash ไม่รับประกันว่าจะถูกกำหนดขึ้น?
หลังจากนี้เราใช้N4140 (มาตรฐาน C ++ 14) ตาม§ 17.6.3.4 ต้องการแฮ , ค่าที่ส่งคืนจะขึ้นอยู่กับอาร์กิวเมนต์k ในช่วงเวลาของโปรแกรมเท่านั้น [หมายเหตุ: ดังนั้นการประเมินผลทั้งหมดของการแสดงออกh(k)ที่มีค่าเหมือนกันสำหรับ kผลผลิตผลเดียวกันสำหรับการดำเนินการที่กำหนดของโปรแกรม - บันทึกท้าย] และแฮชของเทมเพลตคลาส Class 20.9.12พูดว่า ... การเริ่มต้นhash<Key>จะต้อง: (1.1) - ตอบสนองความต้องการของแฮช (17.6.3.4) ... (1.2) - ... ซึ่งหมายความว่าค่าแฮชของvalue(เช่นhash<decltype(value)>(value)) อาจใช้ค่าอื่นหากคุณรีสตาร์ทโปรแกรม แต่ทำไม ข้อ จำกัด นี้ไม่ได้อยู่ในมาตรฐานของ C ++ 11 แต่อยู่ในมาตรฐานของ C ++ 14, C ++ 17 และ C ++ 20 ในฐานะผู้ใช้ …

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