ตัวดำเนินการ“ ->” ใน C ++ คืออะไร


8924

หลังจากที่ได้อ่านคุณลักษณะที่ซ่อนอยู่และมุมมืดของ C ++ / STLบนcomp.lang.c++.moderatedฉันรู้สึกประหลาดใจอย่างสมบูรณ์ที่ต่อไปนี้ข้อมูลที่รวบรวมและทำงานทั้งใน Visual Studio 2008 และ G ++ 4.4

นี่คือรหัส:

#include <stdio.h>
int main()
{
    int x = 10;
    while (x --> 0) // x goes to 0
    {
        printf("%d ", x);
    }
}

เอาท์พุท:

9 8 7 6 5 4 3 2 1 0

ฉันคิดว่านี่คือ C เพราะมันใช้ได้ใน GCC เช่นกัน สิ่งนี้นิยามไว้ที่ไหนในมาตรฐานและมาจากที่ไหน


503
หรือแม้กระทั่งระยะห่างที่เหมาะสมเพียงแค่ ... ฉันไม่คิดว่าฉันเคยเห็นช่องว่างระหว่างตัวแปรและทั้ง++หรือ--ก่อน ...
แมทธิว Scharley

1154
ตัวดำเนินการ "ไปที่" นี้สามารถเปลี่ยนกลับได้ (0 <- x) และยังมีโอเปอเรเตอร์ "run to" (0 <---- x) Geez สิ่งที่สนุกที่สุดที่ฉันเคยได้ยินคือ c ++ syntax =) +1 สำหรับคำถาม
SadSido

233
สนุกมากถึงแม้ว่าการตีความจะผิดมาก แต่ก็อธิบายได้ว่ารหัสทำงานอย่างถูกต้อง :)
Noldorin

811
#define upto ++<ลองจินตนาการถึงความเป็นไปได้ไวยากรณ์ใหม่ #define downto -->, หากคุณรู้สึกชั่วร้ายคุณสามารถทำ#define for while(และ#define do ) {(และ#define done ;}) และเขียนfor x downto 0 do printf("%d\n", x) doneโอ้มนุษย์ ...
Chris Lutz

98
เปิดความเป็นไปได้ของวิธีการเข้ารหัสใหม่ที่แสดงออกได้ดีคุ้มค่าที่จะเสียสละบางคำเตือนของคอมไพเลอร์สำหรับ: bool CheckNegative (int x) {return x <0? ถูกผิด ); }
TTT

คำตอบ:


8602

-->ไม่ใช่ผู้ประกอบการ มันเป็นความจริงสองผู้ประกอบการที่แยกจากกันและ-->

การลดลงของรหัสตามเงื่อนไขxในขณะที่ส่งคืนค่าxดั้งเดิม (ไม่ลดลง) แล้วเปรียบเทียบค่าเดิมกับการ0ใช้ตัว>ดำเนินการ

เพื่อความเข้าใจที่ดีขึ้นสามารถเขียนข้อความดังต่อไปนี้:

while( (x--) > 0 )

262
จากนั้นอีกครั้งมันจะมีลักษณะเหมือนตัวดำเนินการช่วงบางชนิดในบริบทนั้น
ชาร์ลส์ซัลเวีย

109
การบอกว่า x ลดการโพสต์แล้วเปรียบเทียบกับ 0 เหมือนกับการบอกว่า x ลดลงหลังจากถูกเปรียบเทียบกับ 0
Charles Salvia

8
ฉันไม่คิดว่ามันจะเหมือนกัน ฉันคิดว่าคำว่า "แล้ว" หมายถึงมีคำสั่งซื้อ (หลังจากการลดลงโพสต์ค่าของ x คือหนึ่งน้อยกว่า) ฉันคิดว่ามีคนพูดว่า "คุณกำลังโพสต์ลดค่า x แล้วเปรียบเทียบค่าเก่ากับ 0 ... " เพื่อให้ชัดเจนขึ้น แต่นี่ก็เป็น nitpicking อยู่ดี เราทุกคนรู้ว่าสิ่งที่มีความหมาย
Johannes Schaub - litb

