เหตุใดตัวอักษรตัวอักษร C จึงอยู่ภายในแทนอักขระ


103

ใน C sizeof('a') == sizeof(char) == 1++, สิ่งนี้ทำให้เข้าใจง่ายเนื่องจาก'a'เป็นอักขระตามตัวอักษรและsizeof(char) == 1ตามที่กำหนดโดยมาตรฐาน

ใน C อย่างไรก็ตามsizeof('a') == sizeof(int). นั่นคือดูเหมือนว่าอักษรตัวอักษร C เป็นจำนวนเต็ม มีใครรู้บ้างว่าทำไม? ฉันสามารถค้นหาการกล่าวถึง C quirk นี้ได้มากมาย แต่ไม่มีคำอธิบายว่าเหตุใดจึงมีอยู่


sizeof จะส่งคืนขนาดของไบต์หรือไม่? ถ่านและ int มีขนาดไม่เท่ากัน?
Josh Smeaton

1
ซึ่งอาจขึ้นอยู่กับคอมไพเลอร์ (และสถาปัตยกรรม) สนใจที่จะบอกว่าคุณกำลังใช้อะไรอยู่? มาตรฐาน (อย่างน้อยถึงปี 89) หลวมมาก
dmckee --- อดีตผู้ดูแลลูกแมว

2
ไม่. ถ่านจะมีขนาดใหญ่ 1 ไบต์ดังนั้น sizeof ('a') == 1 เสมอ (ใน c ++) ในขณะที่ int สามารถมีขนาดเท่ากับ 1 ในทางทฤษฎีแต่จะต้องมีไบต์ที่มีอย่างน้อย 16 บิตซึ่งไม่น่าเป็นไปได้มาก : ) ดังนั้น sizeof ('a')! = sizeof (int) มีโอกาสมากใน C ++ ในการใช้งานส่วนใหญ่
Johannes Schaub - litb

2
... ในขณะที่ C.
Johannes Schaub - litb

22
'a' คือ int ในช่วง C - C ไปถึงที่นั่นก่อน - C ทำตามกฎ C ++ เปลี่ยนกฎ คุณสามารถโต้แย้งว่ากฎ C ++ มีความหมายมากกว่า แต่การเปลี่ยนกฎ C จะสร้างความเสียหายมากกว่าผลดีดังนั้นคณะกรรมการมาตรฐาน C จึงไม่แตะต้องสิ่งนี้อย่างชาญฉลาด
Jonathan Leffler

คำตอบ:


36

การอภิปรายในเรื่องเดียวกัน

"โดยเฉพาะอย่างยิ่งการส่งเสริมการขายแบบอินทิกรัลใน K&R C แทบจะเป็นไปไม่ได้เลยที่จะใช้ค่าอักขระโดยไม่ได้รับการเลื่อนขั้นเป็น int ก่อนดังนั้นการทำให้อักขระคงที่ int ในตอนแรกจึงตัดขั้นตอนนั้นออกไปและยังคงเป็นอักขระหลายตัว ค่าคงที่เช่น 'abcd' หรือจำนวนมากจะพอดีกับ int "


ค่าคงที่หลายอักขระไม่สามารถพกพาได้แม้จะอยู่ระหว่างคอมไพเลอร์บนเครื่องเดียว (แม้ว่า GCC ดูเหมือนจะสอดคล้องกันในทุกแพลตฟอร์มก็ตาม) ดู: stackoverflow.com/questions/328215
Jonathan Leffler

