เหตุใด C จึงไม่อนุญาตให้เชื่อมสตริงเข้าด้วยกันเมื่อใช้ตัวดำเนินการตามเงื่อนไข


95

โค้ดต่อไปนี้คอมไพล์ได้โดยไม่มีปัญหา:

int main() {
    printf("Hi" "Bye");
}

อย่างไรก็ตามสิ่งนี้ไม่ได้รวบรวม:

int main() {
    int test = 0;
    printf("Hi" (test ? "Bye" : "Goodbye"));
}

เหตุผลนั้นคืออะไร?


95
การต่อสายอักขระเป็นส่วนหนึ่งของระยะเริ่มต้น ไม่ใช่ส่วนหนึ่งของนิพจน์ synatx ของ C กล่าวอีกนัยหนึ่งคือไม่มีค่าประเภท "string literal" ลิเทอรัลสตริงเป็นองค์ประกอบศัพท์ของซอร์สโค้ดที่สร้างค่า
Kerrek SB

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

2
รายละเอียด: ในโพสต์นี้"Hi"และ"Bye"เป็นตัวอักษรสตริงไม่ใช่สตริงที่ใช้ในไลบรารีมาตรฐาน C ด้วยสตริงลิเทอรัลคอมไพเลอร์จะเชื่อมต่อกัน"H\0i" "B\0ye"concatenate ไม่เหมือนกันกับsprintf(buf,"%s%s", "H\0i" "B\0ye");
chux - Reinstate Monica

15
ไม่มากก็น้อยเหตุผลเดียวกับที่คุณทำไม่ได้a (some_condition ? + : - ) b
user253751

4
โปรดทราบว่าแม้printf("Hi" ("Bye"));จะใช้ไม่ได้ - ไม่จำเป็นต้องใช้ตัวดำเนินการที่เกี่ยวข้อง วงเล็บก็เพียงพอแล้ว (แม้ว่าprintf("Hi" test ? "Bye" : "Goodbye")จะไม่รวบรวมก็ตาม) มีโทเค็นจำนวน จำกัด เท่านั้นที่สามารถติดตามสตริงลิเทอรัลได้ ลูกน้ำ,, วงเล็บเหลี่ยมเปิด, วงเล็บเหลี่ยม[ปิด](เช่นเดียวกับ1["abc"]- และใช่มันน่ากลัว), วงเล็บกลม)ปิด, วงเล็บปีกกาปิด}(ในตัวเริ่มต้นหรือบริบทที่คล้ายกัน) และอัฒภาค;ถูกต้อง (และอีกสตริงตามตัวอักษร); ฉันไม่แน่ใจว่ามีคนอื่น ๆ
Jonathan Leffler

คำตอบ:


121

ตามมาตรฐาน C (ขั้นตอนการแปล 5.1.1.2)

1 ลำดับความสำคัญของกฎไวยากรณ์ของการแปลถูกระบุโดยขั้นตอนต่อไปนี้ 6)

  1. โทเค็นลิเทอรัลสตริงที่อยู่ติดกันจะเชื่อมต่อกัน

และหลังจากนั้น

  1. อักขระเว้นวรรคสีขาวที่คั่นโทเค็นไม่มีความสำคัญอีกต่อไป โทเค็นก่อนการประมวลผลแต่ละรายการจะถูกแปลงเป็นโทเค็นราชสกุลส่งผลให้มีการไวยากรณ์และความหมายการวิเคราะห์และแปลเป็นหน่วยการแปล

ในการก่อสร้างครั้งนี้

"Hi" (test ? "Bye" : "Goodbye")

ไม่มีโทเค็นตัวอักษรสตริงที่อยู่ติดกัน ดังนั้นการก่อสร้างนี้ไม่ถูกต้อง


43
นี่เป็นเพียงการยืนยันซ้ำว่าไม่อนุญาตใน C. ไม่ได้อธิบายว่าทำไมซึ่งเป็นคำถาม ไม่รู้ว่าทำไมถึงสะสม 26 upvotes ใน 5 ชั่วโมง .... และยอมรับไม่น้อย! ยินดีด้วย.
Lightness Races ใน Orbit

4
ต้องเห็นด้วยกับ @LightnessRacesinOrbit ที่นี่ ทำไมไม่ควร(test ? "Bye" : "Goodbye")evaulate อย่างใดอย่างหนึ่งของสายอักขระตัวอักษรเป็นหลักทำ "Hi" "Bye"หรือ"Hi Goodbye"? (คำถามของฉันมีคำตอบอยู่ในคำตอบอื่น ๆ )
บ้า