38
ใน Java ก็ยังรวบรวม :)
สตีเว่น Devijver

44
ชื่อของมันคือ @Jay เป็นรูปแบบการเขียนโปรแกรมที่ไม่ดี :-) นี่เป็นหลักฐานตามความจริงที่ว่าคำถามถูกถามตั้งแต่แรก มันสมเหตุสมผลมากกว่าที่จะผูกโอเปอเรเตอร์กับสิ่งที่พวกเขากำลังดำเนินการอยู่แทนที่จะเป็นสิ่งที่ไม่เกี่ยวข้องดังนั้นwhile (x-- > 0)จะเหมาะกว่า นอกจากนี้ยังทำให้ชัดเจนยิ่งขึ้นว่าเกิดอะไรขึ้น (อย่างน้อยในตัวแก้ไขฟอนต์คงที่) ซึ่งหมายความว่าไม่จำเป็นต้องใช้วงเล็บในคำตอบนี้
paxdiablo

3131

หรือสำหรับบางสิ่งบางอย่างที่แตกต่างกันอย่างสิ้นเชิง ... สไลด์ไปx0

while (x --\
            \
             \
              \
               > 0)
     printf("%d ", x);

ไม่ใช่ทางคณิตศาสตร์ แต่ ... ทุกภาพวาดพันคำ ...


216
@mafutrct - ตามที่ฉันจำได้ \ ใน C เพียงต่อท้ายบรรทัดถัดไปราวกับว่าไม่มีการแบ่งบรรทัด ที่นี่ไม่มีอะไรทำ
โฮแกน

2
@mafu อักขระ '\' จะบอกคอมไพเลอร์ว่าบรรทัดปัจจุบันดำเนินต่อไปในบรรทัดถัดไปดังนั้นคอมไพเลอร์ควรผสานทั้งสองบรรทัดและคอมไพล์เป็นหนึ่ง 'while (x -> 0)' จะทำงานจนกระทั่ง x เท่ากับ -1 แต่วิธีที่เขาสร้างการเยื้องทำให้มันดูเหมือนว่า x เลื่อนเป็นศูนย์ 'ในขณะที่ x เลื่อนเป็น 0 ... '
Felype

16
IIRC, K&R C อนุญาตให้มีช่องว่างระหว่าง '-'s ในตัวดำเนินการลดค่าซึ่งในกรณีนี้คุณอาจมีแบ็กสแลชอยู่ตรงกลางซึ่งจะดูเย็นกว่า :)
Jules

10
@ArnavBorborah มันเป็นความหมายการแสดงออกเก่าwhy waste words when a picture does a better jobใช้เป็นเรื่องตลกในบริบทนี้ (มีอยู่ในความเป็นจริง 2 คำหลักwhileและprintf)
ไนซ์

88
อ่าใช่ผู้ควบคุมสไลด์ที่ไม่ชัดเจน ฉันจะลืมได้อย่างไร!
demonkoryu

2377

นั่นเป็นตัวดำเนินการที่ซับซ้อนมากดังนั้นแม้ISO / IEC JTC1 (คณะกรรมการด้านเทคนิคร่วม 1)วางคำอธิบายไว้ในสองส่วนที่แตกต่างกันของมาตรฐาน C ++

พวกเขาเป็นตัวดำเนินการที่ต่างกันสองตัว: --และ>อธิบายตามลำดับใน§5.2.6 / 2 และ§5.9ของมาตรฐาน C ++ 03


1277

มันเทียบเท่ากับ

while (x-- > 0)

x--(การลดลงภายหลัง) เทียบเท่ากับx = x-1ดังนั้นรหัสแปลงเป็น:

while(x > 0) {
    x = x-1;
    // logic
}
x--;   // The post decrement done when x <= 0

