1

I have the following function that I've used in C programs plenty of times before:

/**
    Splits a given string into an array of strings using given delimiters.
    @param input_string
        The string to be split.
    @param delimiters
        The characters that will be used as delimiters.
    @return
        The components of the split string followed by @c NULL , or only
        @c NULL if sufficient memory fails to allocate for the returned array.
 */
char **split(char *input_string, const char *delimiters) {
    char **components = NULL;
    int components_count = 0;

    char *component = strtok(input_string, delimiters);
    while (component) {
        ++components_count;

        // |components| is reallocated to accomodate |component|. If
        // |realloc()| fails, |NULL| is returned.
        components = realloc(components, sizeof(char *) * components_count);
        if (!components) return NULL;
        components[components_count - 1] = component;

        component = strtok(NULL, delimiters);
    }

    // |components| is reallocated once more to accomodate an additional
    // |NULL|. Only |NULL| is returned in |realloc()| fails.
    components = realloc(components, sizeof(char *) * (components_count + 1));
    if (!components) {
        return NULL;
    }
    components[components_count] = NULL;

    return components;
}

I just recently added the function to a C++ project to use in a situation where I was required to deal with C-strings. When compiling, I now get this errors:

error: assigning to 'char **' from incompatible type 'void *'
        components = realloc(components, sizeof(char *) * components_count);

error: assigning to 'char **' from incompatible type 'void *'
    components = realloc(components, sizeof(char *) * (components_count + 1));

I'm completely lost as to what to do about these errors. As far as I'm concerned, what I'm doing should be legal in C++ since it's always worked fine in C. Any insight?

If it helps, I'm am using clang++ on OS X as a compiler, but this code is also expected to compile with g++ on Ubuntu.

Jared
  • 4,240
  • 4
  • 22
  • 27
  • Comments are not for extended discussion; this conversation has been [moved to chat](http://chat.stackoverflow.com/rooms/74597/discussion-on-question-by-jared-why-is-realloc-mysteriously-behaving-different). – George Stocker Apr 07 '15 at 01:59

3 Answers3

4

Not everything has to be the same on C and C++; malloc and realloc is a usual example of this.

  1. You don't have to explicitly cast the void pointer in C, it will be done automatically, as in your example.
  2. You definitely have to explicitly cast that pointer in C++, both in malloc and realloc functions.

There is a great deal of differences between those two languages, don't take everything for granted.

In this link some differences on basic stuff between C and C++ are stated here; it might be worth reading it.

http://www.cprogramming.com/tutorial/c-vs-c++.html

Or this (suggested by a comment):

http://david.tribble.com/text/cdiffs.htm

codingEnthusiast
  • 3,800
  • 2
  • 25
  • 37
  • Glad this had such a simple solution. Added `(char **)` before each `realloc()` call, and everything works well. Thanks for the useful link. – Jared Apr 05 '15 at 00:13
  • That website isn't accurate at all! The last point it makes is flat-out wrong. All three C standards contain something along the lines of this quote: ["reaching the } that terminates the main function returns a value of 0."](http://www.iso-9899.info/n1570.html#5.1.2.2.3) indeed it is true that C and C++ are completely different languages, though they commonly have compatible ABIs (as does assembly, D, etc). If you're looking for a valid link to support that statement, [this one goes into much more detail, however outdated it is](http://david.tribble.com/text/cdiffs.htm). – autistic Apr 05 '15 at 02:14
  • It might also be worth reading [this answer](http://stackoverflow.com/a/605858/1989425)... – autistic Apr 05 '15 at 02:16
3

C++ doesn't allow void* pointers to be implicitly converted to other pointers. Also, C and C++ are quite different languages, so not all of C will work on C++ because it is a different language.

Explicitly casting the realloc() result should work however.

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
Alex Díaz
  • 2,303
  • 15
  • 24
1

Isolate your C code from your C++ code. They are different languages. Treating C as though it can run in C++ makes about as much sense as treating Traditional Chinese as though it can run in Simplified Chinese. If you're writing a program to compile with a C++ compiler, it should probably look very different to the program you write to compile with a C compiler.

Nonetheless, there are times when you might want to link some C code (or assembly code, or whatever) to your C++ code. The process is probably similar for every language, providing the compilers you're using have a compatible ABI. The example I'll use is gcc and g++.

Compile your C code using your C compiler (eg. gcc), but without the linking process (eg. using the -c flag). For example: gcc -c split.c

Compile your C++ code using your C++ compiler, and link the object code generated by your C compiler into it. For example: g++ main.cpp split.o

autistic
  • 1
  • 3
  • 35
  • 80