48
@LightnessRacesinOrbit เพราะปกติเมื่อมีคนถามว่าทำไมบางอย่างถึงไม่รวบรวมใน C พวกเขาจะขอคำชี้แจงว่ากฎใดที่มันทำลายไม่ใช่เหตุผลที่Standard Authors of Antiquityเลือกให้เป็นแบบนั้น
user1717828

4
@LightnessRacesinOrbit คำถามที่คุณอธิบายน่าจะไม่ตรงประเด็น ฉันไม่เห็นเหตุผลทางเทคนิคใด ๆว่าทำไมจึงไม่สามารถใช้สิ่งนั้นได้ดังนั้นหากไม่มีคำตอบที่ชัดเจนจากผู้เขียนข้อกำหนดคำตอบทั้งหมดจะขึ้นอยู่กับความคิดเห็น และโดยทั่วไปแล้วจะไม่อยู่ในหมวดหมู่ของคำถามที่ "ใช้ได้จริง" หรือ "ตอบได้" (เนื่องจากศูนย์ช่วยเหลือระบุว่าเราต้องการ)
jpmc26

12
@LightnessRacesinOrbit มันอธิบายว่าทำไม : "เพราะ C standard พูดอย่างนั้น" คำถามเกี่ยวกับสาเหตุที่กฎนี้ถูกกำหนดตามที่กำหนดจะไม่อยู่ในหัวข้อ
user11153

135

ตามมาตรฐาน C11 บท§5.1.1.2การเรียงต่อกันของตัวอักษรสตริงที่อยู่ติดกัน:

โทเค็นลิเทอรัลสตริงที่อยู่ติดกันจะเชื่อมต่อกัน

ที่เกิดขึ้นในขั้นตอนการแปล ในทางกลับกัน:

printf("Hi" (test ? "Bye" : "Goodbye"));

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


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

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

เพียงแค่ FYI สำหรับการต่อสตริงรันไทม์( ไม่ใช่ตัวอักษร ) เรามีฟังก์ชันไลบรารีstrcat()ที่เชื่อมสองสตริงเข้าด้วยกัน ข้อสังเกตคำอธิบายกล่าวถึง:

char *strcat(char * restrict s1,const char * restrict s2);

strcat()ฟังก์ชั่นผนวกสำเนาของสตริงที่ชี้ไปตามs2(รวมถึงตัวละครยุติโมฆะ) ไปยังจุดสิ้นสุดของสตริงชี้ไปตาม s1ตัวละครเริ่มต้นของการs2เขียนทับอักขระ null s1ในตอนท้ายของ [... ]

เราจะเห็นว่าs1เป็นสตริงไม่ใช่สตริงลิเทอรัล อย่างไรก็ตามเนื่องจากเนื้อหาของs2ไม่มีการเปลี่ยนแปลง แต่อย่างใดจึงสามารถเป็นสตริงตามตัวอักษรได้เป็นอย่างดี


1
คุณอาจต้องการเพิ่มคำอธิบายเพิ่มเติมเกี่ยวกับstrcatอาร์เรย์ปลายทางต้องมีความยาวเพียงพอที่จะรับอักขระจากs2บวกเทอร์มิเนเตอร์ว่างหลังจากที่มีอักขระอยู่แล้ว
chqrlie

39

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

เนื่องจากกรณีทั่วไปคือคุณจะไม่มีโครงสร้างเช่นนี้สำหรับค่าที่ทราบในเวลาคอมไพล์มาตรฐาน C ได้รับการออกแบบมาเพื่อ จำกัด คุณลักษณะการเรียงต่อกันอัตโนมัติเป็นกรณีพื้นฐานที่สุด: เมื่อตัวอักษรอยู่ข้างกันอย่างแท้จริง .

แต่แม้ว่าจะไม่ได้ระบุถึงข้อ จำกัด นี้ในลักษณะนั้นหรือหากข้อ จำกัด นั้นสร้างขึ้นแตกต่างกันตัวอย่างของคุณก็ยังคงเป็นไปไม่ได้ที่จะตระหนักได้หากไม่ทำให้การเชื่อมต่อเป็นกระบวนการรันไทม์ และสำหรับสิ่งนั้นเรามีฟังก์ชั่นไลบรารีเช่นstrcat.