15
มันไม่ถูกต้องนัก ค่าของ x ภายในร่างกายลูปจะแตกต่างกันในกรณีที่สอง คำสั่งการมอบหมายในตัวอย่างของคุณควรอยู่เหนือตรรกะเพื่อให้เทียบเท่า Postfix - ลบ 1 แต่การเปรียบเทียบจะเกิดขึ้นกับค่าก่อนหน้าการลบ
uliwitness

4
@uliwitness สิ่งเหล่านี้เทียบเท่ากันอย่างแท้จริง มันจะผิดถ้ามีการใช้คำนำหน้า: 0 >-- xในกรณีนี้xจะลดลงก่อนตรรกะ ใน postfix ลอจิกจะดำเนินการก่อนที่จะลดลงและทำให้ทั้งสองตัวอย่างจะเทียบเท่า อย่าลังเลที่จะเขียนพวกเขาในConsoleและทดสอบพวกเขา
Candleshark

12
พวกเขายังไม่เทียบเท่า หลังจากลูปแรก, x คือ -1 (หรือ overflown ในกรณีที่มันไม่ได้ลงนาม), หลังจากที่สอง, มันคือ 0 (สมมติว่า x เริ่มต้นที่ไม่เป็นลบ, ทั้งลูปจะแก้ไข x หรือตัวแตกหรือ ... )
Caesar

1
while(x=x-1,x+1 > 0)เทียบเท่า
SS Anne

2
@Shebham ต่อไปนี้เป็นตัวอย่างตัวนับ: ถ้า x เริ่มต้นเป็น 0 ภายใต้ลูปดั้งเดิมมันจะออกเป็น -1 ด้วยเวอร์ชันของคุณมันจะยังคงเป็นศูนย์ ดังนั้นพวกเขาจึงไม่เทียบเท่า
Elliott

1208

x สามารถไปที่ศูนย์ได้เร็วขึ้นในทิศทางตรงกันข้าม:

int x = 10;

while( 0 <---- x )
{
   printf("%d ", x);
}

8 6 4 2

คุณสามารถควบคุมความเร็วด้วยลูกศร!

int x = 100;

while( 0 <-------------------- x )
{
   printf("%d ", x);
}

90 80 70 60 50 40 30 20 10

;)


6
ระบบปฏิบัติการชนิดใดที่เอาต์พุตนี้สร้างขึ้นฉันใช้ Ubuntu 12.04 ซึ่งฉันมีข้อความแสดงข้อผิดพลาด
Bhuvanesh

74
แม้ว่ามันควรจะชัดเจน แต่สำหรับทุกคนที่ยังใหม่กับ C ++ ที่อ่านข้อความนี้: อย่าทำเช่นนั้น เพียงใช้การกำหนดเพิ่มเติมหากคุณต้องการเพิ่ม / ลดจำนวนมากกว่าหนึ่งรายการ
Blimeo

263
ศูนย์ด้วย "เลเซอร์" ในขณะที่ (0> - - - - - - - - - - ---------- x) ... เอาท์พุทเดียวกัน
ซามูเอลแดเนียล

4
@ ฟอร์ดคุณแน่ใจหรือว่าไม่ได้รวบรวม? -> coliru.stacked-crooked.com/a/5aa89a65e3a86c98
doc

18
@doc มันรวบรวมใน c ++ แต่ไม่ใช่ใน c
phord

548

มัน

#include <stdio.h>
int main(void){
     int x = 10;

     while( x-- > 0 ){ // x goes to 0

       printf("%d ", x);
     }

     return 0;
}

แค่พื้นที่ทำให้สิ่งต่าง ๆ ดูตลก--ลดลงและ>เปรียบเทียบ


431

การใช้งานของ-->มีความเกี่ยวข้องทางประวัติศาสตร์ การลดลงคือ (และยังคงอยู่ในบางกรณี) เร็วกว่าการเพิ่มขึ้นของสถาปัตยกรรม x86 การใช้การ-->แนะนำที่xกำลังจะเกิดขึ้น0และดึงดูดผู้ที่มีภูมิหลังทางคณิตศาสตร์


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

