我想設計一個函數,它帶有可變數量的參數,其中一個參數本身就是va_list
;但我的代碼中出現錯誤,我不明白是什麼...把一個va_list變量放在一個變量參數列表(!)裏面
警告 - 我的問題不是關於設計一個代碼做我想做的事情(我找到了一種方法來繞過這個問題),但只有理解我做錯了什麼......
解釋我的問題,讓我們先從一個簡單的例子,即:一個功能ffprintf
這就像fprintf
,但是寫的內容下載到若干字符串,字符串,其數量爲由ffprintf
的第一個參數指示,其身份由下一個參數給出(這些參數的數量可能因呼叫而異,因此您必須使用變量argum ent list)。這樣的功能會被這樣使用:
FILE *stream0, *stream1, *stream2;
int a, b;
ffprintf (3, stream0, stream1, stream2, "%d divided by %d worths %f", a, b, (double)a/b);
而且它的代碼是:
void ffprintf (int z, ...)
{va_list vlist, auxvlist;
FILE **streams = malloc (z * sizeof(FILE *));
va_start (vlist, z);
for (int i = 0; i < z; ++i)
{streams[i] = va_arg (vlist, FILE *); // Getting the next stream argument
}
char const *format = va_arg (vlist, char const *); // Getting the format argument
for (int i = 0; i < z; ++i)
{va_copy (auxvlist, vlist); // You have to work on a copy "auxvlist" of "vlist", for otherwise "vlist" would be altered by the next line
vfprintf (streams[i], format, auxvlist);
va_end (auxvlist);
}
va_end (vlist);
free (streams);
}
這工作正常。現在,也有標準功能vfprintf
,它的原型是vfprintf (FILE *stream, char const* format, va_list vlist);
,並且你使用這樣來創建具有可變參數列表中的其他功能:
void fprintf_variant (FILE *stream, char const* format, ...)
{
va_list vlist;
va_start (vlist, format);
vfprintf (stream, format, vlist);
va_end (vlist);
}
這太正常工作。現在,我的目標是這兩個觀念結合起來,創造一個功能,我會打電話vffprintf
,你會使用這樣的:
FILE *stream0, *stream1, *stream2;
void fprintf_onto_streams012 (char const *format, ...)
{va_list vlist;
va_start (vlist, format);
vffprintf (3, stream0, stream1, stream2, format, vlist);
va_end (vlist);
}
我設計了下面的代碼:
void vffprintf (int z, ...)
{va_list vlist, auxvlist, auxauxvlist;
va_start (vlist, z);
FILE **streams = malloc (z * sizeof(FILE *));
for (int i = 0; i < z; ++i)
{streams[i] = va_arg (vlist, FILE *);
}
char const *format = va_arg (vlist, char const *);
va_copy (auxvlist, va_arg (vlist, va_list)); // Here I get the next argument of "vlist", knowing that this argument is of "va_list" type
for (int i = 0; i < z; ++i)
{va_copy (auxauxvlist, auxvlist);
vfprintf (streams[i], format, auxvlist);
va_end (auxauxvlist);
}
va_end (auxvlist);
va_end (vlist);
free (streams);
}
此代碼編譯順利,但它不能正常工作...例如,如果我寫了下面的完整代碼:
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
void vffprintf (int z, ...)
{va_list vlist, auxvlist, auxauxvlist;
FILE **streams = malloc (z * sizeof(FILE *));
va_start (vlist, z);
for (int i = 0; i < z; ++i)
{streams[i] = va_arg (vlist, FILE *);
}
char const *format = va_arg (vlist, char const *);
va_copy (auxvlist, va_arg (vlist, va_list));
for (int i = 0; i < z; ++i)
{va_copy (auxauxvlist, auxvlist);
vfprintf (streams[i], format, auxauxvlist);
va_end (auxauxvlist);
}
va_end (auxvlist);
va_end (vlist);
free (streams);
}
void printf_variant (char const *format, ...)
{va_list vlist;
va_start (vlist, format);
vffprintf (1, stdout, format, vlist);
va_end (vlist);
}
int main (void)
{printf_variant ("Ramanujan's number is %d.\n", 1729);
return 0;
}
,我收到了段錯誤...爲什麼?!
P.-S .:對不起,這個很長的問題;但我希望它非常清楚,因爲它是相當技術性的...
P.-S.2:我故意爲這個問題使用了兩個標籤「va-list」和「variableargumentlists」,因爲這對我感興趣是va_list
,看作是類型,在(其他)變量參數列表中,被看作列表 ...因此,這些實際上是兩個不同的概念。
所以問題是爲什麼最後一個例子失敗? – this
是的,這正是:-) –
如果您忽略內存泄漏,看起來很好。 – this