0

I tried to program a merge sort function using only static arrays and of course I have an incomprehensible error.

So the first question is that when I compile my program it gives me a multiple definition error on line 9 of that code:

#include <cmath>
#include "include\sort.h"


/*
Theses fonctions accept only arrays of unsigned short int with a length in unsigned int
*/

unsigned short int* sortByFusion(unsigned short int arr[]) { // HERE !!!!!!!!
    const unsigned int arrSize = sizeof(arr)/sizeof(unsigned short int);
    if (arrSize <= 1) {return arr;}

    /*
    Declarations and initializations of the two half array
    */
    const unsigned int arrLeftSize = static_cast<unsigned int>(floor(arrSize/2));
    const unsigned int arrRightSize = static_cast<unsigned int>(arrSize - arrLeftSize);

    unsigned short int arrLeft[arrLeftSize];
    unsigned short int arrRight[arrRightSize];

    for (unsigned int i = 0; i < arrLeftSize; i ++)
        arrLeft[i] = arr[i];
    for (unsigned int i = 0; i < arrRightSize; i ++)
        arrRight[i] = arr[i + arrLeftSize];

    /*
    Sort the two arrays
    */
    for (unsigned int i = 0; i < arrLeftSize; i ++)
        arrLeft[i] = *(sortByFusion(arrLeft) + i);
    for (unsigned int i = 0; i < arrRightSize; i ++)
        arrRight[i] = *(sortByFusion(arrRight) + i);

    /*
    And fusion them
    */
    unsigned int i(0), j(0);
    for (unsigned int k = 0; k < arrSize; k ++) {
        if (i >= arrLeftSize)           {arr[k] = arrRight[j]; j ++;} //That line
        else if (j >= arrRightSize)     {arr[k] = arrLeft[i]; i ++;}  //And that line are here to avoid segmentation fault
        else {
            if (arrLeft[i] <= arrRight[j]) {arr[k] = arrLeft[i]; i ++;}
            else {arr[k] = arrRight[j]; j ++;}
        }
    }
return arr;
}

What did I do wrong? I tried to put some ifndef define endif but it did nothing more. It seems that everybody has a problem with multiple definition always a bit different on this forum.

Secondly, I used some static_cast but why does floor return a double when we pass a double as argument? Logically, it should give us an integer (the floor of a number is always an integer ...)?

For the compiler, it is GNU GCC, but I don't know how to find its version. And I work with Code::Blocks.

And this is the header file :

#ifndef SORT_H_INCLUDED
#define SORT_H_INCLUDED

unsigned short int* sortByFusion(unsigned short int arr[]);

#endif // SORT_H_INCLUDED
Bobog
  • 163
  • 5
  • Could you provide the following? 1). The compile error message you got for line#9. 2). The platform, C++ compiler and the compiler's version you are working with. 3). The content of sort.h if it's not a standard header file. – yaobin Jul 05 '15 at 19:44
  • 1). You can enter "gcc --version" in a terminal to see its version. 2). Are you working on a Linux system? Or Mac? Or Windows? 3). I compiled your code on my Ubuntu virtual machine, using "gcc (Ubuntu 4.8.2-19ubuntu1) 4.8.2", I saw a "No such file or directory" file on the line of "#include "include\sort.h" because Ubuntu uses '/' to separate paths. After I changed it from '\' to '/', I don't get any compile errors about multiple-definition. – yaobin Jul 06 '15 at 14:22

1 Answers1

1
 const unsigned int arrSize = sizeof(arr)/sizeof(unsigned short int);

This line is not working as expected, because c++ doesn't keep any information about the length of an array with a runtime array - which is really just a pointer to the array, thus sizeof(arr) returns sizeof(unsigned short int*) which is the size of a pointer.


As why there is an error in line 9, I can't help you without seeing the header sort.h.


//static_cast<unsigned int>(floor(arrSize/2)); // Wrong
arrSize/2; // Right, C++ does floor integer divisions.

unsigned short int arrLeft[arrLeftSize];
unsigned short int arrRight[arrRightSize];

These two lines aren't valid C++ because the length of the declared arrays can not be determined at compile time.

WorldSEnder
  • 4,875
  • 2
  • 28
  • 64
  • Ok, but can i do something to have the size of an array without passing it as an argument ? It is more comfortable for the user ... – Bobog Jul 05 '15 at 19:21
  • @Bobog If you're passing in a pointer, no. If you're passing an array, you can let the compiler figure out its size through the template mechanism. When doing this, passing a pointer will not compile: `template void foo(int (&array)[N]) {}` – JorenHeit Jul 05 '15 at 19:25
  • @Bobog, see here http://stackoverflow.com/questions/2867783/c-arrays-as-function-arguments – WorldSEnder Jul 05 '15 at 19:27
  • @Bobog Also consider `std::array` which is a wrapper for a static array of fixed size. You also need templates to deal with it (unless the size is known), but the syntax is a bit more elegant. – JorenHeit Jul 05 '15 at 19:33
  • @WorldSEnder: Just want to confirm my understanding of your reply. You said "c++ doesn't keep any information about the length of an array with the array". I would say C++ does keep information of array length as long as it is a real array. In this instance, although 'arr' is declared in the form of an array, C/C++ converts it to a pointer. As a result, now 'arr' is no longer an array and thus it loses the array length information. – yaobin Jul 06 '15 at 14:26
  • @yaobin, That's definitly how you should think of it. The standard phrases it differently and I would say that the length of a compile-time array is kept associated to but not with the array, but I think you understand it correctly – WorldSEnder Jul 06 '15 at 14:30