25
ทีนี้การลดลงสู่ศูนย์หมายความว่าคุณต้องเปรียบเทียบกับ 0 ต่อการวนซ้ำวนซ้ำเท่านั้นในขณะที่การวนซ้ำไปทาง n หมายถึงการเปรียบเทียบกับการวนซ้ำแต่ละครั้ง อดีตมีแนวโน้มที่จะง่ายขึ้น (และในบางสถาปัตยกรรมทดสอบโดยอัตโนมัติหลังจากการดำเนินการลงทะเบียนข้อมูลทุกครั้ง)
Joey Adams

9
@Burrito แม้ว่าฉันจะไม่เห็นด้วย แต่ลูปที่มีค่าไม่เป็นศูนย์มักจะทำนายได้อย่างสมบูรณ์แบบ
Duncan

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

7
แน่นอนทั้งหมดนี้เป็นสิ่งที่สงสัยในวันนี้เนื่องจากคอมไพเลอร์ที่ทันสมัยสามารถ vectorize และย้อนกลับลูปโดยอัตโนมัติ
Lambda Fairy


362

เกินบรรยาย แต่ฉันจะใช้สิ่งนี้:

#define as ;while

int main(int argc, char* argv[])
{
    int n = atoi(argv[1]);
    do printf("n is %d\n", n) as ( n --> 0);
    return 0;
}

17
@SAFX - มันจะเป็นอักษรอียิปต์โบราณอย่างสมบูรณ์แบบด้วยวงเล็บอียิปต์
mouviciel

1
สิ่งนี้ไม่ได้รวบรวม C ไม่ใช่ Pascal ซึ่งการตกแต่งภายในdo ... whileเป็นรายการคำสั่ง ใน C do { ... } whileมันเป็นบล็อกดังนั้นจึงต้อง
user207421

25
@EJP มันจะรวบรวม do statement while ( expression ) ;ไวยากรณ์ ต้องบอกว่าฉันหวังว่ามันจะเข้าใจว่าฉันหมายถึงตัวอย่างเป็นเรื่องตลก
Escualo

321

หนังสือเล่มหนึ่งที่ฉันอ่าน (ฉันจำไม่ถูกต้องว่าหนังสือเล่มใด) ที่ระบุไว้: คอมไพเลอร์พยายามแยกการแสดงออกของโทเค็นที่ใหญ่ที่สุดโดยใช้กฎด้านซ้ายขวา

ในกรณีนี้การแสดงออก:

x-->0

แยกวิเคราะห์โทเค็นที่ใหญ่ที่สุด:

token 1: x
token 2: --
token 3: >
token 4: 0
conclude: x-- > 0

กฎเดียวกันนี้ใช้กับนิพจน์นี้:

a-----b

หลังจากแยกวิเคราะห์:

token 1: a
token 2: --
token 3: --
token 4: -
token 5: b
conclude: (a--)-- - b

ฉันหวังว่านี่จะช่วยให้เข้าใจการแสดงออกที่ซับซ้อนได้ ^^


98
คำอธิบายที่สองของคุณไม่ถูกต้อง คอมไพเลอร์จะเห็นa-----bและคิด(a--)-- - bซึ่งไม่คอมไพล์เพราะa--ไม่ส่งคืนค่า lvalue
Tim Leaf

22
นอกจากนี้xและ--เป็นโทเค็นแยกสอง
Roland Illig

23
@DoctorT: มันผ่าน lexer semantic pass เท่านั้นที่สามารถส่งข้อผิดพลาดนั้นได้ ดังนั้นคำอธิบายของเขาถูกต้อง
v.oddou

