พฤติกรรมแปลก ๆ ของ memcpy
ฉันต้องการคัดลอกจำนวนเต็มที่ยาวที่ไม่ได้ลงนามไปยังถ่านบัฟเฟอร์ไบต์โดยไบต์ ถ้าฉันใช้บรรทัดใต้ความคิดเห็นมันจะไม่ถูกคัดลอกไปยังบัฟเฟอร์
char buf[128];
//unsigned long int_val = 268435456;
unsigned long int_val = 293456376;
cout << "Value of int_val: " << int_val << endl;
memset(buf, 0, sizeof(buf));
memcpy(buf, &int_val, sizeof(long));
cout << "Value after unsigned long int copy - buf: " << buf << endl;
const int len = strlen(buf);
cout << "buf" << endl << "====" << endl;
for (int i = 0; i < len; i++)
{
printf("%3d (0x%02X)\n", buf[i], buf[i]);
}
ต่อไปนี้คือผลลัพธ์ของการรันสองครั้งที่แต่ละค่า:
Value of int_val: 268435456
Value after unsigned long int copy - buf:
buf
===
Value of int_val: 293456376
Value after unsigned long int copy - buf: ��}
buf
===
-8 (0xFFFFFFF8)
-55 (0xFFFFFFC9)
125 (0x7D)
17 (0x11)
คำตอบ
ในเลขฐานสิบหกเป็น 268435456 10000000 16 คุณ c ++ ร้านค้าไบต์ของนั้นunsigned longในความทรงจำกับไบต์มูลค่าต่ำก่อนหน้านี้ในหน่วยความจำดังนั้นนี้จะถูกเก็บไว้ในหน่วยความจำเป็นไบต์มีค่า 00 16 , 00 16 , 00 16 10 16
memcpybufได้อย่างถูกต้องสำเนาเหล่านี้เข้าไปในไบต์
จากนั้นเมื่อstrlen(buf)ตรวจสอบbufจะพบค่า null ไบต์ (00 16 ) ก่อน สิ่งนี้บ่งชี้ว่าสตริงอักขระbufมีความยาวเป็นศูนย์เนื่องจากอักขระยุติจะปรากฏขึ้นทันทีที่จุดเริ่มต้น จึงstrlen(buf)คืนค่าศูนย์
เนื่องจากค่าส่งคืนนี้ถูกกำหนดให้lenกับลูปจึงfor (int i = 0; i < len; i++)ทำการวนซ้ำเป็นศูนย์
ในทำนองเดียวกันในcout << "Value after unsigned long int copy - buf: " << buf << endl;, bufมีสตริงของความยาวเป็นศูนย์ดังนั้นไม่มีตัวอักษรที่พิมพ์สำหรับมัน
ไม่ได้คัดลอกไปยังบัฟเฟอร์
ใช่แล้ว.
cout << ... << buf << endl; const int len = strlen(buf);
ไม่ชัดเจนว่าทำไมคุณถึงไม่คาดหวังผลลัพธ์ที่คุณเห็น 0 คือค่าของอักขระเทอร์มิเนเตอร์ null ถ้าไบต์ลำดับหน่วยความจำต่ำสุดของจำนวนเต็มคือ 0 บัฟเฟอร์จะมีสตริงที่สิ้นสุดด้วยค่าว่างที่แสดงถึงสตริงว่าง ในกรณีเช่นนี้ผลลัพธ์ที่คุณเห็นจะเป็นที่คาดหวัง ในระบบ endian ขนาดเล็ก (และในระบบ endian ขนาดใหญ่ที่longมีความกว้างมากกว่า 4 ไบต์) ซึ่งเป็นกรณีของ 268435456 ซึ่งเป็นเลขฐานสิบหก 0x10'00'00'00
เพียงเพราะไบต์ที่คุณคัดลอกแสดงถึงสตริงว่างไม่ได้หมายความว่าไบต์นั้นไม่ได้ถูกคัดลอก