Hello!
Recently I've been working on a project which requires an API, the user supplies a function pointer which returns a specific value, this function needs a list of string arguments, similar to what you may find in the "main" function. I first thought maybe some sort of linked list but that would be inefficient so I decided on this. I first didn't really know how to implement it but after some fiddling I managed to implement this procedure to return a char** with the specified strings.

#include <stdarg.h>
char **new_argv(int count, ...)
{
    va_list args;
    int i;
    char **argv = malloc((count+1) * sizeof(char*));
    char *temp;
    va_start(args, count);
    for (i = 0; i < count; i++) {
        temp = va_arg(args, char*);
        argv[i] = malloc(sizeof(temp));
        argv[i] = temp;
    }
    argv[i] = NULL;
    va_end(args);
    return argv;
}

It is a variadic function (can accept a variable amount of arguments, ...) it accepts the amount of strings given, and the strings.

Example use:

void example()
{
    char **argv = new_argv(4, "This", "is", "a", "test");
    // argv[0] == "This"
    // argv[2] == "a"
}

I'm mainly posting this for two reasons, for people to test it and give feedback, mainly about memory efficiency, and to demonstrate it if other people need something similar in their projects.

Github Gist

Thanks for reading!

Recommended Answers

All 7 Replies

To be similar to argv in main argument you need to allocate one more than count pointers, the last pointer is NULL. That will also let you pass argv to other functions without needing to also pass the number of strings it contains.

Next, argv needs to have it's own copy of all strings so that the pointers do not get invalidated when the origianal strings are destroyed.

You also need to rename the function because it conflicts with argv array name.

#include <stdarg.h>
char **makeArgv(int count, ...)
{
    va_list args;
    int i;
    char **argv = malloc((count+1) * sizeof(char*));
    char *temp;
    va_start(args, count);
    for (i = 0; i < count; i++) {
        temp = va_arg(args, char*);
        argv[i] = malloc(sizeof(temp+1));
        strcpy(argv[i],temp);
    }
    argv[i] = NULL;
    va_end(args);
    return argv;
}

Oh I see... Wasn't aware of this, thanks for the help. I will make the change.

Please re-read my previous post for additional problems.

Line 11 argv[i] = malloc(sizeof(temp)); or the modified form argv[i] = malloc(sizeof(temp+1)); does not allocate enough memory.

temp is a char* and has a fixed size 4 bytes (or maybe 8 depending on platform) so these 2 lines respectively allocate either 4 or 5 bytes of data. You then strcpy what temp points to into the location pointed to by argv[i]. This is likely to be a larger copy than the allocated memory.

You need to allocate memory for what temp points to not temp itself, the easiest (if not most secure) way is to use strlen and add 1 for the terminator.

argv[i] = malloc(strlen(temp)+1);
commented: Right :) +14

Another way to do it is to call strdup() and you can delete the strcpy() line.

argv[i] = strdup(temp);

wow. very well done

Pointers was a bit complicated topic for me. But here I could grasp the coding easily. I have excuted the program, also I have tried out the code argv[i] = strdup(temp); by replacing strcpy() line. Now the pointers is becoming interesting for me.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.