9
ตราบใดที่คุณคิดว่า-->เป็นผู้ประกอบการ (ซึ่งเป็นสิ่งที่ส่อให้เห็นโดยมีคำถามที่ถูกถาม) คำตอบนี้ไม่เป็นประโยชน์เลย - คุณจะคิดว่าโทเค็นที่ 2 คือไม่เพียง--> --หากคุณรู้ว่า-->ไม่ใช่ตัวดำเนินการคุณอาจไม่มีปัญหาในการทำความเข้าใจรหัสในคำถามดังนั้นหากคุณไม่มีคำถามที่แตกต่างไปจากเดิมอย่างสิ้นเชิงฉันไม่แน่ใจว่าสิ่งนี้มีประโยชน์อย่างไร
Bernhard Barker

4
ตัวอย่าง @DoctorT สามารถแก้ไขได้โดยสมมติว่าaมีตัวดำเนินการ post-decrement มากเกินไปซึ่งจะส่งคืน lvalue coliru.stacked-crooked.com/a/e1effc351ae79e9f
doc

275

ตรงนี้เป็นเช่นเดียวกับ

while (x--)
{
   printf("%d ", x);
}

สำหรับตัวเลขที่ไม่ใช่ลบ


153
สิ่งนี้ไม่ควรเป็นfor(--x++;--x;++x--)หรือ
Mateen Ulhaq

9
@DoctorT นั่นเป็นสิ่งที่unsignedมีไว้สำหรับ
โคลจอห์นสัน

12
@MateenUlhaq นั่นเป็นสิ่งที่ผิดตามมาตรฐานการแสดงออก--x++มีพฤติกรรมที่ไม่ได้กำหนดตาม§1.9.15
WorldSEnder

หากใช้งานอยู่จะใช้unsignedมัน%u
Cacahuete Frito

242

อย่างไรก็ตามเรามีโอเปอเรเตอร์ "ไปที่" แล้ว "-->"ง่ายต่อการจดจำเป็นทิศทางและ "ในขณะที่ x ไปที่ศูนย์" เป็นความหมายตรง

นอกจากนี้ยังมีประสิทธิภาพมากกว่า"for (x = 10; x > 0; x --)"ในบางแพลตฟอร์มเล็กน้อย


17
จะไม่เป็นจริงเสมอโดยเฉพาะเมื่อค่าของ x เป็นลบ
พระพิฆเนศ Gopalasubramanian

15
รุ่นอื่นไม่ทำสิ่งเดียวกัน - โดยfor (size_t x=10; x-->0; )เนื้อความของลูปจะถูกดำเนินการกับ 9,8, .. , 0 ในขณะที่เวอร์ชันอื่นมี 10,9, .. , 1 มันค่อนข้างยุ่งยากในการออกจากลูปลงไปที่ศูนย์ด้วยตัวแปรที่ไม่ได้ลงนาม
Pete Kirkham

4
ฉันคิดว่านี่เป็นสิ่งที่ทำให้เข้าใจผิดเล็กน้อย ... เราไม่มีตัวดำเนินการ "ไปที่" อย่างแท้จริงเนื่องจากเราต้องการ++>ให้ผู้อื่นทำงานที่เพิ่มขึ้น
tslmy

19
@Josh: ที่จริงแล้วการล้นมีพฤติกรรมที่ไม่ได้กำหนดไว้intดังนั้นมันก็สามารถกินสุนัขของคุณได้อย่างง่ายดายเช่นเดียวxกับให้เป็นศูนย์ถ้ามันเริ่มเป็นลบ
SamB

3
นี่เป็นสำนวนที่สำคัญมากสำหรับฉันเนื่องจากเหตุผลที่กำหนดไว้ใน comnmet โดย @PeteKirkham เนื่องจากฉันต้องลดลูปในปริมาณที่ไม่ได้ลงนามตลอด0เวลา (สำหรับการเปรียบเทียบสำนวนของถนัดการทดสอบสำหรับศูนย์เช่นการเขียนwhile (n--)แทนไม่ได้ลงนามn, ซื้อคุณไม่มีอะไรและสำหรับฉันอย่างมาก hampers การอ่าน.) นอกจากนี้ยังมีคุณสมบัติที่น่ารื่นรมย์ที่คุณระบุอีกหนึ่งกว่าดัชนีเริ่มต้นซึ่งเป็นสิ่งที่มักจะ คุณต้องการ (เช่นสำหรับวงรอบอาร์เรย์ที่คุณระบุขนาดของมัน) ฉันชอบที่-->ไม่มีที่ว่างเพราะนี่ทำให้สำนวนง่ายต่อการจดจำ
Marc van Leeuwen

