0

Tried looking at past questions dealing with this issue but all of those seem to relate to C++ not C. And I have to write the program in C. So I have this portion of code that is suppose to do the following: Modifies an existing kstring, pointed to by strp, to be at least nbytes bytes long... And so on. But I have the code for the function but I keep getting an error: invalid conversion from ‘void*’ to ‘char*’.

typedef struct
    {
        char *data;
        size_t length;
    } kstring; 

Function:

void kstrextend(kstring *strp, size_t nbytes)
{
    char *nwData;
    int lnth=strp->length;
    if(lnth < nbytes)
    {
        // new array allocate with large size and copy data to new array
        nwData = realloc(strp->data, nbytes);
        // call abort in case of error
        if(nwData == NULL)
        {
            abort();
        }
        //Making strp->data point to the new array
        strp->data = nwData;
        //Setting strp->length to the new size.
        strp->length = nbytes;
        // filled with '\0' in remaining space of new array
        for (int lp = lnth; lp < nbytes; lp++)
        {
            strp->data[lp] = '\0';
        }
    }
}

Portion of main where function is called:

name.data = (char*)calloc(sizeof("Hello"), 1);
strcpy(input, "Hello");
name.length=5;
kstrextend(&name,40);
printf("%s %d",name.data,name.length);
  • There seem to be some inconsistencies between `length` and the number of bytes actually allocated. For instance, `sizeof("Hello")` is 6, since it includes the trailing null byte, but you're using 5 for `length`, and the code seems to treat `length` as the number of allocated bytes, not one less. – Tom Karzes Feb 05 '19 at 04:43
  • 3
    Are you sure you compile it as C? – user58697 Feb 05 '19 at 04:56
  • What line is the error rendering on? I'm assuming it's the realloc line? – Byte Lab Feb 05 '19 at 04:57
  • Also, what is a kstring? Could you please include the typedef? – Byte Lab Feb 05 '19 at 04:59
  • you are correct that is the line the error appears on. –  Feb 05 '19 at 05:10
  • @TomNorth thank you for clarifying, and welcome to stack overflow. In the future, please try to be more specific in your questions. For example, you should provide the line number where you are seeing the error, and probably the whole error message as well. – Byte Lab Feb 05 '19 at 05:22
  • 1
    @TomNorth: You must be compiling this as C++, not C. C allows direct assignment between `void *` and other pointer types, whereas C++ does not. You should not get this error from a C compiler. How are you compiling this code? Please show the *exact* command you are using. – John Bode Feb 05 '19 at 05:39
  • @JohnBode I am running it on a unix virtual machine through Putty and when I created my source file I gave it the extension .cc. And when I compile the code I type exactly "g++ -Wall -O -g kstring.cc" And I get the error: kstring.cc:122:19: error: invalid conversion from ‘void*’ to ‘char*’ [-fpermissive] nwData = realloc(strp->data, nbytes);. –  Feb 05 '19 at 05:53
  • 1
    @TomNorth FYI Putty is just an ssh terminal client - it doesn't have anything to do with what compilation you're using. As John Bode mentioned, in the future you should include the command used to compile that you're seeing an issue with. Also, if the file is a C file it should have the .c extension rather than .cc, and as I mentioned in the answer, you should use gcc instead of g++. – Byte Lab Feb 05 '19 at 06:08
  • Make use if the macro definition [`__cplusplus`](https://port70.net/~nsz/c/c11/n1570.html#6.10.8): `#ifdef __cplusplus` / `#error wrong or misconfigured compiler` / `#endif` – pmg Feb 05 '19 at 08:47
  • OT: regarding: `abort();` this would be much better written as: `perror( "realloc failed" ); exit( EXIT_FAILURE );` The `perror()` will output to `stderr`, your error message AND the text reason the system thinks the call to `realloc()` failed. Then the call to `exit()` results in a clean exit from the program. Note: `exit()` and `EXIT_FAILURE` are both found in the header file: `stdlib.h` – user3629249 Feb 06 '19 at 04:03
  • the compile statement should look like: `gcc -c -Wall -Wextra -Wconversion -pedantic -std=C99 kstring.c -o kstring.o` then when all the compile problems are fixed, link it with: `gcc kstring.o -o kstring` of course if you want debug info included, then both statements should also have `-ggdb` (for the gdb debugger) – user3629249 Feb 06 '19 at 04:07

1 Answers1

0

The issue is where you're calling realloc:

// new array allocate with large size and copy data to new array
nwData = realloc(strp->data, nbytes);

nwData is a char * type, but realloc returns a void *. See https://en.cppreference.com/w/c/memory/realloc for more information. You should instead cast to a char * as you do when setting name.data:

nwData = (char *)realloc(strp->data, nbytes);

I'm assuming you're compiling with g++? If you're writing a C program you should compile with gcc, which will compile according to C language semantics rather than C++.

As a side note, I see that you're manually setting the remainder of the array to \0 in a loop:

// filled with '\0' in remaining space of new array
for (int lp = lnth; lp < nbytes; lp++)
{
    strp->data[lp] = '\0';
}

It is typically much faster (and better code style) to use the builtin memcpy function rather than using a loop:

memset(strp->data + lnth, nbytes - lnth, '\0');
Byte Lab
  • 1,576
  • 2
  • 17
  • 42
  • Could whoever downvoted this answer please explain why? – Byte Lab Feb 05 '19 at 05:29
  • I didn't downvote. But I can see why someone might, especially since you also stress the difference between C and C++ semantics. Read https://stackoverflow.com/questions/605845/do-i-cast-the-result-of-malloc – StoryTeller - Unslander Monica Feb 05 '19 at 06:26
  • I'm not sure what point you're trying to make. C and C++ are different languages with different semantics. That is a separate argument from whether casting the `void*` result of malloc to another pointer type is justified. His question was why his program couldn't compile, and it was because he was compiling C++ instead of C. – Byte Lab Feb 05 '19 at 06:56
  • 2
    From the question: "And I have to write the program in C" - Your suggestion to actually use a C compiler is good. The suggestion to add a cast is C++-compiler appeasing, unidiomatic and totally beside the point. I.e. not good. – StoryTeller - Unslander Monica Feb 05 '19 at 06:59
  • Oh, and you seem to have confused `memcpy` with `memset` – StoryTeller - Unslander Monica Feb 05 '19 at 07:01
  • @StoryTeller oops, right you are about `memset`. That was silly of me. Regarding suggesting the cast - that's a completely subjective and pedantic argument and you know it. I'll add as well that your tone is condescending. I.e. not good. – Byte Lab Feb 05 '19 at 07:07
  • It's not subjective, there are good reasons on that post. And writing idiomatic code is damn important. Seems you asked about the downvote just to pick a fight. Thanks for making that clear, I know not to bother with you anymore. – StoryTeller - Unslander Monica Feb 05 '19 at 07:08
  • Being idiomatic is important, but the value of casting here is subjective. You could argue that it makes the code more readable to see what type you're allocating. It also helps the OP to understand types, which he clearly did not given that he didn't understand the error message about type conversion. Also, respectfully, you were the one who took the first condescending tone. Don't tell someone that their words are "unidiomatic and totally beside the point" and then get indignant when they call you out on it. – Byte Lab Feb 05 '19 at 07:14