8
ฉันจะทราบว่าก) ใบเสนอราคานี้ไม่มีการระบุแหล่งที่มา การอ้างอิงเพียงระบุว่า "คุณจะไม่เห็นด้วยกับความคิดเห็นนี้ซึ่งโพสต์ไว้ในกระทู้ที่ผ่านมาซึ่งพูดถึงปัญหาที่เป็นปัญหาหรือไม่" ... และ b) มันน่าหัวเราะเพราะcharตัวแปรไม่ใช่ int ดังนั้นการทำให้อักขระคงที่เป็นหนึ่งจึงเป็นกรณีพิเศษ c1 = c2;และมันก็เป็นเรื่องง่ายที่จะใช้ค่าตัวอักษรโดยไม่มีการส่งเสริม: OTOH c1 = 'x'คือการแปลงขาลง ที่สำคัญที่สุดsizeof(char) != sizeof('x')ซึ่งเป็นปัญหาด้านภาษาที่ร้ายแรง สำหรับค่าคงที่ของอักขระหลายไบต์นั่นคือเหตุผล แต่มันล้าสมัย
Jim Balter

27

คำถามเดิมคือ "ทำไม"

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

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

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

สิ่งนี้ทำให้สิ่งต่าง ๆ ไม่สอดคล้องกันดังนั้นเมื่อ K&R เขียนหนังสือที่มีชื่อเสียงของพวกเขาพวกเขาจึงวางกฎที่ว่าตัวอักษรตามตัวอักษรจะได้รับการเลื่อนระดับเป็น int ในนิพจน์ใด ๆ เสมอไม่ใช่แค่พารามิเตอร์ฟังก์ชัน

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

เมื่อ C ++ ได้รับการออกแบบฟังก์ชันทั้งหมดจำเป็นต้องมีต้นแบบทั้งหมด (ยังไม่จำเป็นต้องใช้ใน C แม้ว่าจะได้รับการยอมรับในระดับสากลว่าเป็นแนวปฏิบัติที่ดีก็ตาม) ด้วยเหตุนี้จึงมีการตัดสินใจว่าสามารถเก็บอักขระตามตัวอักษรไว้ในถ่านได้ ข้อดีของสิ่งนี้ใน C ++ คือฟังก์ชันที่มีพารามิเตอร์ char และฟังก์ชันที่มีพารามิเตอร์ int มีลายเซ็นที่แตกต่างกัน ข้อได้เปรียบนี้ไม่เป็นเช่นนั้นในค.

นี่คือเหตุผลที่พวกเขาแตกต่างกัน วิวัฒนาการ...


2
+1 จากฉันสำหรับคำตอบที่แท้จริงว่า 'ทำไม?' แต่ฉันไม่เห็นด้วยกับคำสั่งสุดท้าย - "ข้อดีของสิ่งนี้ใน C ++ คือฟังก์ชันที่มีพารามิเตอร์ char และฟังก์ชันที่มีพารามิเตอร์ int จะมีลายเซ็นที่แตกต่างกัน" - ใน C ++ ยังคงเป็นไปได้ที่ 2 ฟังก์ชันจะมีพารามิเตอร์ของ ขนาดเดียวกันและลายเซ็นที่แตกต่างกันเช่นVsvoid f(unsigned char) void f(signed char)
Peter K

3
@PeterK John น่าจะดีกว่านี้ แต่สิ่งที่เขาพูดนั้นถูกต้องเป็นหลัก แรงจูงใจสำหรับการเปลี่ยนแปลงใน C ++ คือถ้าคุณเขียนf('a')คุณอาจต้องการความละเอียดเกินที่จะเลือกสำหรับการโทรที่มากกว่าf(char) f(int)ขนาดสัมพัทธ์intและcharไม่เกี่ยวข้องตามที่คุณพูด
zwol

21

ฉันไม่ทราบสาเหตุที่เฉพาะเจาะจงว่าทำไมอักขระตามตัวอักษรใน C จึงเป็นประเภท int แต่ในภาษา C ++ มีเหตุผลที่ดีที่จะไม่ไปในทางนั้น พิจารณาสิ่งนี้:

void print(int);
void print(char);

print('a');