221

รหัสนี้เปรียบเทียบ x และ 0 ก่อนแล้วจึงลดลง x (ยังกล่าวในคำตอบแรก: คุณโพสต์ลดลง x แล้วเปรียบเทียบ x และ 0 กับ>ผู้ประกอบการ) ดูผลลัพธ์ของรหัสนี้:

9 8 7 6 5 4 3 2 1 0

ตอนนี้เราเปรียบเทียบก่อนแล้วลดลงโดยเห็น 0 ในผลลัพธ์

หากเราต้องการลดอันดับแรกจากนั้นเปรียบเทียบใช้รหัสนี้:

#include <stdio.h>
int main(void)
{
    int x = 10;

    while( --x> 0 ) // x goes to 0
    {
        printf("%d ", x);
    }
    return 0;
}

ผลลัพธ์นั้นคือ:

9 8 7 6 5 4 3 2 1

177

คอมไพเลอร์ของฉันจะพิมพ์ออกมา 9876543210 เมื่อฉันเรียกใช้รหัสนี้

#include <iostream>
int main()
{
    int x = 10;

    while( x --> 0 ) // x goes to 0
    {
        std::cout << x;
    }
}

อย่างที่คาดไว้. ความwhile( x-- > 0 )หมายที่while( x > 0)แท้จริง x--โพสต์ xdecrements

while( x > 0 ) 
{
    x--;
    std::cout << x;
}

เป็นวิธีที่แตกต่างในการเขียนสิ่งเดียวกัน

เป็นเรื่องที่ดีที่ต้นฉบับดูเหมือนว่า "ในขณะที่ x ไปที่ 0"


4
ผลลัพธ์จะไม่ถูกกำหนดเฉพาะเมื่อคุณกำลังเพิ่ม / ลดลงของตัวแปรเดียวกันมากกว่าหนึ่งครั้งในคำสั่งเดียวกัน มันใช้ไม่ได้กับสถานการณ์นี้
Tim Leaf

13
while( x-- > 0 ) actually means while( x > 0)- ฉันไม่แน่ใจว่าสิ่งที่คุณกำลังพยายามที่จะพูดที่นั่น แต่วิธีที่คุณพูดมันหมายถึง--ไม่มีความหมายใด ๆ ซึ่งเห็นได้ชัดว่าผิดมาก
Bernhard Barker

ในการผลักดันจุดกลับบ้านจาก @Dukeling คำตอบนี้ไม่เหมือนกับโพสต์ต้นฉบับ ในโพสต์เดิมxจะเป็น-1หลังจากที่ออกจากวงในขณะที่ในคำตอบนี้จะเป็นx 0
Mark Lakata

148

มีช่องว่างระหว่าง--และ>ถึง xถูกโพสต์ decremented ที่เป็น decremented x>0 ?หลังจากการตรวจสอบสภาพ


42
พื้นที่ไม่ได้หายไป - C (++) ละเว้นช่องว่าง

27
@ H2CO3 นี่ไม่เป็นความจริงโดยทั่วไป มีสถานที่ที่มีพื้นที่สีขาวจะต้องใช้ราชสกุลแยกต่างหากเช่นในเป็นเมื่อเทียบกับ#define foo() #define foo ()
เจนส์

30
@Jens วิธีการเกี่ยวกับ: "พื้นที่ไม่ได้หายไป - C (++) ละเว้นพื้นที่สีขาวที่ไม่จำเป็น"
Kevin P. Rice

139

--เป็นตัวดำเนินการลดค่าและ>เป็นตัวดำเนินการมากกว่า

