ฉันมีกลุ่มของฟังก์ชันที่ประกาศไว้ทั้งหมดเป็น static
และ fastcall
ส่วนใหญ่ใช้ตัวชี้ไปยังโครงสร้างที่รองรับบทบาทของ this
ใน C++ ไม่มากก็น้อย ฟังก์ชั่นบางอย่างไม่ต้องการอะไรในโครงสร้าง แต่เพื่อความสม่ำเสมอฉันอยากจะส่งต่อตัวชี้ให้พวกเขาต่อไป คอมไพเลอร์จะสังเกตเห็นว่าไม่ได้ใช้อาร์กิวเมนต์และละเว้นการจัดสรรการลงทะเบียนหรือไม่
คอมไพเลอร์จะปรับอาร์กิวเมนต์ที่ไม่ได้ใช้ของฟังก์ชันคงที่ให้เหมาะสมหรือไม่
คำตอบ (3)
ฉันเขียนโปรแกรมไร้สาระนี้เพื่อทดสอบสิ่งนี้ มันมีโค้ดไร้สาระอยู่ในฟังก์ชัน และเรียกมันหลายครั้งเพราะไม่เช่นนั้นคอมไพเลอร์ก็จะอินไลน์การเรียกใช้ฟังก์ชันทั้งหมด ทำให้การทดสอบไร้ประโยชน์ (มันเป็นการผสมผสานที่แปลกของ C และ C++ ฉันรู้ว่า.... รหัสโง่ ๆ แต่ก็ยังใช้งานได้เพื่อสาธิตปัญหา)
#include <stdio.h>
#include <vector>
#include <algorithm>
using namespace std;
struct demo
{
int a;
char ch;
};
static void __fastcall func(struct demo* d)
{
for(int i = 0; i < 100; i++) {
std::vector<int> a;
std::sort(begin(a), end(a));
printf("THis is a test");
printf("Hello world\n");
}
}
int main()
{
// void*p = (void*)&func;
struct demo d;
func(&d);
func(&d);
func(&d);
func(&d);
func(&d);
func(&d);
func(&d);
//printf((const char*)p);
}
ตามที่เขียนไว้ที่นั่นการเรียกใช้ฟังก์ชันคอมไพล์ดังนี้: -
func(&d);
00F61096 call func (0F61000h)
func(&d);
00F6109B call func (0F61000h)
func(&d);
00F610A0 call func (0F61000h)
func(&d);
00F610A5 call func (0F61000h)
func(&d);
00F610AA call func (0F61000h)
func(&d);
00F610AF call func (0F61000h)
func(&d);
00F610B4 call func (0F61000h)
ซึ่งแสดงว่าคอมไพเลอร์ จะละเว้นพารามิเตอร์ อย่างแน่นอนหากไม่ได้ใช้ อย่างไรก็ตาม หากฉันไม่ใส่เครื่องหมายสองบรรทัดตรงนั้นเพื่อรับที่อยู่ของฟังก์ชัน จากนั้นสิ่งต่าง ๆ ก็เปลี่ยนไป มันจะสร้างสิ่งนี้แทน:-
00C71099 lea ecx,[esp]
00C7109C call func (0C71000h)
func(&d);
00C710A1 lea ecx,[esp]
00C710A4 call func (0C71000h)
func(&d);
00C710A9 lea ecx,[esp]
00C710AC call func (0C71000h)
func(&d);
00C710B1 lea ecx,[esp]
00C710B4 call func (0C71000h)
มันจะส่งตัวชี้ไปที่ไหน
สมมติฐานของฉันคือในกรณีแรกคอมไพเลอร์สามารถพิสูจน์ได้ว่าถ้ามันสร้างรูปแบบการเรียกแบบกำหนดเองให้กับฟังก์ชันที่ไม่มีเอฟเฟกต์ที่ผู้ใช้มองเห็นได้ แต่ในกรณีที่สองที่คุณใช้ตัวชี้ไปยังฟังก์ชัน ฟังก์ชัน สามารถเรียกได้จากโมดูลอื่นที่คอมไพล์แยกกัน ซึ่งไม่มีทางรู้ได้ว่าจำเป็นต้องใช้พารามิเตอร์หรือไม่ แม้ว่าในกรณีนี้ มันไม่สำคัญว่ารีจิสเตอร์จะถูกตั้งค่าหรือไม่ โดยทั่วไปคอมไพลเลอร์จำเป็นต้องยึดติดกับรูปแบบการเรียกที่แน่นอน ดังนั้นฉันคิดว่ามันสร้างโค้ดทั่วไปที่สุด และจะไม่ใช้แบบแผนการเรียกแบบกำหนดเองหากทำได้ ไม่ต้องพิสูจน์ว่ามันสามารถดูโค้ดทั้งหมดที่สามารถเรียกใช้ฟังก์ชันได้
อย่างไรก็ตาม เพื่อตอบคำถาม ไม่มีคอมไพเลอร์จะไม่ส่งพารามิเตอร์ที่ไม่ได้ใช้ในรีจิสเตอร์เสมอไป แต่ฉันจะไม่เขียนโค้ดใด ๆ ที่ขึ้นอยู่กับพฤติกรรมเฉพาะใด ๆ ที่นี่เป็นการเปลี่ยนโค้ดที่ไม่เกี่ยวข้องที่อื่น (รับที่อยู่ของฟังก์ชัน) เปลี่ยนไป พฤติกรรมนั้นและไม่มีอะไรรับประกันด้วยมาตรฐานใด ๆ ที่ฉันเห็น
ก่อนอื่น คอมไพลเลอร์ควรเตือนคุณเกี่ยวกับอาร์กิวเมนต์ของฟังก์ชันที่ไม่ได้ใช้ หากคุณใช้แฟล็กคอมไพเลอร์ที่เหมาะสม (เช่น -Wall) ฉันขอแนะนำให้ทิ้งอาร์กิวเมนต์ที่คุณไม่ได้ใช้ออกจากรายการอาร์กิวเมนต์ แม้ว่าฉันจะ เดาว่าพวกเขาจะได้รับการปรับให้เหมาะสม สิ่งที่คุณสามารถทำได้เพื่อให้แน่ใจว่าคอมไพล์โค้ดของคุณสองครั้ง ครั้งแรกกับอาร์กิวเมนต์และอีกครั้งไม่มี และทำ diff
ระหว่างไบนารี่เพื่อดูว่าตรงกันหรือไม่ ฉันคิดว่ามันควรขึ้นอยู่กับคอมไพเลอร์ที่คุณใช้และแฟล็กการปรับให้เหมาะสม
ไชโย
แอนดี้
diff
- จะไม่สามารถตรวจสอบความแตกต่างได้ (เนื่องจากการดำเนินการขึ้นอยู่กับสิ่งอื่น ๆ มากมายที่อาจแตกต่างกันไปในแต่ละกระบวนการดำเนินการ ยิ่งไปกว่านั้น การเริ่มต้นตัวแปรจะใช้เวลามากขนาดนั้น
- person exexzian; 12.01.2013
do a diff between the binaries
- ฉันกำลังถามไบนารี่ diff b/w ของอะไร? เวลาดำเนินการหรือ ??
- person exexzian; 12.01.2013
คุณสามารถละเว้นอาร์กิวเมนต์ในนิยามฟังก์ชันได้ สิ่งนี้จะให้คำแนะนำแก่คอมไพเลอร์ว่าไม่ได้ใช้อาร์กิวเมนต์ Perticular มันจะใช้ประโยชน์จากมันและปรับโค้ดให้เหมาะสม
เป็นโมฆะ func (สาธิตโครงสร้าง *) { ... }