3
ฉันเพิ่งอ่านสมมติฐาน แม้ว่าสิ่งที่คุณพูดจะค่อนข้างถูกต้อง แต่คุณไม่สามารถให้แหล่งข้อมูลได้เนื่องจากไม่มีเลย แหล่งที่มาเดียวที่เกี่ยวกับ C คือเอกสารมาตรฐานซึ่ง (แม้ว่าจะมีหลายกรณีที่น่ารังเกียจ) ไม่ได้ระบุว่าเหตุใดบางสิ่งจึงเป็นอย่างนั้น แต่เพียงระบุว่าต้องเป็นวิธีที่เฉพาะเจาะจง ดังนั้นการที่ไม่จู้จี้จุกจิกเกี่ยวกับ Vlad จากคำตอบของมอสโกนั้นไม่เหมาะสม เนื่องจาก OP สามารถแบ่งออกเป็น "ทำไมถึงเป็นแบบนั้น" - ในกรณีที่คำตอบเดียวที่มีที่มาที่ถูกต้องคือ "เพราะเป็น C และนั่นคือวิธีที่กำหนด C" นั่นคือคำตอบที่ถูกต้องตรงตามตัวอักษรเพียงคำตอบเดียว
dhein

1
นี่คือ (ชื่นชม) โดยขาดคำอธิบาย แต่ที่นี่พูดอีกครั้งว่าคำตอบของ Vlad ให้บริการมากกว่านี้เป็นคำอธิบายสำหรับปัญหาหลักจากนั้นคุณก็ทำ กล่าวอีกครั้ง: แม้ว่าข้อมูลที่คุณให้ฉันสามารถยืนยันได้ว่าเกี่ยวข้องและถูกต้อง แต่ฉันไม่เห็นด้วยกับข้อร้องเรียนของคุณ และในขณะที่ฉันจะไม่พิจารณา offtopic ของคุณเช่นกันมันมาจาก POV offtopic ของฉันมากกว่านั้น Vlads ก็เป็นจริง
dhein

11
@ Zaibis: ที่มาคือฉัน คำตอบของวลาดไม่ใช่คำอธิบาย แต่อย่างใด เป็นเพียงการยืนยันหลักฐานของคำถามเท่านั้น แน่นอนว่าทั้งสองอย่างนี้ "ไม่อยู่ในหัวข้อ" (คุณอาจต้องการค้นหาความหมายของคำนั้น) แต่คุณมีสิทธิ์แสดงความคิดเห็น
Lightness Races ในวงโคจร

แม้หลังจากอ่านความคิดเห็นข้างต้นแล้วฉันก็ยังสงสัยว่าใครลงคะแนนคำตอบนี้ᶘᵒᴥᵒᶅฉันเชื่อว่านี่เป็นคำตอบที่สมบูรณ์แบบเว้นแต่ OP จะขอคำชี้แจงเพิ่มเติมเกี่ยวกับคำตอบนี้
Mohit Jain

2
ฉันไม่สามารถแยกแยะได้ว่าทำไมคำตอบนี้จึงเป็นที่ยอมรับสำหรับคุณและ @ VladfromMoscow ไม่ใช่เมื่อทั้งคู่พูดในสิ่งเดียวกันและเมื่อเขาได้รับการสนับสนุนจากการอ้างอิงและของคุณไม่เป็นเช่นนั้น
Marquis of Lorne

30

เพราะ C ไม่มีstringพิมพ์. ตัวอักษรสตริงถูกรวบรวมไปยังcharอาร์เรย์โดยอ้างถึงโดยchar*ตัวชี้

C อนุญาตให้รวมตัวอักษรที่อยู่ติดกันในเวลาคอมไพล์ดังตัวอย่างแรกของคุณ คอมไพเลอร์ C เองมีความรู้บางอย่างเกี่ยวกับสตริง แต่ไม่มีข้อมูลนี้ในรันไทม์ดังนั้นการต่อข้อมูลจึงไม่สามารถเกิดขึ้นได้

ในระหว่างขั้นตอนการรวบรวมตัวอย่างแรกของคุณ "แปล" เป็น:

int main() {
    static const char char_ptr_1[] = {'H', 'i', 'B', 'y', 'e', '\0'};
    printf(char_ptr_1);
}

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

อย่างไรก็ตามตัวอย่างที่สองของคุณ "แปล" เป็นดังนี้:

int main() {
    static const char char_ptr_1[] = {'H', 'i', '\0'};
    static const char char_ptr_2[] = {'B', 'y', 'e', '\0'};
    static const char char_ptr_3[] = {'G', 'o', 'o', 'd', 'b', 'y', 'e', '\0'};
    int test = 0;
    printf(char_ptr_1 (test ? char_ptr_2 : char_ptr_3));
}