-->สองผู้ประกอบการจะนำไปใช้เป็นหนึ่งเดียวเช่น


11
พวกเขากำลังนำไปใช้เป็นตัวดำเนินการ 2 ที่แยกต่างหาก พวกเขาเขียนเพียงทำให้เข้าใจผิดเพื่อดูเหมือนว่า "คนเดียว"
underscore_d

129

มันเป็นการรวมกันของผู้ให้บริการสองราย อันดับแรก--คือการลดค่าและ>สำหรับการตรวจสอบว่าค่ามากกว่าตัวถูกดำเนินการทางขวาหรือไม่

#include<stdio.h>

int main()
{
    int x = 10;

    while (x-- > 0)
        printf("%d ",x);

    return 0;
}

ผลลัพธ์จะเป็น:

9 8 7 6 5 4 3 2 1 0            

122

ที่จริงแล้วxมีการโพสต์ลดลงและมีการตรวจสอบเงื่อนไขที่ มันไม่ใช่-->มัน(x--) > 0

หมายเหตุ: ค่าของxจะถูกเปลี่ยนหลังจากตรวจสอบเงื่อนไขแล้วเนื่องจากมีการเปลี่ยนแปลงภายหลัง บางกรณีที่คล้ายกันสามารถเกิดขึ้นได้เช่น:

-->    x-->0
++>    x++>0
-->=   x-->=0
++>=   x++>=0

6
ยกเว้นว่า ++> แทบจะไม่สามารถใช้งานได้สักพัก ตัวดำเนินการ "ไปถึง ... " จะเป็น ++ <ซึ่งดูไม่ดีเท่าที่ควร ตัวดำเนินการ -> เป็นเรื่องบังเอิญที่มีความสุข
Florian F

2
@BenLeggiero นั่นอาจ 'ทำงาน' ในแง่ของการสร้างรหัสที่ทำอะไรบางอย่าง (ในขณะที่ผู้อ่านที่ไม่ชอบรหัสมารยาทที่ฉลาด) แต่ความหมายแตกต่างกันเนื่องจากความหมายของการใช้ predecrement จะทำให้เกิดการวนซ้ำน้อยลง เป็นตัวอย่างที่วางแผนไว้มันจะไม่ดำเนินการลูปร่างกายถ้าxเริ่มต้นที่ 1 แต่while ( (x--) > 0 )จะ {แก้ไข} Eric Lippert ครอบคลุมทั้งในบันทึกย่อประจำรุ่น C # 4 ของเขา: blogs.msdn.microsoft.com/ericlippert/2010/04/01/…
underscore_d

120

CและC ++ปฏิบัติตามกฎ "การทำลายล้างสูงสุด" วิธีเดียวกัน --- ขแปลไป(a--) - bในกรณีของคุณ จะแปลว่าx-->0(x--)>0

สิ่งที่กฏบอกเป็นหลักคือไปทางซ้ายไปทางขวานิพจน์เกิดขึ้นจากการใช้อักขระสูงสุดซึ่งจะทำให้เกิดนิพจน์ที่ถูกต้อง


5
ซึ่งเป็นสิ่งที่ OP ถือว่า: "((a) ->)" เป็นแทะเล็มสูงสุด ปรากฎว่าสมมติฐานดั้งเดิมของ OP ไม่ถูกต้อง: "->" ไม่ใช่ตัวดำเนินการที่ถูกต้องสูงสุด
david

4
หรือที่เรียกว่าการแยกวิเคราะห์โลภถ้าฉันจำได้อย่างถูกต้อง
Roy Tinker

1
@RoyTinker การสแกนโลภ โปรแกรมแยกวิเคราะห์ไม่มีส่วนเกี่ยวข้องกับสิ่งนี้
user207421

27

ทำไมต้องเกิดภาวะแทรกซ้อนทั้งหมด?

คำตอบง่ายๆสำหรับคำถามต้นฉบับคือ:

