ตัวเลข int -> กฎการแปลงตัวชี้


19

พิจารณารหัสต่อไปนี้

void f(double p) {}
void f(double* p) {}

int main()
{ f(1-1); return 0; }

MSVC 2017 ไม่ได้รวบรวมสิ่งนั้น มันตัวเลขมีสายเรียกเกินไปคลุมเครือเป็น1-1เป็นเช่นเดียวกับและดังนั้นจึงสามารถแปลงเป็น0 double*เทคนิคอื่น ๆ เช่น0x0, 0Lหรือstatic_cast<int>(0)ไม่ทำงานอย่างใดอย่างหนึ่ง แม้แต่การประกาศ a const int Zero = 0และการเรียกก็f(Zero)ทำให้เกิดข้อผิดพลาดเดียวกัน มันทำงานได้เพียงอย่างถูกต้องหากไม่ได้เป็นZeroconst

ดูเหมือนว่าปัญหาเดียวกันจะใช้กับ GCC 5 และด้านล่าง แต่ไม่ใช่ GCC 6 ฉันอยากรู้ว่านี่เป็นส่วนหนึ่งของมาตรฐาน C ++, ข้อผิดพลาด MSVC ที่รู้จักหรือการตั้งค่าในคอมไพเลอร์ Google คร่าวๆไม่ได้ผลลัพธ์

คำตอบ:


18

MSVC ถือว่า1-1เป็นค่าคงที่ตัวชี้โมฆะ นี้ได้ถูกต้องโดยมาตรฐานสำหรับ C ++ 03 ซึ่งทั้งหมดแสดงออกคงที่หนึ่งที่มีค่า0เป็นค่าคงที่ชี้โมฆะ แต่มันก็มีการเปลี่ยนแปลงเพื่อให้มีเพียงศูนย์อักษรจำนวนเต็มมีค่าคงที่ชี้โมฆะสำหรับ C ++ 11 CWG ปัญหา 903 นี่คือการเปลี่ยนแปลงที่เกิดขึ้นอย่างที่คุณเห็นในตัวอย่างของคุณและตามที่ได้บันทึกไว้ในมาตรฐานด้วยโปรดดู[diff.cpp03.conv]ของมาตรฐาน C ++ 14 (ฉบับร่าง N4140)

MSVC ใช้การเปลี่ยนแปลงนี้เฉพาะในโหมดที่สอดคล้อง ดังนั้นรหัสของคุณจะรวบรวมกับ/permissive-ธง แต่ผมคิดว่าการเปลี่ยนแปลงได้ดำเนินการเฉพาะใน MSVC 2019 ดูที่นี่

ในกรณีของ GCC, GCC 5 จะใช้ค่าเริ่มต้นเป็นโหมด C ++ 98 ในขณะที่ GCC 6 และค่าเริ่มต้นในภายหลังเป็นโหมด C ++ 14 ซึ่งเป็นสาเหตุที่การเปลี่ยนแปลงในพฤติกรรมดูเหมือนจะขึ้นอยู่กับรุ่น GCC

หากคุณโทรfด้วยค่าคงที่ตัวชี้โมฆะเป็นอาร์กิวเมนต์การโทรนั้นจะคลุมเครือเนื่องจากค่าคงที่ตัวชี้โมฆะสามารถแปลงเป็นค่าตัวชี้โมฆะของประเภทตัวชี้ใด ๆ และการแปลงนี้มีอันดับเดียวกันกับการแปลงของint(หรือชนิดหนึ่ง) doubleไปยัง


-1

คอมไพเลอร์ทำงานอย่างถูกต้องตาม[over.match]และ [Conv]โดยเฉพาะ [conv.fpint] และ [conv.ptr]

ลำดับการแปลงมาตรฐานคือ [blah blah] เป็นศูนย์หรือหนึ่ง [... ] การแปลงแบบอินทิกรัลแบบลอยตัว, การแปลงพอยน์เตอร์, [... ]

และ

prvalue ของประเภทจำนวนเต็มหรือประเภทการแจงนับไม่ได้ จำกัด สามารถแปลงเป็น prvalue ของชนิดทศนิยม ผลลัพธ์จะถูกต้องหากเป็นไปได้ [blah blah]

และ

ค่าคงที่ตัวชี้ null เป็นตัวอักษรจำนวนเต็มที่มีค่าเป็นศูนย์หรือ [... ] ค่าคงที่ตัวชี้โมฆะสามารถแปลงเป็นประเภทตัวชี้; ผลลัพธ์คือค่าตัวชี้โมฆะของประเภทนั้น [blah blah]

