2

I can't figure out this error during parameter passing.

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

typedef char my_char;

void myfunc(const my_char** data)
{
    printf ("%s\n", *data);
    printf ("%s\n", *(data + 1));
}

int main(){

    char **mydata;
    mydata = malloc(sizeof(char*)*2);
    mydata[0] = malloc(sizeof(char)*50);
    mydata[1] = malloc(sizeof(char)*50);

    memset(mydata[0],'\0',50);
    memset(mydata[1],'\0',50);
    strcpy (mydata[0], "Hello");
    strcpy (mydata[1], "world");

    myfunc((my_char**)mydata);

    free (mydata[0]);
    free (mydata[1]);
    free (mydata);

    return 0;
}

It works properly. But gives a warning when I typecast the argument explicitly. Why is this so? The warning displayed is :

warning: passing argument 1 of ‘myfunc’ from incompatible pointer type

As far as I know, the typecasting should help the compiler understand , what type of data the pointer is holding on to. But here its not helping at all.

0aslam0
  • 1,797
  • 5
  • 25
  • 42
  • 2
    `const my_char**` and `my_char**` are not compatible, you see. – Sourav Ghosh Jan 13 '15 at 09:00
  • 1
    This is a reasonable question, not sure about the downvotes. It's in the [C FAQ](http://c-faq.com/ansi/constmismatch.html) but other introductory materials might not have covered the topic. – M.M Jan 13 '15 at 09:01
  • @SouravGhosh I thought const didn't make much difference. – 0aslam0 Jan 13 '15 at 09:04
  • 1
    Your instinct is right, but the compiler treats them differently – nj-ath Jan 13 '15 at 09:07
  • @darknight No, the instinct is wrong and the compiler is right. The compiler is almost always right. When it's not right, a team of highly trained monkeys usually gets it fixed. But your instinct is something only you can fix. – n. m. could be an AI Jan 13 '15 at 09:11
  • `char **` *should* be implicitly convertible to `char * const *` however the designers of C never got around to adding that in... – M.M Jan 13 '15 at 09:13
  • I like the way you put it. @n.m. – 0aslam0 Jan 13 '15 at 09:13
  • Why "should be convertible" ? @MattMcNabb – 0aslam0 Jan 13 '15 at 09:14
  • @xachu4u there's nothing that can go wrong that way. Your function should take `char const * const * data` to indicate that neither the strings, nor the pointers to the strings, will be changed by the function. It'd be nice if you could just write `myfunc(mydata);` to call the function but C doesn't allow it. (C++ does) – M.M Jan 13 '15 at 09:16
  • The only workarounds are ugly; you can write `myfunc( (void *)mydata );` (technically UB I think), or include the cast (perhaps with the cast hidden by a macro) – M.M Jan 13 '15 at 09:17

3 Answers3

2

Use const while typecasting the datatype.

myfunc((const my_char**)mydata);

You are getting that value as a const in a function.

Karthikeyan.R.S
  • 3,991
  • 1
  • 19
  • 31
  • Could you elaborated on _why_ this is the case? `const int* x = (int*) 1;` does not produce a warning, yet just adding another level of indirection does. – llf May 27 '18 at 02:18
0

Remove const, adding a const causes the type of argument passed to be confused from declaration, and type-cast the data elements like so:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

typedef char my_char;

void myfunc(my_char** data)
{
    printf("%s\n", *data);
    printf("%s\n", *(data + 1));
}

int main(){

    char **mydata;
    mydata = (char **)malloc(sizeof(char*)* 2);
    mydata[0] = (char *)malloc(sizeof(char)* 50);
    mydata[1] = (char *)malloc(sizeof(char)* 50);

    memset(mydata[0], '\0', 50);
    memset(mydata[1], '\0', 50);
    strcpy(mydata[0], "Hello");
    strcpy(mydata[1], "world");

    myfunc((my_char**)mydata);

    free(mydata[0]);
    free(mydata[1]);
    free(mydata);

    return 0;
}
  • I didn't down vote but the reason should be . you are changing the function argument type which is not right – Gopi Jan 13 '15 at 09:04
  • thanks gopi i will add that to the answer. – Ganesh Kamath - 'Code Frenzy' Jan 13 '15 at 09:04
  • It's better to [not cast malloc](http://stackoverflow.com/questions/605845/do-i-cast-the-result-of-malloc). Also it is good code design for functions that do not modify their pointed-to data to indicate this by the use of `const`, so it's not good advice to suggest removing that. (although admittedly there is no "nice" workaround) – M.M Jan 13 '15 at 09:13
0

You either remove const from void myfunc(const my_char** data) i.e void myfunc(my_char** data) or while type casting provide const i.e myfunc((const my_char**)mydata);

manish
  • 944
  • 2
  • 14
  • 27