#include <stdio.h>
int main()
{
    int x = 10;
    while (x > 0) 
    {
        printf("%d ", x);
        x = x-1;
    }
}

ทำสิ่งเดียวกัน ไม่ได้บอกว่าคุณควรทำแบบนี้ แต่ทำสิ่งเดียวกันและจะตอบคำถามในโพสต์เดียว

x--เป็นเพียงชวเลขข้างต้นและเป็นเพียงมากขึ้นกว่าปกติ> operatorไม่มีความลึกลับที่ยิ่งใหญ่!

ทุกวันนี้มีคนจำนวนมากที่สร้างสิ่งเรียบง่ายซับซ้อน)


17
คำถามนี้ไม่เกี่ยวกับภาวะแทรกซ้อน แต่เกี่ยวกับ ** คุณสมบัติที่ซ่อนอยู่และมุมมืดของ C ++ / STL **
pix

20
โปรแกรมที่นี่ให้เอาต์พุตที่แตกต่างจากต้นฉบับเนื่องจาก x ที่นี่ลดลงหลังจาก printf นั่นแสดงให้เห็นว่า "คำตอบง่าย ๆ " นั้นมักจะไม่ถูกต้อง
Öö Tiib

2
The OP's way: 9 8 7 6 5 4 3 2 1 0และThe Garry_G way: 10 9 8 7 6 5 4 3 2 1
Anthony

2
มันไม่ได้ทำสิ่งเดียวกัน ย้ายของคุณx=x-1ก่อนprintfแล้วคุณสามารถพูดว่า "มันทำสิ่งเดียวกัน"
CITBL

26

ในวิธีการทั่วไปเราจะกำหนดเงื่อนไขในwhileวงเล็บห่วง()และเงื่อนไขยุติภายในวงเล็บปีกกา{}แต่-->กำหนดทั้งสองในครั้งเดียว

ตัวอย่างเช่น:

int abc(void)
{
    int a = 5
    while((a--) > 0) // Decrement and comparison both at once
    {
        // Code
    }
}

การลดลงนี้aและวิ่งวนรอบในขณะที่มีค่ามากกว่าa0

ตามอัตภาพมันจะเป็นเช่น:

int abc(void)
{
    int a = 5;
    while(a > 0)
    {
        a--;
        // Code
    }
    a--;
}

ทั้งสองวิธีเราทำสิ่งเดียวกันและบรรลุเป้าหมายเดียวกัน


5
สิ่งนี้ไม่ถูกต้อง รหัสในคำถามไม่: 'test-write-execute' (ทดสอบก่อนเขียนค่าใหม่รันลูป) ตัวอย่างของคุณคือ 'test-execute-write'
v010dya

@ v010dya แก้ไขคำตอบตอนนี้มันtest-write-executeเป็นเหมือนคำถามขอบคุณที่ชี้ให้เห็น!
Kotauskas

@VladislavToncharov การแก้ไขของคุณยังไม่ถูกต้อง ดูของฉัน
SS Anne

8

(x --> 0) วิธี (x-- > 0)

  1. คุณสามารถใช้ได้ (x -->)
    output -: 9 8 7 6 5 4 3 2 1 0

  2. คุณสามารถใช้(-- x > 0) มันหมายความว่า(--x > 0)
    output -: 9 8 7 6 5 4 3 2 1

  3. คุณสามารถใช้ได้
(--\
    \
     x > 0)

output -: 9 8 7 6 5 4 3 2 1

  1. คุณสามารถใช้ได้
(\
  \
   x --> 0)

output -: 9 8 7 6 5 4 3 2 1 0

  1. คุณสามารถใช้ได้
(\
  \
   x --> 0
          \
           \
            )

output -: 9 8 7 6 5 4 3 2 1 0

  1. คุณสามารถใช้
(
 x 
  --> 
      0
       )

output -: 9 8 7 6 5 4 3 2 1 0

เช่นเดียวกันคุณสามารถลองวิธีการมากมายในการเรียกใช้คำสั่งนี้ได้สำเร็จ

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