มีข้อดีหลายประการสำหรับรหัสดังกล่าว แต่น่าเสียดายที่มาตรฐาน C ไม่ได้ถูกเขียนขึ้นเพื่ออำนวยความสะดวก คอมไพเลอร์ได้เสนอการรับประกันพฤติกรรมที่มีประสิทธิภาพเกินกว่ามาตรฐานที่กำหนดซึ่งทำให้สามารถเขียนโค้ดดังกล่าวได้อย่างเรียบร้อยกว่าในมาตรฐาน C แต่คอมไพเลอร์ได้เริ่มเพิกถอนการค้ำประกันดังกล่าวในนามของการปรับให้เหมาะสมที่สุด
ที่สะดุดตาที่สุดคอมไพเลอร์ C หลายคนมีการรับประกันในอดีต (โดยการออกแบบหากไม่มีเอกสารประกอบ) ว่าหากทั้งสองประเภทโครงสร้างมีลำดับเริ่มต้นเดียวกันตัวชี้ไปยังประเภทใดประเภทหนึ่งอาจถูกใช้เพื่อเข้าถึงสมาชิกของลำดับทั่วไปแม้ว่าประเภทนั้นจะไม่เกี่ยวข้อง และยิ่งไปกว่านั้นเพื่อจุดประสงค์ในการสร้างลำดับเริ่มต้นทั่วไปพอยน์เตอร์ทั้งหมดไปยังโครงสร้างนั้นเทียบเท่ากัน รหัสที่ใช้พฤติกรรมดังกล่าวอาจสะอาดกว่าและปลอดภัยกว่ารหัสที่ไม่ได้ แต่น่าเสียดายที่แม้ว่ามาตรฐานต้องการให้โครงสร้างที่ใช้ลำดับการใช้ร่วมกันเริ่มต้นร่วมกันต้องวางในลักษณะเดียวกันมันห้ามใช้รหัสจากการใช้งานจริง ตัวชี้ชนิดหนึ่งเพื่อเข้าถึงลำดับเริ่มต้นของอีกประเภทหนึ่ง
ดังนั้นหากคุณต้องการเขียนโค้ดเชิงวัตถุใน C คุณจะต้องตัดสินใจ (และควรทำการตัดสินใจก่อน) เพื่อข้ามห่วงจำนวนมากเพื่อปฏิบัติตามกฎตัวชี้ประเภทของ C และเตรียมพร้อมที่จะมี คอมไพเลอร์สมัยใหม่จะสร้างโค้ดแบบไร้สาระหากมีการเล็ดลอดขึ้นแม้ว่าคอมไพเลอร์รุ่นเก่าจะสร้างโค้ดที่ทำงานตามที่ตั้งใจไว้หรือมีการบันทึกเอกสารข้อกำหนดอื่น ๆ ที่รหัสจะสามารถใช้ได้กับคอมไพเลอร์ที่กำหนดค่าไว้ "-fno-เคร่งครัด - aliasing") บางคนคิดว่า "-fno-เคร่งครัด - aliasing" เป็นความชั่วร้าย แต่ฉันขอแนะนำว่ามันจะมีประโยชน์มากกว่าที่จะคิดว่า "-fno-เข้มงวด-aliasing" C เป็นภาษาที่ เสนอพลังความหมายมากขึ้นสำหรับวัตถุประสงค์บางอย่างมากกว่า "มาตรฐาน" Cแต่ด้วยค่าใช้จ่ายของการปรับให้เหมาะสมซึ่งอาจมีความสำคัญต่อวัตถุประสงค์อื่น
จากตัวอย่างในคอมไพเลอร์แบบดั้งเดิมคอมไพเลอร์เชิงประวัติจะตีความโค้ดต่อไปนี้:
struct pair { int i1,i2; };
struct trio { int i1,i2,i3; };
void hey(struct pair *p, struct trio *t)
{
p->i1++;
t->i1^=1;
p->i1--;
t->i1^=1;
}
เป็นขั้นตอนต่อไปในการสั่งซื้อ: เพิ่มสมาชิกคนแรกของ*p
เสริมบิตต่ำสุดของสมาชิกคนแรกของ*t
แล้วพร่องสมาชิกคนแรกของและเติมเต็มบิตต่ำสุดของสมาชิกคนแรกของ*p
*t
คอมไพเลอร์สมัยใหม่จะจัดลำดับของการดำเนินการใหม่ในแบบที่รหัสจะมีประสิทธิภาพมากขึ้นหากp
และt
ระบุวัตถุที่แตกต่าง แต่จะเปลี่ยนพฤติกรรมหากพวกเขาไม่
ตัวอย่างนี้มีการวางแผนโดยเจตนาและในทางปฏิบัติรหัสซึ่งใช้ตัวชี้ประเภทหนึ่งเพื่อเข้าถึงสมาชิกที่เป็นส่วนหนึ่งของลำดับเริ่มต้นทั่วไปของประเภทอื่นมักจะงานได้ แต่น่าเสียดายที่ไม่มีวิธีรู้เมื่อรหัสดังกล่าวอาจล้มเหลว ไม่สามารถใช้งานได้อย่างปลอดภัยเลยยกเว้นการปิดใช้งานการวิเคราะห์นามแฝงแบบอิงประเภท
ตัวอย่างที่มีการประดิษฐ์น้อยกว่านั้นจะเกิดขึ้นหากต้องการเขียนฟังก์ชั่นเพื่อทำอะไรบางอย่างเช่นสลับสองพอยน์เตอร์เป็นประเภทใดก็ได้ ในคอมไพเลอร์ "1990s C" ส่วนใหญ่ที่สามารถทำได้ผ่าน:
void swap_pointers(void **p1, void **p2)
{
void *temp = *p1;
*p1 = *p2;
*p2 = temp;
}
อย่างไรก็ตามใน C มาตรฐานหนึ่งจะต้องใช้:
#include "string.h"
#include "stdlib.h"
void swap_pointers2(void **p1, void **p2)
{
void **temp = malloc(sizeof (void*));
memcpy(temp, p1, sizeof (void*));
memcpy(p1, p2, sizeof (void*));
memcpy(p2, temp, sizeof (void*));
free(temp);
}
หาก*p2
ถูกเก็บไว้ในที่เก็บข้อมูลที่จัดสรรและตัวชี้ชั่วคราวไม่ได้ถูกเก็บไว้ในที่จัดเก็บข้อมูลประเภทที่มีประสิทธิภาพ*p2
จะกลายเป็นประเภทของตัวชี้ชั่วคราวและรหัสที่พยายามใช้*p2
เป็นประเภทใด ๆ ที่ไม่ตรงกับตัวชี้ชั่วคราว ประเภทจะเรียกใช้พฤติกรรมที่ไม่ได้กำหนด เพื่อให้แน่ใจว่าไม่น่าเป็นไปได้อย่างยิ่งที่ผู้รวบรวมจะสังเกตเห็นสิ่งนี้ แต่เนื่องจากปรัชญาของคอมไพเลอร์สมัยใหม่ต้องการให้โปรแกรมเมอร์หลีกเลี่ยงพฤติกรรมที่ไม่ได้กำหนดเลยฉันไม่สามารถนึกถึงวิธีที่ปลอดภัยอื่น ๆ ในการเขียนรหัสข้างต้น .