-4

The code is the following. The reason I'm using void * args is because this function has to be used in a threaded program. It was tested with and without any threads, and it doesn't work in any of both workflows. I'm pretty new to C and this might be obvious to the average programmer but even with gdb I can't find the problem.

void arg(const void* args) {
    char* arr = (char*) args;
    printf("%s", arr[0]);
    printf("%s", arr[1]);
    return;
}

int main (void) {
    char* a[2] = {"Hello", "World!"};
    arg((void*)a);
    return 0;
}

The above code will segfault when dereferencing args.

  • `a` is an array of `char*`'s and it decays to `char**`. Enable warnings. See [demo with warnings](https://onlinegdb.com/wgSNO5rLN) – Jason Aug 09 '22 at 16:02
  • 3
    please tag only the language you are using. C != C++. I dont know C, but in C++ there is no need to use `void*` for threading via `std::thread` – 463035818_is_not_an_ai Aug 09 '22 at 16:04
  • 1
    Elements of a `char` array are single characters, not strings. – Gerhardh Aug 09 '22 at 16:05
  • 2
    Do you really want C++ advice regarding this code? If you are writing C, the answer should be "No". – Drew Dormann Aug 09 '22 at 16:06
  • 4
    Since you tagged as C++, prefer to use `std::string`. The `std::string` maintains it's length and is easier to pass to functions. – Thomas Matthews Aug 09 '22 at 16:06
  • Since you tagged as C, remember to use the `str*()` functions with the C-String, character array. For example, use `strcmp` instead of comparing the pointers. Also, remember to allocate an extra slot in the array for the terminating nul character. – Thomas Matthews Aug 09 '22 at 16:07
  • `a` in `main()` is an array of `char *`. Passing the name of an array to a function converts it to a pointer to its first element which would be of type `char **`. The type of `arr` in `arg()` therefore needs to be `char **`, not `char *`. – Peter Aug 09 '22 at 16:09
  • 1
    "The reason I'm using `void*`" - except you're not; you're using `const void *`. Further, your types are strewn all over the place and you're "fixing" those by hard-casts. Casts aren't magic, and abusing them can, and will, hide root problems until runtime, leaving you scratching you head. That code should look [like this](https://godbolt.org/z/Eoex3nbGW). – WhozCraig Aug 09 '22 at 16:09
  • 1
    `char* a[2] = {"Hello", "World!"};` is **not valid C++**. – Jason Aug 09 '22 at 16:09
  • 2
    I think we should stop commenting on this until the OP clarifies which language he's using. – Paul Sanders Aug 09 '22 at 16:37
  • 1
    @PaulSanders True, I did not notice I added the C++ tag, sorry for the inconvenience. – Mario Olcina Aug 09 '22 at 19:35

2 Answers2

2

First things first, char* a[2] = {"Hello", "World!"}; is not valid C++. If you enable warnings you'll see that we need to declare a as

vvvvv----------------------------------->added const 
const char* a[2] = {"Hello", "World!"}; //VALID

Also there is no need to cast anything to void* here. You can directly declare the parameter to be of type const char** as shown below:

void arg(const char** args) {
    
    std::cout<<args[0]<<std::endl;
    std::cout<<args[1]<<std::endl;
    return;
}

int main () {
    const char* a[2] = {"Hello", "World!"};
    arg(a);
    return 0;
}

Working demo

Another option is to use std::string instead of string literals here.


The reason I'm using void * args is because this function has to be used in a threaded program

void arg(const void* args) {
    const char*const* ptr = static_cast<const char * const *>( args );
    std::cout<<ptr[0]<<std::endl;
    std::cout<<ptr[1]<<std::endl;
    return;
}

int main () {
//--vvvvv------------------------------------>added const
    const char* a[2] = {"Hello", "World!"};
//------v------------------------------------>no need to use cast here
    arg(a);
    return 0;
}

And the C version can look like:

void arg(void* args)
{
    const char** arr = args;
    printf("%s", arr[0]);
    printf("%s", arr[1]);
}
Jason
  • 36,170
  • 5
  • 26
  • 60
0

The expressions arr[0] and arr[1] have the type char after the casting

char* arr = (char*) args;

So at least using the conversion specifier s with objects of the type char

printf("%s", arr[0]);
printf("%s", arr[1]);

is incorrect.

It seems you mean the following

void arg(const void* args) {
    const char** arr = args;
    printf("%s", arr[0]);
    printf("%s", arr[1]);
}

Pay attention to that the array a

char* a[2] = {"Hello", "World!"};

used in expressions (with rare exceptions) is implicitly converted to a pointer of the type char **.

In C++ the array of string literals shall be declared with the qualifier const

const char* a[2] = {"Hello", "World!"};

And you need explicitly casting the pointer of the type const void to the type const char ** like for example

const char*const* arr = static_cast<const char * const *>( args );
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335