Function Arguments: Know Number w/o Null

  • Thread starter Thread starter jk22
  • Start date Start date
Click For Summary

Discussion Overview

The discussion revolves around the possibility of defining a function in C or C++ that can determine the number of arguments passed to it without using a terminating null or explicitly specifying the count. The conversation touches on variadic functions, templates, and the handling of variable argument lists in both languages.

Discussion Character

  • Technical explanation
  • Debate/contested

Main Points Raised

  • Some participants assert that in C, it is not possible to know the number of arguments in a variadic function without a terminating null or explicit count.
  • Others mention that C99 and C++11 introduced variadic macros and templates, which allow for more flexible handling of arguments, but do not resolve the original question for C.
  • One participant provides a C++ example using variadic templates to demonstrate how to count and print arguments, highlighting the use of `sizeof...(args)`.
  • There is a contention regarding the standard way C handles variable arguments, with some stating that it lacks a mechanism to determine the number or types of unnamed arguments, while others argue that it provides facilities for stepping through such lists.
  • Concerns are raised about the use of C++11 features, particularly regarding object slicing and the handling of complex user-defined types in loops.
  • Participants discuss the implications of inheritance and object slicing in C++, suggesting that careful design can mitigate some issues.

Areas of Agreement / Disagreement

Participants do not reach a consensus on the capabilities of C regarding variadic functions, with some asserting limitations while others highlight available mechanisms. The discussion remains unresolved regarding the best practices for handling variable arguments in C and C++.

Contextual Notes

Limitations include the lack of a standard mechanism in C for determining the number of unnamed arguments, and the potential issues with object slicing in C++ when using certain features.

jk22
Messages
732
Reaction score
25
Is it possible to define a function f (int **a,...)

And to know the number of arguments without writing it in a nor terminating the arguments with Null ?
 
Technology news on Phys.org
jk22 said:
Is it possible to define a function f (int **a,...)

And to know the number of arguments without writing it in a nor terminating the arguments with Null ?
As an old-style variadic function, the answer is no.

C99 and C++11 added the concept of variadic macros. I'll leave that up to someone else.

C++11 added the concept of variadic templates. For example,
Code:
#include <iostream>

template<typename... Args>
void print_pointers_to_whatever (Args... args) {
    std::count << "print_pointers_to_whatever() received "
              << sizeof...(args) << " arguments. Values are:";
    char c[2] = {0,0};
    for (auto p : {args...}) {
        std::count << c << ' ' << *p;
        c[0] = ',';
    } 
    std::count << '\n';
}

int main() {
    int i1 = 1, i2 = 2, i3 = 3, i4 = 4;
    double f1 = 1.5, f2 = 2.5, f3 = 3.5;
    const char *hello = "Hello", *world = "world!";

    print_pointers_to_whatever (&i4,&i3,&i2,&i1);
    print_pointers_to_whatever (&f1,&f2,&f3);
    print_pointers_to_whatever (&hello, &world);
}

For a demo of the above, see https://ideone.com/JNe9Qv .
 
Last edited:
  • Like
Likes   Reactions: Silicon Waffle and jk22
Svein said:
C has a standard way of dealing with this. See https://en.wikipedia.org/wiki/Stdarg.h.
C does not have a standard way of dealing with this. The article you cited specifically states "There is no mechanism defined for determining the number or types of the unnamed arguments passed to the function. The function is simply required to know or determine this somehow, the means of which vary."
 
  • Like
Likes   Reactions: Silicon Waffle
D H said:
[...]
template<typename... Args>
void print_pointers_to_whatever (Args... args) {
std::count << "print_pointers_to_whatever() received "
<< sizeof...(args) << " arguments. Values are:";
char c[2] = {0,0};
for (auto p : {args...}) {
std::count << c << ' ' << *p;
c[0] = ',';
}
std::count << '\n';
}
[...][/code]
I like C++11/14's latest features but auto key and this new for loop construct I think should be used with care especially when one is having to deal with non-POD or complex user-defined types without user-defined versions of copy ctor, assignment operator, with and without universal references, etc. since their objects will be sliced off or fail to get initialized in the loop.
 
D H said:
C does not have a standard way of dealing with this. The article you cited specifically states "There is no mechanism defined for determining the number or types of the unnamed arguments passed to the function. The function is simply required to know or determine this somehow, the means of which vary."
I read it somewhat differently:
  • It provides facilities for stepping through a list of function arguments of unknown number and type.
Of course it cannot specify what it does not know, it just gives you the mechanism to handle a variable number of arguments. The C++ preprocessor uses it all the time.
 
  • Like
Likes   Reactions: Silicon Waffle
Silicon Waffle said:
I like C++11/14's latest features but auto key and this new for loop construct I think should be used with care especially when one is having to deal with non-POD or complex user-defined types without user-defined versions of copy ctor, assignment operator, with and without universal references, etc. since their objects will be sliced off or fail to get initialized in the loop.
You can always use for (auto& element : container) in such cases.

That said, the slicing problem is ever present in C++, and it's arguably only worse with constructors, move assignment operators, universal references, etc. Inheritance isn't just a double edged sword, it's sometimes a sword with edges anywhere you look. Sometimes the best way to avoid getting cut is to be very frugal with inheritance. The slicing problem pretty much disappears if you make the constructors and assignment operators in base classes protected, only elevating them to public for the final instantiable classes. In C++11/14 you can declare those final instantiable classes as final.
 

Similar threads

  • · Replies 26 ·
Replies
26
Views
3K
Replies
8
Views
2K
Replies
2
Views
2K
  • · Replies 1 ·
Replies
1
Views
2K
  • · Replies 4 ·
Replies
4
Views
2K
  • · Replies 6 ·
Replies
6
Views
2K
  • · Replies 20 ·
Replies
20
Views
5K
  • · Replies 1 ·
Replies
1
Views
3K
Replies
3
Views
2K
  • · Replies 11 ·
Replies
11
Views
2K