ใช่คุณสามารถทำได้ แต่มันค่อนข้างน่าเกลียดและคุณต้องรู้จำนวนอาร์กิวเมนต์สูงสุด นอกจากนี้หากคุณอยู่ในสถาปัตยกรรมที่อาร์กิวเมนต์ไม่ถูกส่งผ่านบนสแต็กเช่น x86 (เช่น PowerPC) คุณจะต้องทราบว่ามีการใช้ประเภท "พิเศษ" (double, float, altivec เป็นต้น) หรือไม่ ดังนั้นจัดการกับพวกเขาตาม อาจเจ็บปวดได้อย่างรวดเร็ว แต่ถ้าคุณใช้ x86 หรือถ้าฟังก์ชั่นดั้งเดิมมีขอบเขตชัดเจนและ จำกัด ก็สามารถใช้งานได้
มันจะยังคงเป็นแฮ็คใช้สำหรับการดีบัก อย่าสร้างซอฟต์แวร์ให้กับคุณ ต่อไปนี้เป็นตัวอย่างการทำงานใน x86:
#include <stdio.h>
#include <stdarg.h>
int old_variadic_function(int n, ...)
{
va_list args;
int i = 0;
va_start(args, n);
if(i++<n) printf("arg %d is 0x%x\n", i, va_arg(args, int));
if(i++<n) printf("arg %d is %g\n", i, va_arg(args, double));
if(i++<n) printf("arg %d is %g\n", i, va_arg(args, double));
va_end(args);
return n;
}
int old_variadic_function_wrapper(int n, ...)
{
va_list args;
int a1;
int a2;
int a3;
int a4;
int a5;
int a6;
int a7;
int a8;
/* Do some work, possibly with another va_list to access arguments */
/* Work done */
va_start(args, n);
a1 = va_arg(args, int);
a2 = va_arg(args, int);
a3 = va_arg(args, int);
a4 = va_arg(args, int);
a5 = va_arg(args, int);
a6 = va_arg(args, int);
a7 = va_arg(args, int);
va_end(args);
return old_variadic_function(n, a1, a2, a3, a4, a5, a6, a7, a8);
}
int main(void)
{
printf("Call 1: 1, 0x123\n");
old_variadic_function(1, 0x123);
printf("Call 2: 2, 0x456, 1.234\n");
old_variadic_function(2, 0x456, 1.234);
printf("Call 3: 3, 0x456, 4.456, 7.789\n");
old_variadic_function(3, 0x456, 4.456, 7.789);
printf("Wrapped call 1: 1, 0x123\n");
old_variadic_function_wrapper(1, 0x123);
printf("Wrapped call 2: 2, 0x456, 1.234\n");
old_variadic_function_wrapper(2, 0x456, 1.234);
printf("Wrapped call 3: 3, 0x456, 4.456, 7.789\n");
old_variadic_function_wrapper(3, 0x456, 4.456, 7.789);
return 0;
}
ด้วยเหตุผลบางอย่างคุณไม่สามารถใช้การลอยด้วย va_arg ได้ gcc บอกว่ามันถูกแปลงเป็นสองเท่า แต่โปรแกรมขัดข้อง สิ่งนี้แสดงให้เห็นว่าโซลูชั่นนี้เป็นแฮ็กและไม่มีวิธีแก้ปัญหาทั่วไป ในตัวอย่างของฉันฉันคิดว่าจำนวนการโต้แย้งสูงสุดคือ 8 แต่คุณสามารถเพิ่มจำนวนนั้นได้ ฟังก์ชั่นที่ห่อหุ้มยังใช้เลขจำนวนเต็มเท่านั้น แต่มันทำงานในลักษณะเดียวกันกับพารามิเตอร์ 'ปกติ' อื่น ๆ เนื่องจากมันส่งไปยังจำนวนเต็มเสมอ ฟังก์ชั่นเป้าหมายจะรู้ประเภทของมัน แต่ผู้ห่อหุ้มตัวกลางของคุณไม่จำเป็นต้องใช้ กระดาษห่อยังไม่จำเป็นต้องรู้จำนวนอาร์กิวเมนต์ที่เหมาะสมเนื่องจากฟังก์ชั่นเป้าหมายจะรู้ได้ด้วย หากต้องการทำงานที่มีประโยชน์ (ยกเว้นเพียงบันทึกการโทร) คุณอาจต้องรู้ทั้งคู่