Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Verifying variable arguments are of expected type

I'm currently writing a function which will take a variable number of arguments. I pass the number of arguments into the function and then will iterate through the arguments list.

Each of the passed arguments should be an integer. I will be adding this integer to a vector of integers which will be used later.

I would like to make sure that some joker doesn't attempt to pass this function something other then an integer in the future. I recognize that I can check the current argument from va_arg to ensure it is not NULL and I can use something like isanum(va_arg()) to determine if it is a valid integer. I suppose I could even check the sizeof(va_arg) and compare it against the sizeof(int) and ensure they are equal.

Are there any other checks which I can run to verify I have been passed a valid integer?

Thanks in advance for assistance

like image 618
BSchlinker Avatar asked Jun 24 '11 18:06

BSchlinker


People also ask

How do you check a method argument in Python?

The inspect module helps in checking the objects present in the code that we have written. We are going to use two methods i.e. signature() and getargspec() methods from the inspect module to get the list of parameters name of function or method passed as an argument in one of the methods.

What symbols are used in a function declaration to indicate that it is a Variadic function?

A function with a parameter that is preceded with a set of ellipses ( ... ) is considered a variadic function. The ellipsis means that the parameter provided can be zero, one, or more values.


4 Answers

There is no sensible way you can do this. Variable-argument functions work by concatenating all the raw binary representations of the arguments into one big chunk of data on the stack. So it relies on both the caller and the callee agreeing on what the number and type of arguments are (otherwise you'll end up reading e.g. an int as if it were a float).

As to your specific ideas:

  • va_arg() is a macro that simply interprets some number of bytes of the raw stack data as whatever type you specify. So invoking sizeof() on it will simply tell you the size of the data type you asked for.

  • In general, there are no patterns of raw binary data that form an invalid integer. So the hypothetical isanum() could not work.

like image 156
Oliver Charlesworth Avatar answered Oct 19 '22 23:10

Oliver Charlesworth


Each of the passed arguments should be an integer.

If you have a C++0x compiler, I suggest an initializer_list<int> instead of varargs:

#include <initializer_list>

void foo(std::initializer_list<int> numbers)
{
    my_vector.insert(my_vector.end(), numbers.begin(), numbers.end());
}

int main()
{
    foo( {2, 3, 5, 7} );
}

This is straight-forward and completely type-safe.

like image 44
fredoverflow Avatar answered Oct 20 '22 00:10

fredoverflow


Each of the passed arguments should be an integer. I will be adding this integer to a vector of integers which will be used later.

Then why not just accept a vector of integers?

void AddIntegers(const std::vector<int>& vec);

You can then always concatenate vectors together using iterators.

Or make an interface like this:

void AddInteger(int newInt);

Or even this:

void AddIntegers(const int* integers, unsigned int numIntegers);

template <unsigned int Size>
void AddIntegers(int (&integers)[Size])
{
    AddIntegers(integers, Size);
}

int main()
{
    int i[] = {1, 2, 3, 4};
    AddIntegers(i);
}

These will work if you need to work with a C++03 compiler. If you have a C++0x compiler, there are far superior solutions available.

like image 22
In silico Avatar answered Oct 19 '22 23:10

In silico


Variable arguments are unsafe by design. You cannot check that the user passed correct type in any way. C++0x comes to the rescue with variadic templates but not many compilers support it nowadays (only GCC afaik).

like image 45
Karel Petranek Avatar answered Oct 20 '22 01:10

Karel Petranek