Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. [SOLVED] Variable arguments
Forum Update on Monday, May 27th 2025

[SOLVED] Variable arguments

Scheduled Pinned Locked Moved General and Desktop
13 Posts 7 Posters 13.0k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • M Offline
    M Offline
    MarianMMX
    wrote on 11 Nov 2013, 10:02 last edited by
    #4

    Yes, I want to use C++ variadic arguments or variadic templates, but I don't know how to modify a QString passed as argument.

    1 Reply Last reply
    0
    • K Offline
      K Offline
      kqt-mr-nv6
      wrote on 11 Nov 2013, 10:10 last edited by
      #5

      you have to pass pointers to modify the passed arguments

      i recommend you to use QStringList it would be simpler
      and efficient

      you can also avoid pointers, by returning the modified QStringList

      @QStringList Function(const QStringList StringList)
      {
      QStringList TempStringList;

          // do required stuff
      

      return TempStringList;
      }@

      1 Reply Last reply
      0
      • M Offline
        M Offline
        MuldeR
        wrote on 11 Nov 2013, 12:32 last edited by
        #6

        [quote author="MarianMMX" date="1384164137"]Yes, I want to use C++ variadic arguments or variadic templates, but I don't know how to modify a QString passed as argument.[/quote]

        You really should not be using variadic arguemnts in C++, because it's absolutely NOT type-safe! And there is NO way to determine the number of arguments, except by adding an extra argument that defines the number of arguments. Nowadays, in C++, we use overloaded functions instead!

        But, if you insist, it can be done (only) like this:
        @#include <stdarg.h>

        //The following variadic function will CRASH, if either
        //1. The actual number of arguments is different from "count"
        //2. The type of any of the arguments is not QString*
        func1(const size_t count, ...)
        {
        va_list ap;
        va_start(ap, count);

        //Iterate over all string
        for (size_t i = 0; i < count; i++)
        {
            QString *currentString = va_arg(ap, (QString*));
            *currentString = "New string value";
        }
        
        va_end(ap);
        

        }

        //Use like this
        main()
        {
        QString a, b, c, d;

        func1(1, &a);
        func1(2, &a, &b);
        func1(3, &a, &b, &c);
        func1(4, &a, &b, &c, &d);
        

        }
        @

        Details:
        http://www.cplusplus.com/reference/cstdarg/va_arg/

        [quote author="MarianMMX" date="1384164137"]but I don't know how to modify a QString passed as argument.[/quote]

        See my previous post above!

        My OpenSource software at: http://muldersoft.com/

        Qt v4.8.6 MSVC 2013, static/shared: http://goo.gl/BXqhrS

        Go visit the coop: http://youtu.be/Jay...

        1 Reply Last reply
        0
        • M Offline
          M Offline
          MarianMMX
          wrote on 11 Nov 2013, 12:55 last edited by
          #7

          I try to avoid pointers, so I will use QStringList.

          1 Reply Last reply
          0
          • M Offline
            M Offline
            MuldeR
            wrote on 11 Nov 2013, 12:59 last edited by
            #8

            [quote author="MarianMMX" date="1384174555"]I try to avoid pointers, so I will use QStringList.[/quote]

            As in my example above, you can use references instead of pointers. Actually in your very first post you were using references, but you were using const references. Of course you can not modify a const reference. But you can modify a non-const reference, may it be a QString or a QStringList.

            Also note: If you are passing a QString or QStringList by-value (i.e. not as a reference or pointer), your function will get a copy of the original QString or QStringList. Then you will be able to modify the copy, but you really only modify the copy, i.e. original QString or QStringList will not be modified.

            @//Passing "by value", i.e. passing a COPY of the original
            func1(QString str)
            {
            //Modifications to "str" will NOT be visible to caller!
            }

            //Passing "by reference", i.e. passing a reference to the original
            func1(QString &str)
            {
            //Modifications to "str" will be visible to caller!
            }

            //Passing "by pointer", i.e. passing a pointer to the original
            func1(QString *str)
            {
            //Modifications to "*str" will be visible to caller!
            }@

            My OpenSource software at: http://muldersoft.com/

            Qt v4.8.6 MSVC 2013, static/shared: http://goo.gl/BXqhrS

            Go visit the coop: http://youtu.be/Jay...

            1 Reply Last reply
            0
            • M Offline
              M Offline
              MarianMMX
              wrote on 11 Nov 2013, 13:16 last edited by
              #9

              bq. Of course you can not modify a const reference.

              In the example in the first post only the first QString is const.

              bq. As in my example above, you can use references instead of pointers.

              So..
              @for (size_t i = 0; i < count; i++)

              {
              
                  QString currentString = va_arg(ap, (QString&));
              
                  currentString = "New string value";
              
              }@
              

              is OK?

              1 Reply Last reply
              0
              • M Offline
                M Offline
                MuldeR
                wrote on 11 Nov 2013, 13:29 last edited by
                #10

                You are not showing the signature of your function.

                Nor are you calling va_start() and va_end() - or you are not showing that.

                Anyway, I don't think passing references that way is possible.

                If you really want the highly error-prone variadic version, use pointers:
                @#include <stdarg.h>

                //WARNING: The following code will CRASH horribly, if the caller doesn't pass exactly "count" Pointers to QString's!
                void func1(const size_t count, ...)
                {
                va_list ap;
                va_start(ap, count);

                //Iterate over all string
                for (size_t i = 0; i < count; i++)
                {
                    QString *currentString = va_arg(ap, QString*);
                    *currentString = "New string value";
                }
                
                va_end(ap);
                

                }

                int main()
                {
                QString a = "String #1";
                QString b = "String #2";
                func1(2, &a, &b);
                }@

                Or just do it properly and safely:
                @void func1(QStringList &strings)
                {
                for (size_t i = 0; i < strings.size(); i++)
                {
                strings[i] = "New string value";
                }
                }

                int main()
                {
                QStringList list;
                list << "String #1" << "String #2";
                func1(list);
                }@

                My OpenSource software at: http://muldersoft.com/

                Qt v4.8.6 MSVC 2013, static/shared: http://goo.gl/BXqhrS

                Go visit the coop: http://youtu.be/Jay...

                1 Reply Last reply
                0
                • N Offline
                  N Offline
                  NicuPopescu
                  wrote on 11 Nov 2013, 14:10 last edited by
                  #11

                  just for the record, a templated version would be:

                  @template<class... T> void f_template(T... args)
                  {
                  const int size = sizeof...(args);
                  QString *res[size] = {args...};
                  for(int i=0;i<size;i++)
                  {
                  *res[i] = "new string";
                  }
                  }
                  ...
                  f_template(&s1,&s2,&s3,&s4);
                  ...
                  @

                  no need to pass the args count and is type safe ...

                  1 Reply Last reply
                  2
                  • osirisgothraO Offline
                    osirisgothraO Offline
                    osirisgothra
                    wrote on 23 Dec 2024, 18:08 last edited by
                    #12

                    future users - stay away from va_args, they have always caused issues because people think they found a way to count the uncountable arguments (ie, depending on memory values, which differ depending on the compiler, not every compiler resets unused memory, if any, after the stored values and you may just be reading into undefined space causing at least an exception/crash or at worst catastrophic damage)
                    You can apply the above to class functions as well, even static ones and its important to note that template values with typenames specifiers will be deduced by the caller:
                    so calling "template<typename... T> func(T... args)" with func("a", "b") will turn that T into const char* automatically without having to specify func<const char*>

                    Some people rejoining C++ after decades might think you would have to do that, and it is because of how explicit C++ used to be way back when (before ISO).

                    I've noticed this detail gets largely glossed over these days because the new C++ standard is largely implicit, but to oldschool programmers this is a detail you should probably be made aware of and that's C++'s many new "deductions" that have been signed into standard over the years. One such deduction is performed right before template expansion and that would be the above mentioned template type/classname deduction which is why you can call f_template(args) without doing f_template<type>(args).

                    I'm truly glad you r/offmychess t finally, but please don't go too far, because you r/beyondvoxels and that implies that u r/donewithlife. Oh well time to git back to the lab, because azure sea here, I have a lot of work to do...

                    1 Reply Last reply
                    0
                    • crimson1023C Offline
                      crimson1023C Offline
                      crimson1023
                      wrote on 23 Dec 2024, 20:20 last edited by
                      #13

                      You can refer to this code.

                      void my_printf(const char *format, ...) {
                          va_list args;
                          va_start(args, format);
                          
                          for (const char *p = format; *p != '\0'; p++) {
                              if (*p == '%') {
                                  p++; // Move past '%'
                                  switch (*p) {
                                      case 'd': { // Handle integer
                                          int i = va_arg(args, int);
                                          printf("%d", i);
                                          break;
                                      }
                                      case 'c': { // Handle char
                                          char c = (char)va_arg(args, int); // char is promoted to int
                                          putchar(c);
                                          break;
                                      }
                                      case 's': { // Handle string
                                          char *s = va_arg(args, char *);
                                          printf("%s", s);
                                          break;
                                      }
                                      default: // Handle unknown format specifiers
                                          putchar('%');
                                          putchar(*p);
                                          break;
                                  }
                              } else {
                                  putchar(*p); // Print regular character
                              }
                          }
                          
                          va_end(args);
                      }
                      
                      1 Reply Last reply
                      0

                      • Login

                      • Login or register to search.
                      • First post
                        Last post
                      0
                      • Categories
                      • Recent
                      • Tags
                      • Popular
                      • Users
                      • Groups
                      • Search
                      • Get Qt Extensions
                      • Unsolved