ควรมีความชัดเจนว่าเหตุใดจึงไม่รวบรวมข้อมูลนี้ ตัวดำเนินการ ternary ?จะได้รับการประเมินที่รันไทม์ไม่ใช่เวลาคอมไพล์เมื่อ "สตริง" ไม่มีอยู่อีกต่อไป แต่เป็นcharอาร์เรย์ธรรมดาเท่านั้นที่อ้างอิงโดยพchar*อยน์เตอร์ ไม่เหมือนกับตัวอักษรสตริงที่อยู่ติดกันตัวชี้อักขระที่อยู่ติดกันเป็นเพียงข้อผิดพลาดทางไวยากรณ์


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

ไม่ควรstatic const char *char_ptr_1 = {'H', 'i', 'B', 'y', 'e', '\0'};เป็นstatic const char *char_ptr_1 = "HiBye";และในทำนองเดียวกันสำหรับตัวชี้ที่เหลือ?
Spikatrix

@CoolGuy เมื่อคุณเขียนstatic const char *char_ptr_1 = "HiBye";คอมไพเลอร์แปลบรรทัดเป็นstatic const char *char_ptr_1 = {'H', 'i', 'B', 'y', 'e', '\0'};ดังนั้นไม่ควรเขียนว่า "เหมือนสตริง" ดังที่คำตอบกล่าวว่าสตริงจะถูกรวบรวมไปยังอาร์เรย์ของตัวอักษรและหากคุณกำหนดอาร์เรย์ของอักขระในรูปแบบ "ดิบ" ส่วนใหญ่คุณจะใช้รายการอักขระที่คั่นด้วยจุลภาคเช่นเดียวกับstatic const char *char_ptr_1 = {'H', 'i', 'B', 'y', 'e', '\0'};
Ankush

3
@Ankush ครับ แต่ถึงแม้ว่าstatic const char str[] = {'t', 'e', 's', 't', '\0'};เป็นเช่นเดียวกับstatic const char str[] = "test";, static const char* ptr = "test";เป็นไม่ได้static const char* ptr = {'t', 'e', 's', 't', '\0'};เช่นเดียวกับ อดีตถูกต้องและจะคอมไพล์ แต่ส่วนหลังไม่ถูกต้องและทำในสิ่งที่คุณคาดหวัง
Spikatrix

ฉันได้แก้ไขย่อหน้าสุดท้ายและแก้ไขตัวอย่างโค้ดแล้วขอบคุณ!
ไม่ลงนาม

13

หากคุณต้องการให้ทั้งสองสาขาสร้างค่าคงที่สตริงเวลาคอมไพล์เพื่อเลือกในรันไทม์คุณจะต้องมีมาโคร

#include <stdio.h>
#define ccat(s, t, a, b) ((t)?(s a):(s b))

int
main ( int argc, char **argv){
  printf("%s\n", ccat("hello ", argc > 2 , "y'all", "you"));
  return 0;
}

10

เหตุผลนั้นคืออะไร?

รหัสของคุณโดยใช้ตัวดำเนินการ ternary จะเลือกตามเงื่อนไขระหว่างตัวอักษรสตริงสองตัว ไม่ว่าเงื่อนไขจะทราบหรือไม่ทราบก็ไม่สามารถประเมินได้ในเวลาคอมไพล์ดังนั้นจึงไม่สามารถคอมไพล์ได้ แม้แต่คำสั่งนี้printf("Hi" (1 ? "Bye" : "Goodbye"));ก็ไม่สามารถรวบรวมได้ เหตุผลในเชิงลึกอธิบายไว้ในคำตอบข้างต้น ความเป็นไปได้อีกอย่างหนึ่งของการทำคำสั่งดังกล่าวโดยใช้ผู้ประกอบการที่ถูกต้องประกอบไปด้วยการรวบรวมยังจะเกี่ยวข้องกับแท็กรูปแบบและผลของคำสั่งผู้ประกอบ ternary ในรูปแบบอาร์กิวเมนต์เพิ่มเติมprintfเพื่อ แม้แล้วprintf()พิมพ์ออกมาจะให้เป็นที่ประทับใจของ "ที่มีการตัดแบ่ง" สตริงเหล่านั้นเท่านั้นที่และเร็วที่สุดเท่าที่รันไทม์

#include <stdio.h>

int main() {
    int test = 0;
    printf("Hi %s\n", (test ? "Bye" : "Goodbye")); //specify format and print as result
}

3
SO ไม่ใช่ไซต์บทช่วยสอน คุณควรให้คำตอบแก่ OP ไม่ใช่การสอน
Michi

