ให้ x = 10,y = 5 และ z = x*y+--y จะได้ z = 54
แต่ถ้าเขียนใหม่ เป็น z = --y+x*y จะได้ z = 44
คำถามคือ ทั้งๆที่ pre-decrement มี precedence สูงกว่า คูณ หาร แต่ทำไมอันแรกถึงไม่ทำ --y ก่อนแต่อันล่างกลับทำก่อน?
เขาหมายถึงจะทำก่อนมาบวกกัน คือ
อันแรก
xy*(--y)+ (เป็น post-order)
คือ เอา x*y แล้ว ยัดเข้า stack
จากนั้นเจอ --y จึงลดค่า y ลงหนึ่ง แล้วนำค่า y ที่ลดแล้วมาใช้ในการบวก ซึ่งทำทีหลังการลดค่า
ถ้าผมเข้าใจไม่ผิดนะครับ
+*xy--y +--y*xy
ไม่นิยามไว้ครับ ขึ้นอยู่กับคอมไพเลอร์ (ISO C99 หัวข้อ 6.5 Expression ดู footnote 73-74)
จากผลลัพธ์ข้างบน คอมไพเลอร์ทำจากซ้ายไปขวาครับ
ตัวแรก
1) _ <- x * y 2) y <- y - 1 3) z <- y + _
ตัวหลัง
1) y <- y - 1 2) _ <- x * y 3) z <- y + _
ผลลัพธ์จาก gcc 4.4 ได้ตามด้านบนครับ ส่วน visual c++ 2008 ได้ผลลัพธ์เป็น 44 ทั้งคู่
ขอบคุณทุกท่านมากครับ
ขอถามเพิ่มเติมว่า ถ้า compiler(gcc) ทำจากซ้ายไปขาย แล้วทำไม z = x*y+x*--y จึงได้ z = 80 หรอครับ คือ ถ้าทำจากซ้่ายมาขวา ผมเข้าใจว่า มันจะทำ x*y ก่อน ตามด้วย x*--y แล้วค่อยบวกกัน ซึ่งน่าจะได้ 50+40=90 แต่ไม่ใช่
จริงด้วย ดูจากไฟล์ assembly กลายเป็น
--y; y += y; z = x * y;
movl $10, 24(%esp) movl $5, 28(%esp) decl 28(%esp) movl 28(%esp), %eax addl %eax, %eax imull 24(%esp), %eax movl %eax, 4(%esp) movl $LC0, (%esp) call _printf
แถมถ้าคอมไพล์ด้วย -O2
movl $80, 4(%esp) movl $LC0, (%esp) call _printf
สรุปคือ ไม่เข้าใจเหมือนกัน
อย่าไปดู assembly ครับ เดี๋ยวงงเปล่าๆ จริงๆ ถ้าจขกท กำลังเรียนเรื่องวิชา compiler ก็ดูตามหลักการ prefix postfix ก็น่าจะพอแล้ว
ส่วนในกรณีนี้เกิดจากความพยายามทำ optimize ของ compiler ครับ
x*y+x*--y เปลี่ยนได้เป็น x*(y+--y) หรือ (y+--y)*x ครับ แต่มันเอา y+--y มาทำก่อน ก็เพราะว่า มันมี --y อยู่ ก็เลยดึงมาทำก่อนครับ
แต่ที่มันเอา y+--y มาทำก่อนเพราะเหตุผลว่า จะเอา z ไปคูณไม่ได้จนกว่าจะทำ y+y ก่อน แต่จะทำ y+y ไม่ได้จนกว่าจะทำ --y ดังนั้นผลลัพธ์มันก็เลยออกมาอย่างที่เห็น
ขอแนะนำนะครับ
ใส่วงเล็บให้เป็นนิสัยครับ สูตรคำนวน ต้องการอะไร ใส่ให้ชัดเจนไว้ มาอ่านวันหลังจะได้รู้เรื่อง เขียนไว้โล่งๆแบบนี้ บางทีหนึ่งชี่วโมงผ่านไป อาจจะลืมไปแล้วว่าสูตรนี้จะ Flow แบบไหน
a * b - c ผมยังใส่ (a * b) - c เลย
แล้วอย่าเล่นกับ --x --y ดีกว่าครับ Performance ที่ได้ ไม่น่าจะคุ้มกับความงงที่จะเกิดขึ้น มันไปตีกับ Compiler อีกตะหาก
จริงครับ สำหรับการ coding จริงๆ ทั้งวงเล็บและขึ้นบรรทัดใหม่ ถ้าทำได้โดยที่ทำให้ code ไม่รกและดูยาก ผมก็จะทำเสมอ
แต่นี่เข้าใจว่าต้องการศึกษาน่ะครับ (ไม่รู้จะอธิบายยังไงเหมือนกัน ^^')
:: DigiKin8 ::
มันเป็นเรื่องของการศึกษาน่ะครับ :-)
จะสอบแล้วอ่ะดิคับ
555
ขอบคุณทุกท่านมากครับ สรุปคือ มันขึ้นอยู่กับ compiler ว่าจะมองยังไง
เขาหมายถึงจะทำก่อนมาบวกกัน คือ
อันแรก
xy*(--y)+ (เป็น post-order)
คือ เอา x*y แล้ว ยัดเข้า stack
จากนั้นเจอ --y จึงลดค่า y ลงหนึ่ง แล้วนำค่า y ที่ลดแล้วมาใช้ในการบวก ซึ่งทำทีหลังการลดค่า
ถ้าผมเข้าใจไม่ผิดนะครับ
+*xy--y +--y*xy
ไม่นิยามไว้ครับ ขึ้นอยู่กับคอมไพเลอร์ (ISO C99 หัวข้อ 6.5 Expression ดู footnote 73-74)
จากผลลัพธ์ข้างบน คอมไพเลอร์ทำจากซ้ายไปขวาครับ
ตัวแรก
ตัวหลัง
ผลลัพธ์จาก gcc 4.4 ได้ตามด้านบนครับ
ส่วน visual c++ 2008 ได้ผลลัพธ์เป็น 44 ทั้งคู่
ขอบคุณทุกท่านมากครับ
ขอถามเพิ่มเติมว่า ถ้า compiler(gcc) ทำจากซ้ายไปขาย แล้วทำไม z = x*y+x*--y จึงได้ z = 80 หรอครับ คือ ถ้าทำจากซ้่ายมาขวา ผมเข้าใจว่า มันจะทำ x*y ก่อน ตามด้วย x*--y แล้วค่อยบวกกัน ซึ่งน่าจะได้ 50+40=90 แต่ไม่ใช่
จริงด้วย ดูจากไฟล์ assembly กลายเป็น
แถมถ้าคอมไพล์ด้วย -O2
สรุปคือ ไม่เข้าใจเหมือนกัน
อย่าไปดู assembly ครับ เดี๋ยวงงเปล่าๆ จริงๆ ถ้าจขกท กำลังเรียนเรื่องวิชา compiler ก็ดูตามหลักการ prefix postfix ก็น่าจะพอแล้ว
ส่วนในกรณีนี้เกิดจากความพยายามทำ optimize ของ compiler ครับ
x*y+x*--y เปลี่ยนได้เป็น x*(y+--y) หรือ (y+--y)*x ครับ
แต่มันเอา y+--y มาทำก่อน ก็เพราะว่า มันมี --y อยู่ ก็เลยดึงมาทำก่อนครับแต่ที่มันเอา y+--y มาทำก่อนเพราะเหตุผลว่า จะเอา z ไปคูณไม่ได้จนกว่าจะทำ y+y ก่อน แต่จะทำ y+y ไม่ได้จนกว่าจะทำ --y ดังนั้นผลลัพธ์มันก็เลยออกมาอย่างที่เห็น
ขอแนะนำนะครับ
ใส่วงเล็บให้เป็นนิสัยครับ สูตรคำนวน ต้องการอะไร ใส่ให้ชัดเจนไว้
มาอ่านวันหลังจะได้รู้เรื่อง
เขียนไว้โล่งๆแบบนี้ บางทีหนึ่งชี่วโมงผ่านไป อาจจะลืมไปแล้วว่าสูตรนี้จะ Flow แบบไหน
a * b - c ผมยังใส่ (a * b) - c เลย
แล้วอย่าเล่นกับ --x --y ดีกว่าครับ
Performance ที่ได้ ไม่น่าจะคุ้มกับความงงที่จะเกิดขึ้น
มันไปตีกับ Compiler อีกตะหาก
จริงครับ สำหรับการ coding จริงๆ ทั้งวงเล็บและขึ้นบรรทัดใหม่
ถ้าทำได้โดยที่ทำให้ code ไม่รกและดูยาก ผมก็จะทำเสมอ
แต่นี่เข้าใจว่าต้องการศึกษาน่ะครับ (ไม่รู้จะอธิบายยังไงเหมือนกัน ^^')
:: DigiKin8 ::
มันเป็นเรื่องของการศึกษาน่ะครับ :-)
จะสอบแล้วอ่ะดิคับ
555
ขอบคุณทุกท่านมากครับ สรุปคือ มันขึ้นอยู่กับ compiler ว่าจะมองยังไง