ตอนนี้ความละเอียดเกินพิกัดคือการเลือกการจับคู่ที่ดีที่สุดในทุกฟังก์ชั่นผู้สมัคร (ซึ่งเป็นคุณสมบัติที่สนุกสนานไม่จำเป็นต้องสามารถเข้าถึงได้แม้ในตำแหน่งการโทร!) การจับคู่ที่ดีที่สุดคืออันที่มีพารามิเตอร์ที่แน่นอนหรือการแปลงที่เป็นไปได้น้อยที่สุด การแปลงมาตรฐานอาจเป็นศูนย์หรือหนึ่งรายการ (... สำหรับทุกพารามิเตอร์) และศูนย์จะ "ดีกว่า" มากกว่าหนึ่งรายการ

(1-1)0เป็นตัวอักษรจำนวนเต็มมีค่า

คุณสามารถแปลงตัวอักษรเป็นศูนย์จำนวนเต็มแต่ละอย่างใดอย่างหนึ่งdoubleหรือdouble*(หรือnullptr_t) กับอีกหนึ่งแปลง ดังนั้นสมมติว่ามีฟังก์ชั่นมากกว่าหนึ่งฟังก์ชั่นนี้ถูกประกาศ (ตามตัวอย่างในกรณี) มีผู้สมัครมากกว่าหนึ่งคนและผู้สมัครทุกคนดีเท่ากันไม่มีการแข่งขันที่ดีที่สุด มันคลุมเครือและคอมไพเลอร์ก็ถูกต้องเกี่ยวกับการบ่น


1
วิธีการคืออักษรจำนวนเต็ม ? มันคือการแสดงออกที่มีสองตัวอักษรจำนวนเต็มที่มีมูลค่าและผู้ประกอบการ 1-11-
walnut

@walnut: คุณอาจหมายถึงถ้อยคำที่น่าอึดอัดใจ"ลำดับของไบนารีตัวเลขแปดหลักตัวเลขหรือเลขฐานสิบหกหลัก" นั่นเป็นถ้อยคำที่ค่อนข้างโชคร้ายสำหรับบางสิ่งที่ค่อนข้าง "ชัดเจน" ซึ่งแนะนำสิ่งที่ไม่ใช่กรณี (เช่นไม่รวมอักขระลบ) ด้วย "หลัก" เพียงอย่างเดียวและตามคำจำกัดความของ "หลัก" (หนึ่งใน 0 ... 9) มันเป็นไปไม่ได้ที่จะมีตัวอักษรเชิงลบใด ๆ (เช่น-1) ซึ่งเนื่องจากประเภทเริ่มต้นมีการลงนามอย่างไรก็ตามมีความจำเป็นอย่างชัดเจนและเป็นไปได้ที่สามารถพิสูจน์ได้ (และยอมรับในระดับสากล) ด้วย
Damon

1
ผมหมายถึงไวยากรณ์สำหรับจำนวนเต็มตัวอักษร1-1ที่แสดงในการเชื่อมโยงมาตรฐานซึ่งไม่ตรงกับ C ++ ไม่มีตัวอักษรจำนวนเต็มลบ -1คือนิพจน์ที่ประกอบด้วย1จำนวนเต็มตามตัวอักษรและชนิดตัว-ดำเนินการลบ ดูเพิ่มเติมส่วน "หมายเหตุ" บน cppreference.com
walnut

มันเป็นความจริงอย่างแน่นอนว่าไวยากรณ์ไม่ได้มี แต่ที่ไม่กว้างขวาง ตามความจำเป็นและตามคำนิยาม C ++ จะมีตัวอักษรเชิงลบมากยกเว้นว่าคุณจะต่อท้ายอย่างชัดเจนuตัวอักษรของคุณคือตามคำนิยามที่ลงชื่อ ประเภทที่เซ็นชื่อมีค่าลบ (ประมาณ 50% ของค่าที่เป็นไปได้คือค่าลบ) มันเป็นเรื่องโชคร้ายที่ไวยากรณ์ (ด้วยเหตุผลที่ฉันไม่รู้) กำลังทำให้เข้าใจผิดในลักษณะนี้และถึงแม้ว่าในทางเทคนิค (ตามหลักไวยากรณ์) -1 นั้นเป็นตัวอักษรที่เป็นบวกบวกเมื่อตะกี้โดยวิธีอื่น ๆ ทั้งหมดนั้นเป็นลบ ตามตัวอักษร เหมือน 3 + 4 เป็นตัวอักษร
Damon

โดยวิธีการ - 0Uฉันพยายาม ปัญหาเดียวกัน สิ่งที่ฉันไม่ได้ลองคือสิ่งที่มีenumค่า บางทีคนที่มีชื่ออาจจะเปลี่ยนสิ่งต่าง ๆ ฉันสิ้นสุดการเขียนการแสดงออกยาวกับและdecltype remove_reference
user1334767
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.