Jump to content
  • Advertisement
Sign in to follow this  
random_thinker

Curious : What is the dreaded elipsis construct?

This topic is 4682 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I've seen some posts with the mention of the "dreaded elipsis construct". What is it, and why is it 'dreaded'? --random [Edited by - random_thinker on August 26, 2005 3:27:00 PM]

Share this post


Link to post
Share on other sites
Advertisement
It's vararg functions, such as printf, which take an arbitrary number of arguments. And it's dreaded in C++ because it completely discards type-safety in favor of a bizarre, complex, and unintuitive system of type coercion and unsafe getter functions.

Share this post


Link to post
Share on other sites
The ellipsis construct is used in varidic functions like printf(). You using it like:

int my_function(int some_argument, ...);


And the ellipsis construct sucks up all the parameters after the initial arguments. This is one of the legacies C++ has inherited from C. The down side is that the ellipsis completely destroys type safety. There is no knowledge of type except what the function can guess from the non-ellipsis arguments. This construct does not interact well with pretty much any C++ features. In particular trying to pass a class type to a function with ellipsis arguments is bad bad mojo, since the constructor will probably be called when placing it on the stack and the destructor will not be called since the varidic function won't know how to clean it up.

Share this post


Link to post
Share on other sites
Thanks Chaps..

When you mentioned variadic functions, I looked this up on the GNU.org website:


#include <stdarg.h>
#include <stdio.h>

int
add_em_up (int count,...)
{
va_list ap;
int i, sum;

va_start (ap, count); /* Initialize the argument list. */

sum = 0;
for (i = 0; i < count; i++)
sum += va_arg (ap, int); /* Get the next argument value. */

va_end (ap); /* Clean up. */
return sum;
}

int
main (void)
{
/* This call prints 16. */
printf ("%d\n", add_em_up (3, 5, 5, 6));

/* This call prints 55. */
printf ("%d\n", add_em_up (10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10));

return 0;
}



I understand what you mean now...passing objects here could be a disaster!

Thanks Chaps!

--random

Share this post


Link to post
Share on other sites
Quote:
Original post by random_thinker
Thanks Chaps..

When you mentioned variadic functions, I looked this up on the GNU.org website:

*** Source Snippet Removed ***

I understand what you mean now...passing objects here could be a disaster!

Thanks Chaps!

--random


Try passing a std::string by value to printf. The results may surprise you.

MSN

Share this post


Link to post
Share on other sites
Quote:
In particular trying to pass a class type to a function with ellipsis arguments is bad bad mojo, since the constructor will probably be called when placing it on the stack and the destructor will not be called since the varidic function won't know how to clean it up.

I think this reflects lack of understanding of the C calling convention. Despite the presence of "RET n" instructions that return from callee and adjust the stack (-> smaller code), the caller is responsible for cleanup. This is precisely because variadic functions do not know what was passed, but the caller (who pushed those params) does.

And I feel obligated to mention this every time the topic comes up: 1) printf has power unmatched by cout << and is quite concise 2) non-crappy compilers do type checking on known variadic functions!

Share this post


Link to post
Share on other sites
Quote:
Original post by Jan Wassenberg
Quote:
In particular trying to pass a class type to a function with ellipsis arguments is bad bad mojo, since the constructor will probably be called when placing it on the stack and the destructor will not be called since the varidic function won't know how to clean it up.

I think this reflects lack of understanding of the C calling convention. Despite the presence of "RET n" instructions that return from callee and adjust the stack (-> smaller code), the caller is responsible for cleanup. This is precisely because variadic functions do not know what was passed, but the caller (who pushed those params) does.

And I feel obligated to mention this every time the topic comes up: 1) printf has power unmatched by cout << and is quite concise 2) non-crappy compilers do type checking on known variadic functions!


Jan,

Would you have a code example of how you'd clean up after using an elipsis construct on C++ objects? I'm curious as to how this should be done.

--random

Share this post


Link to post
Share on other sites
Quote:
Original post by Jan Wassenberg
I think this reflects lack of understanding of the C calling convention. Despite the presence of "RET n" instructions that return from callee and adjust the stack (-> smaller code), the caller is responsible for cleanup. This is precisely because variadic functions do not know what was passed, but the caller (who pushed those params) does.


Whether or not it's supposed to happen. I've seen the kind of lack of destructor call problem happen in real code. IMO, it's not worth the risk to assume that the calling code will clean up properly.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!