[opensuse-programming] determining the number of args in a vararg call - vscprintf() ?

What is the best/correct way of counting the number of args in vararg call: int function( int blah, ... ) I've been googling a bit, and came across mentions of "vscprintf", in particular this alternative: #define vscprintf(f,a) vsnprintf(NULL,0,f,a) /Per Jessen, Zürich -- To unsubscribe, e-mail: opensuse-programming+unsubscribe@opensuse.org For additional commands, e-mail: opensuse-programming+help@opensuse.org

On Sat, 2011-02-19 at 11:21 +0100, Per Jessen wrote:
What is the best/correct way of counting the number of args in vararg call:
int function( int blah, ... )
I've been googling a bit, and came across mentions of "vscprintf", in particular this alternative:
#define vscprintf(f,a) vsnprintf(NULL,0,f,a)
I am not sure you can count them. The called function really has no way to know how many things have been put on the call stack. vsprinf parses the format string and, really, hopes for the best. This is one cause of segmentation violations. The only thing the compiler can do, after a function call, is to set the stack back to the same location as before the call. But is does not pass to the function how many items were put on the call stack. More's the pity, since the compiler knows how many things are on the stack. But the function interface design (C calling convention) does not provide a mechanism for knowing this. I guess other languages like C# might have this mechanism. Not sure. But if I wa to design a new language and function call convention, I would add a count and per-item type spec to the call. Sure would make programming less a crap shoot! Having said all this, if there was a way I would like to know what it is. I guess stack checking code that can be enabled when compiling must do something here. But I think it is hidden from the called function.
/Per Jessen, Zürich
-- Roger Oberholtzer OPQ Systems / Ramböll RST Ramböll Sverige AB Krukmakargatan 21 P.O. Box 17009 SE-104 62 Stockholm, Sweden Office: Int +46 10-615 60 20 Mobile: Int +46 70-815 1696 SHAW'S PRINCIPAL Build a system that even a fool can use, and only a fool will want to use it. -- To unsubscribe, e-mail: opensuse-programming+unsubscribe@opensuse.org For additional commands, e-mail: opensuse-programming+help@opensuse.org

On Sat, 2011-02-19 at 23:05 +0100, Roger Oberholtzer wrote:
On Sat, 2011-02-19 at 11:21 +0100, Per Jessen wrote:
What is the best/correct way of counting the number of args in vararg call:
int function( int blah, ... )
I've been googling a bit, and came across mentions of "vscprintf", in particular this alternative:
#define vscprintf(f,a) vsnprintf(NULL,0,f,a)
More's the pity, since the compiler knows how many things are on the stack.
The parameters don't really have to be on the stack either. It's implementation defined where the varargs are sent. va_start() is free to dynamically allocate memory on the heap for them There isn't a C standard for how to pass parameters. There is an x86 C calling convention, an x86_64 C calling convention, a SPARC C calling convention etc. (think stack vs. registers, for example). The language leaves that up to the implementation and only specifies how it should behave from the point of view of the C programs. The compiler doesn't even always know how large the stack is, between inline assembly and monstrosities like alloca() anything could happen. There is no guarantee that the function is called from another C binary. And on x86, the parameters are in the stack frame belonging to the previous function technically (before the base pointer, if such a thing is used), there is no way at all to know how much there is. The function needs to have some sort of convention, like the first parameter is the number of parameters, or a format string like printf, or that the argument list should be terminated by a NULL, or something. I don't think there is any other way. Anders -- To unsubscribe, e-mail: opensuse-programming+unsubscribe@opensuse.org For additional commands, e-mail: opensuse-programming+help@opensuse.org

Anders Johansson wrote:
The function needs to have some sort of convention, like the first parameter is the number of parameters, or a format string like printf, or that the argument list should be terminated by a NULL, or something. I don't think there is any other way.
I was thinking that the compiler clearly knows how many arguments is puts on the stack, so perhaps that number was also pushed on the stack. /Per Jessen, Zürich -- To unsubscribe, e-mail: opensuse-programming+unsubscribe@opensuse.org For additional commands, e-mail: opensuse-programming+help@opensuse.org

On 02/20/2011 03:14 AM, Per Jessen wrote:
I was thinking that the compiler clearly knows how many arguments is puts on the stack, so perhaps that number was also pushed on the stack.
Certainly it is the compiler that sets up the stack. As others have said, the implementation has a calling convention. On the DEC Alpha, the first 6 parameters were placed into registers with the rest of the parameters (if any) on the stack. HP PA-RISC had a similar calling convention. Whether arguments are in registers or on the stack, C defines the behavior. The order in which parameters are placed on the stack or in registers is different in C than in other languages because C (and C++) allows for a variable number of parameters. While the compiler knows how many arguments it pushed onto the stack when calling a function, it does not really know how many arguments are actually on the stack in the called function. In some implementations, there is also a stack frame register that makes it easier to unroll the stack. But there are also other things stored in the stack, such as saved registers. But in general, there is no tag on the stack that indicates the number of parameters. -- Jerry Feldman <gaf@blu.org> Boston Linux and Unix PGP key id: 537C5846 PGP Key fingerprint: 3D1B 8377 A3C0 A5F2 ECBB CA3B 4607 4319 537C 5846

On Sat, 2011-02-19 at 11:21 +0100, Per Jessen wrote:
What is the best/correct way of counting the number of args in vararg call:
int function( int blah, ... )
I've been googling a bit, and came across mentions of "vscprintf", in particular this alternative:
#define vscprintf(f,a) vsnprintf(NULL,0,f,a)
This tells you how many characters would have been copied into the destination string, had there been one. It does not tell you how many arguments there were. Only f (the format string) can do that, and then only by trusting the calling function that it's actually correct Anders -- To unsubscribe, e-mail: opensuse-programming+unsubscribe@opensuse.org For additional commands, e-mail: opensuse-programming+help@opensuse.org
participants (4)
-
Anders Johansson
-
Jerry Feldman
-
Per Jessen
-
Roger Oberholtzer