คุณคาดว่าการเรียกพิมพ์จะเลือกเวอร์ชันที่สองโดยใช้ถ่าน การมีอักขระตามตัวอักษรเป็น int จะทำให้เป็นไปไม่ได้ โปรดสังเกตว่าในตัวอักษร C ++ ที่มีอักขระมากกว่าหนึ่งตัวยังคงมีประเภท int แม้ว่าค่าจะถูกกำหนดการนำไปใช้งาน ดังนั้น'ab'มีประเภทintในขณะที่มีประเภท'a'char


ใช่ "การออกแบบและวิวัฒนาการของ C ++" กล่าวว่ารูทีนอินพุต / เอาต์พุตที่โอเวอร์โหลดเป็นสาเหตุหลักที่ C ++ เปลี่ยนกฎ
Max Lybbert

5
แม็กซ์ใช่ฉันโกง ฉันดูมาตรฐานในส่วนความเข้ากันได้ :)
Johannes Schaub - litb

18

ใช้ gcc บน MacBook ของฉันฉันลอง:

#include <stdio.h>
#define test(A) do{printf(#A":\t%i\n",sizeof(A));}while(0)
int main(void){
  test('a');
  test("a");
  test("");
  test(char);
  test(short);
  test(int);
  test(long);
  test((char)0x0);
  test((short)0x0);
  test((int)0x0);
  test((long)0x0);
  return 0;
};

ซึ่งเมื่อรันให้:

'a':    4
"a":    2
"":     1
char:   1
short:  2
int:    4
long:   4
(char)0x0:      1
(short)0x0:     2
(int)0x0:       4
(long)0x0:      4

ซึ่งแสดงให้เห็นว่าอักขระคือ 8 บิตอย่างที่คุณสงสัย แต่ตัวอักษรตัวอักษรเป็น int


7
+1 เพื่อความน่าสนใจ คนมักคิดว่า sizeof ("a") และ sizeof ("") เป็นของ char * และควรให้ 4 (หรือ 8) แต่ในความเป็นจริงพวกเขาอยู่ที่จุดนั้น (sizeof (char [11]) ให้ 11) กับดักสำหรับมือใหม่
paxdiablo

3
อักขระลิเทอรัลไม่ได้รับการเลื่อนระดับเป็น int แต่เป็น int อยู่แล้ว จะไม่มีการส่งเสริมใด ๆ เกิดขึ้นหากวัตถุนั้นเป็นตัวถูกดำเนินการของตัวดำเนินการ sizeof หากมีสิ่งนี้จะทำให้จุดประสงค์ของ sizeof ล้มเหลว
Chris Young

@ คริสยัง: ยะ. ตรวจสอบ. ขอบคุณ.
dmckee --- อดีตผู้ดูแลลูกแมว

8

ย้อนกลับไปตอนที่เขียน C ภาษาแอสเซมบลี MACRO-11 ของ PDP-11 มี:

MOV #'A, R0      // 8-bit character encoding for 'A' into 16 bit register

สิ่งนี้พบได้บ่อยในภาษาแอสเซมบลี - 8 บิตต่ำจะเก็บโค้ดอักขระส่วนบิตอื่น ๆ เคลียร์เป็น 0 PDP-11 ยังมี:

MOV #"AB, R0     // 16-bit character encoding for 'A' (low byte) and 'B'

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

ดังนั้นความคิดของตัวละครที่ได้รับการส่งเสริมให้มีขนาดลงทะเบียนจึงค่อนข้างปกติและเป็นที่ต้องการ แต่สมมติว่าคุณต้องรับ 'A' ในรีจิสเตอร์ที่ไม่ใช่ส่วนหนึ่งของ opcode แบบฮาร์ดโค้ด แต่มาจากที่ใดที่หนึ่งในหน่วยความจำหลักที่มี:

address: value
20: 'X'
21: 'A'
22: 'A'
23: 'X'
24: 0
25: 'A'
26: 'A'
27: 0
28: 'A'