1
สิ่งนี้ไม่ตอบคำถามของ OP อาจเป็นความพยายามที่จะแก้ปัญหาพื้นฐานของ OP แต่เราไม่รู้จริงๆว่ามันคืออะไร
Keith Thompson

1
printfไม่ต้องการตัวระบุรูปแบบ ถ้าเฉพาะการเรียงต่อกันเสร็จสิ้นในเวลาคอมไพล์ (ซึ่งไม่ใช่) การใช้ printf ของ OP จะใช้ได้
David Conrad

ขอบคุณสำหรับคำพูดของคุณ @David Conrad ข้อความที่เลอะเทอะของฉันจะทำให้ดูเหมือนว่าการระบุ printf()จะต้องใช้แท็กรูปแบบซึ่งไม่เป็นความจริงอย่างแน่นอน แก้ไขแล้ว!
user3078414

นั่นเป็นถ้อยคำที่ดีกว่า +1 ขอบคุณ
David Conrad

7

ในprintf("Hi" "Bye");คุณมีสองอาร์เรย์ติดต่อกันของถ่านซึ่งคอมไพเลอร์สามารถทำให้เป็นอาร์เรย์เดียว

ในprintf("Hi" (test ? "Bye" : "Goodbye"));คุณมีอาร์เรย์หนึ่งรายการตามด้วยตัวชี้ไปยังถ่าน (อาร์เรย์ที่แปลงเป็นตัวชี้ไปยังองค์ประกอบแรก) คอมไพลเลอร์ไม่สามารถผสานอาร์เรย์และตัวชี้ได้


0

เพื่อตอบคำถาม - ฉันจะไปที่คำจำกัดความของ printf ฟังก์ชัน printf คาดว่าconst char *เป็นอาร์กิวเมนต์ ตัวอักษรสตริงใด ๆ เช่น "Hi" คือ const char *; อย่างไรก็ตามนิพจน์เช่น(test)? "str1" : "str2"ไม่ใช่ const char * เนื่องจากผลลัพธ์ของนิพจน์ดังกล่าวพบเฉพาะในเวลาทำงานและด้วยเหตุนี้จึงไม่แน่นอนในเวลาคอมไพล์ซึ่งเป็นข้อเท็จจริงที่ทำให้คอมไพเลอร์บ่นอย่างถูกต้อง ในทางกลับกัน - ใช้งานได้ดีอย่างสมบูรณ์printf("hi %s", test? "yes":"no")


* อย่างไรก็ตามการแสดงออกเช่น(test)? "str1" : "str2"ไม่ใช่const char*... แน่นอนมันเป็น! มันไม่ได้เป็นการแสดงออกอย่างต่อเนื่อง แต่ประเภทคือ มันจะดีอย่างสมบูรณ์แบบในการเขียนconst char * printf(test ? "hi " "yes" : "hi " "no")ปัญหาของ OP มีอะไรจะทำอย่างไรกับprintf, "Hi" (test ? "Bye" : "Goodbye")เป็นข้อผิดพลาดทางไวยากรณ์ไม่ว่าสิ่งที่บริบทการแสดงออกเป็น
chqrlie

ตกลง ฉันสับสนผลลัพธ์ของนิพจน์กับนิพจน์ตัวเอง
Stats_Lover

-4

สิ่งนี้ไม่รวบรวมเนื่องจากรายการพารามิเตอร์สำหรับฟังก์ชัน printf คือ

(const char *format, ...)

และ

("Hi" (test ? "Bye" : "Goodbye"))

ไม่พอดีกับรายการพารามิเตอร์

gcc พยายามทำให้เข้าใจโดยจินตนาการว่า

(test ? "Bye" : "Goodbye")

เป็นรายการพารามิเตอร์และบ่นว่า "Hi" ไม่ใช่ฟังก์ชัน


6
ยินดีต้อนรับสู่ Stack Overflow คุณคิดถูกที่ไม่ตรงกับprintf()รายการอาร์กิวเมนต์ แต่นั่นเป็นเพราะนิพจน์ไม่ถูกต้องทุกที่ไม่ใช่แค่ในprintf()รายการอาร์กิวเมนต์ กล่าวอีกนัยหนึ่งคุณได้เลือกเหตุผลที่เฉพาะเจาะจงเกินไปสำหรับปัญหานี้ ปัญหาทั่วไปคือการที่"Hi" (ไม่ถูกต้องใน C printf()ให้อยู่คนเดียวในการเรียกไปยัง ฉันขอแนะนำให้คุณลบคำตอบนี้ก่อนที่จะมีการโหวตลดลง
Jonathan Leffler

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