ถ้าคุณต้องการอ่านแค่ 'A' จากหน่วยความจำหลักนี้ลงในรีจิสเตอร์คุณจะอ่านอันไหน?

  • ซีพียูบางตัวอาจรองรับการอ่านค่า 16 บิตในการลงทะเบียน 16 บิตโดยตรงซึ่งหมายความว่าการอ่านที่ 20 หรือ 22 จะต้องมีการล้างบิตจาก 'X' และขึ้นอยู่กับความสิ้นสุดของ CPU อย่างใดอย่างหนึ่ง จะต้องเปลี่ยนเป็นไบต์ลำดับต่ำ

  • ซีพียูบางตัวอาจต้องการการอ่านที่จัดตำแหน่งหน่วยความจำซึ่งหมายความว่าแอดเดรสต่ำสุดที่เกี่ยวข้องจะต้องมีขนาดข้อมูลหลายขนาดคุณอาจอ่านได้จากที่อยู่ 24 และ 25 แต่ไม่ใช่ 27 และ 28

ดังนั้นคอมไพเลอร์ที่สร้างโค้ดเพื่อรับ 'A' ลงในรีจิสเตอร์อาจต้องการที่จะเสียหน่วยความจำเพิ่มเล็กน้อยและเข้ารหัสค่าเป็น 0 'A' หรือ 'A' 0 - ขึ้นอยู่กับ endianness และตรวจสอบให้แน่ใจว่ามันอยู่ในแนวเดียวกันอย่างถูกต้อง ( เช่นไม่อยู่ในที่อยู่หน่วยความจำแปลก ๆ )

ฉันเดาว่า C เพียงแค่ดำเนินการในระดับนี้ของพฤติกรรมที่เน้น CPU เป็นศูนย์กลางโดยนึกถึงค่าคงที่ของอักขระที่มีขนาดการลงทะเบียนของหน่วยความจำโดยพิจารณาจากการประเมินทั่วไปของ C ว่าเป็น "แอสเซมเบลอร์ระดับสูง"

(ดู 6.3.3 ในหน้า 6-25 ของhttp://www.dmv.net/dec/pdf/macro.pdf )


5

ฉันจำได้ว่าอ่าน K&R และเห็นข้อมูลโค้ดที่จะอ่านทีละอักขระจนกว่าจะถึง EOF เนื่องจากอักขระทั้งหมดเป็นอักขระที่ถูกต้องที่จะอยู่ในไฟล์ / อินพุตสตรีมจึงหมายความว่า EOF ไม่สามารถเป็นค่าถ่านได้ สิ่งที่โค้ดทำคือใส่อักขระอ่านลงใน int จากนั้นทดสอบ EOF จากนั้นแปลงเป็น char หากไม่ใช่

ฉันรู้ว่านี่ไม่ได้ตอบคำถามของคุณอย่างตรงไปตรงมา แต่มันจะสมเหตุสมผลสำหรับตัวอักษรที่เหลือที่จะมีขนาด (int) ถ้าตัวอักษร EOF เป็น

int r;
char buffer[1024], *p; // don't use in production - buffer overflow likely
p = buffer;

while ((r = getc(file)) != EOF)
{
  *(p++) = (char) r;
}

ฉันไม่คิดว่า 0 เป็นอักขระที่ถูกต้อง
gbjbaanb

3
@gbjbaanb: แน่นอนค่ะ มันคืออักขระว่าง ลองคิดดูสิ คุณคิดว่าไฟล์ไม่ควรมีศูนย์ไบต์หรือไม่?
P Daddy

1
อ่านวิกิพีเดีย - "ค่าที่แท้จริงของ EOF คือจำนวนลบที่ขึ้นกับระบบโดยทั่วไปคือ -1 ซึ่งรับประกันว่าไม่เท่ากันกับรหัสอักขระที่ถูกต้อง"
Malx

2
ดังที่ Malx กล่าว - EOF ไม่ใช่ประเภทถ่าน - เป็นประเภท int getchar () และเพื่อนส่งคืน int ซึ่งสามารถเก็บ char ใดก็ได้เช่นเดียวกับ EOF โดยไม่มีข้อขัดแย้ง สิ่งนี้ไม่จำเป็นต้องใช้ตัวอักษรตัวอักษรที่จะมีประเภท int
Michael Burr

2
EOF == -1 มานานหลังจากค่าคงที่อักขระของ C ดังนั้นนี่จึงไม่ใช่คำตอบและไม่เกี่ยวข้องด้วยซ้ำ
Jim Balter

5

ฉันไม่เห็นเหตุผลของมัน (ตัวอักษร C char เป็นประเภท int) แต่นี่คือสิ่งที่ Stroustrup พูดถึงเรื่องนี้ (จากการออกแบบและวิวัฒนาการ 11.2.1 - ความละเอียดแบบละเอียด):

ใน C ประเภทของตัวละครตัวอักษรดังกล่าวเป็นเป็น'a' intน่าแปลกที่การให้'a'ประเภทcharใน C ++ ไม่ก่อให้เกิดปัญหาความเข้ากันได้ ยกเว้นตัวอย่างทางพยาธิวิทยาsizeof('a')ทุกโครงสร้างที่สามารถแสดงได้ทั้ง C และ C ++ ให้ผลลัพธ์เหมือนกัน

ดังนั้นส่วนใหญ่ไม่ควรทำให้เกิดปัญหา


น่าสนใจ! ค่อนข้างขัดแย้งกับสิ่งที่คนอื่นพูดเกี่ยวกับวิธีที่คณะกรรมการมาตรฐาน C "ชาญฉลาด" ตัดสินใจที่จะไม่ลบมุมแหลมนี้ออกจาก C.
j_random_hacker

2

เหตุผลทางประวัติศาสตร์คือ C และ B รุ่นก่อนได้รับการพัฒนาในรุ่นต่างๆของมินิคอมพิวเตอร์ DEC PDP ที่มีขนาดคำต่างๆซึ่งรองรับ ASCII แบบ 8 บิต แต่สามารถคำนวณเลขคณิตบนรีจิสเตอร์เท่านั้น (ไม่ใช่ PDP-11 อย่างไรก็ตามที่มาในภายหลัง) C เวอร์ชันก่อนกำหนดintให้เป็นขนาดคำดั้งเดิมของเครื่องและค่าใด ๆ ที่เล็กกว่าที่intจำเป็นต้องขยายintเพื่อที่จะส่งผ่านไปยังหรือจากฟังก์ชัน หรือใช้ในนิพจน์เชิงตรรกะหรือเลขคณิตแบบบิตเพราะนั่นคือวิธีการทำงานของฮาร์ดแวร์พื้นฐาน

นั่นเป็นสาเหตุที่กฎการส่งเสริมจำนวนเต็มยังคงบอกว่าประเภทข้อมูลใด ๆ ที่มีขนาดเล็กกว่าintจะได้รับการเลื่อนintระดับ นอกจากนี้การใช้งาน C ยังได้รับอนุญาตให้ใช้คณิตศาสตร์เสริมแทนสองส่วนเสริมด้วยเหตุผลทางประวัติศาสตร์ที่คล้ายคลึงกัน เหตุผลที่อักขระเลขฐานแปดหลบหนีและค่าคงที่ฐานแปดเป็นพลเมืองชั้นหนึ่งเมื่อเทียบกับฐานสิบหกก็เช่นเดียวกันว่ามินิคอมพิวเตอร์ DEC รุ่นแรก ๆ เหล่านั้นมีขนาดคำที่หารได้เป็นชิ้นขนาดสามไบต์ แต่ไม่ใช่สี่ไบต์


... และcharมีความยาวเลขฐานแปด 3 ตัว
Antti Haapala

1

นี่คือพฤติกรรมที่ถูกต้องเรียกว่า "การส่งเสริมแบบครบวงจร" มันสามารถเกิดขึ้นได้ในกรณีอื่น ๆ เช่นกัน (ตัวดำเนินการไบนารีส่วนใหญ่ถ้าฉันจำไม่ผิด)

แก้ไข: เพียงเพื่อให้แน่ใจว่าฉันจะตรวจสอบสำเนาของฉันของผู้เชี่ยวชาญด้านการเขียนโปรแกรม C: ความลับลึกและผมยืนยันว่าตัวอักษรถ่านไม่ได้เริ่มต้นด้วยการเป็นชนิดint เริ่มต้นเป็นประเภทcharแต่เมื่อใช้ในนิพจน์จะได้รับการเลื่อนขั้นเป็นไฟล์ int ต่อไปนี้มาจากหนังสือ:

ตัวอักษรมีประเภท int และไปที่นั่นโดยทำตามกฎสำหรับการเลื่อนตำแหน่งจากประเภท char นี่ครอบคลุมสั้นเกินไปใน K&R 1 ในหน้าที่ 39 โดยระบุว่า:

อักขระทุกตัวในนิพจน์จะถูกแปลงเป็น int .... สังเกตว่า float ทั้งหมดในนิพจน์จะถูกแปลงเป็น double .... เนื่องจากอาร์กิวเมนต์ของฟังก์ชันเป็นนิพจน์การแปลงประเภทจะเกิดขึ้นเมื่ออาร์กิวเมนต์ถูกส่งไปยังฟังก์ชัน: ใน โดยเฉพาะถ่านและสั้นกลายเป็น int ลอยกลายเป็นสองเท่า


หากเชื่อความคิดเห็นอื่น ๆ นิพจน์ 'a' จะเริ่มต้นด้วยชนิด int - ไม่มีการส่งเสริมประเภทภายใน sizeof () ที่ 'a' มีประเภท int เป็นเพียงมุมมองของ C ที่ดูเหมือน
j_random_hacker

2
ตัวอักษรถ่านจะมีชนิด int มาตรฐาน ANSI / ISO 99 เรียกสิ่งเหล่านี้ว่า 'ค่าคงที่ของอักขระจำนวนเต็ม' (เพื่อแยกความแตกต่างจาก 'ค่าคงที่อักขระแบบกว้าง' ซึ่งมีประเภท wchar_t) และกล่าวโดยเฉพาะว่า "ค่าคงที่ของอักขระจำนวนเต็มมีประเภท int"
Michael Burr

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

3
ไม่! หากคุณอ่านมาตรฐาน ANSI / ISO 99 Cคุณจะพบว่าใน C นิพจน์ 'a' เริ่มต้นด้วยประเภท int หากคุณมีฟังก์ชันเป็นโมฆะ f (int) และตัวแปรถ่าน c ดังนั้น f (c) จะทำการเลื่อนตำแหน่งแบบอินทิกรัล แต่ f ('a') จะไม่ทำงานเนื่องจากประเภทของ 'a' เป็นint อยู่แล้ว แปลก แต่จริง.
j_random_hacker

2
"เพียงเพื่อความแน่ใจ" - คุณสามารถมั่นใจได้มากขึ้นโดยการอ่านคำสั่ง: "ตัวอักษรมีประเภท int" "ฉันสามารถสันนิษฐานได้ว่านั่นคือหนึ่งในการเปลี่ยนแปลงที่เงียบ" - คุณคิดผิด อักษรตัวอักษรใน C เป็นประเภท int เสมอ
Jim Balter

0

ฉันไม่รู้ แต่ฉันจะเดาว่ามันง่ายกว่าที่จะใช้วิธีนั้นและมันก็ไม่สำคัญจริงๆ ยังไม่ถึง C ++ เมื่อชนิดสามารถกำหนดได้ว่าจะเรียกใช้ฟังก์ชันใดซึ่งจำเป็นต้องได้รับการแก้ไข


0

ฉันไม่รู้เรื่องนี้จริงๆ ก่อนที่จะมีต้นแบบสิ่งที่แคบกว่า int จะถูกแปลงเป็น int เมื่อใช้เป็นอาร์กิวเมนต์ของฟังก์ชัน นั่นอาจเป็นส่วนหนึ่งของคำอธิบาย


1
"คำตอบ" ที่น่าสงสารอีก การแปลงเป็นcharto โดยอัตโนมัติintจะทำให้ค่าคงที่ของอักขระเป็น ints ค่อนข้างไม่จำเป็น สิ่งที่เกี่ยวข้องคือภาษาปฏิบัติต่อค่าคงที่ของอักขระแตกต่างกัน (โดยให้ประเภทอื่น) จากcharตัวแปรและสิ่งที่จำเป็นคือคำอธิบายของความแตกต่างนั้น
Jim Balter

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

0

นี่เป็นเพียงสัมผัสเดียวกับข้อมูลจำเพาะของภาษา แต่ในฮาร์ดแวร์ CPU มักจะมีขนาดรีจิสเตอร์เพียงหนึ่งขนาด - 32 บิตสมมติว่า - และเมื่อใดก็ตามที่ทำงานบนถ่าน (โดยการบวกลบหรือเปรียบเทียบ) จะมี การแปลงโดยนัยเป็น int เมื่อโหลดลงในรีจิสเตอร์ คอมไพเลอร์จะดูแลการมาสก์อย่างเหมาะสมและเปลี่ยนหมายเลขหลังจากการดำเนินการแต่ละครั้งดังนั้นหากคุณเพิ่มพูด 2 ถึง (ถ่านที่ไม่ได้ลงชื่อ) 254 มันจะพันรอบเป็น 0 แทนที่จะเป็น 256 แต่ภายในซิลิกอนจะเป็น int จนกว่าคุณจะบันทึกกลับไปยังหน่วยความจำ

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

(x86 วอนอาจทราบว่ามีเช่น op addh ดั้งเดิมที่เพิ่มการลงทะเบียนแบบกว้างสั้นในขั้นตอนเดียว แต่ภายในแกน RISC จะแปลเป็นสองขั้นตอน: เพิ่มตัวเลขจากนั้นขยายเครื่องหมายเช่นคู่เพิ่ม / extsh บน PowerPC)


1
ยังตอบผิดอีก ปัญหาที่นี่คือสาเหตุที่ตัวอักษรและcharตัวแปรมีประเภทต่างๆกัน โปรโมชั่นโดยอัตโนมัติซึ่งสะท้อนให้เห็นถึงฮาร์ดแวร์ไม่เกี่ยวข้อง - พวกเขากำลังจริงต่อต้านเกี่ยวข้องเพราะตัวแปรที่มีการส่งเสริมโดยอัตโนมัติเพื่อให้เหตุผลสำหรับตัวอักษรของตัวละครจะไม่เป็นชนิดchar charเหตุผลที่แท้จริงคือตัวอักษรหลายไบต์ซึ่งปัจจุบันล้าสมัยแล้ว
Jim Balter

@ Jim Balter ตัวอักษร Multibyte ไม่ล้าสมัยเลย มีอักขระ Unicode และ UTF หลายไบต์
Crashworks

@Crashworks เรากำลังพูดถึงตัวอักษรอักขระหลายไบต์ไม่ใช่ตัวอักษรสตริงหลายไบต์ พยายามให้ความสนใจ
Jim Balter

4
Chrashworks ได้เขียนตัวอักษร คุณควรเขียนว่าอักษรตัวอักษรแบบกว้าง (พูดว่าL'à ') ใช้จำนวนไบต์มากกว่า แต่ไม่เรียกว่าตัวอักษรแบบหลายไบต์ การหยิ่งผยองน้อยลงจะช่วยให้คุณมีความถูกต้องมากขึ้น
Blaisorblade

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