Доступ к массиву через двойной указатель, теряя свое тело, чистый C

Когда я пытаюсь отсортировать содержимое массива, на которое я ссылаюсь через двойной указатель.

http://ideone.com/OapPh

линия 77

SortQuick(&(*data_resource)->data,
   &(*data_resource)->low,
   &(*data_resource)->length - 1);

Содержимое не было отсортировано, с помощью того же метода я очень хорошо печатаю значения этого массива с помощью функции ArrayPrint()

Этот код хорошо компилируется на компиляторе MS C++, про GCC не знаю. В коде или ошибках нет никаких предупреждений, компилятор MS не показывает его в стандартной конфигурации.

3 ответа

Это не сортировка, потому что &(*data_resource)->length - 1 оценивает &(*data_resource)->low,

&(*data_resource)->length это указатель на int, Когда вы вычитаете 1 из него, он указывает на int незадолго до того, и это случается &(*data_resource)->low потому что вы определили элементы структуры именно в этом порядке:

typedef struct Resource
{
        int low;
        int length;
        int *data;
} Resource;

Таким образом, ваш код сортировки получает 2 идентичных индекса для работы и по праву ничего не сортирует, так как нечего сортировать в подмассиве, состоящем только из одного элемента.

Вот немного измененная версия, которая работает:

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

typedef struct Resource
{
        int low;
        int length;
        int *data;
} Resource;

void Swap(int *first, int *second)
{
        int tmp = *first;
        *first = *second;
        *second = tmp;
}

void SortQuick(int **data, int *low, int *high)
{
        int i = *low,
                j = *high,
                x = (*data)[(*low + *high) / 2];

        do
        {
                while((*data)[i] < x) i++;
                while((*data)[j] > x) j--;

                if(i <= j)
                {
                        Swap(&(*data)[i], &(*data)[j]);
                        i++;
                        j--;
                }

        } while(i <= j);

        if(i < *high) SortQuick(data, &i, high);
        if(*low < j) SortQuick(data, low, &j);
}

void ArrayPrint(int **data, int *array_length)
{
        for(int i = 0; i < *array_length; i++)
        {
                printf("[%i]: %20i\r\n", i, (*data)[i]);
        }
}

void ArrayInit(int **data, int *array_length)
{
        (*data) = (int*)malloc(sizeof(int) * *array_length);

        for(int i = 0; i < *array_length; i++)
        {
                (*data)[i] = rand();
        }
}

int GlobalInit(Resource **data_resource)
{
        srand((unsigned int)rand());

        *data_resource = (Resource*)malloc(sizeof(Resource));
        (*data_resource)->low = 0;
        (*data_resource)->length = 10;//rand();

        ArrayInit(&(*data_resource)->data, &(*data_resource)->length);

        return (*data_resource)->length;
}

void BenchmarkTest(Resource **data_resource)
{
        ArrayPrint(&(*data_resource)->data, &(*data_resource)->length);
        (*data_resource)->length--;
        SortQuick(&(*data_resource)->data, &(*data_resource)->low, &(*data_resource)->length);
        (*data_resource)->length++;
        ArrayPrint(&(*data_resource)->data, &(*data_resource)->length);
}

int main(void)
{
        Resource *data_resource = NULL;

        GlobalInit(&data_resource);
        BenchmarkTest(&data_resource);

        return 0;
}

Выход ( идеально):

[0]:           1362961854
[1]:              8891098
[2]:            392263175
[3]:            158428306
[4]:           2074436122
[5]:             47170999
[6]:            431826012
[7]:           1599373168
[8]:           1769073836
[9]:           1043058022
[0]:              8891098
[1]:             47170999
[2]:            158428306
[3]:            392263175
[4]:            431826012
[5]:           1043058022
[6]:           1362961854
[7]:           1599373168
[8]:           1769073836
[9]:           2074436122

Все эти ссылки и разыменования указателей сводят вас с ума, и в большинстве случаев они не нужны, попробуйте это:

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

typedef struct Resource
{
    int low;
    int length;
    int *data;
} Resource;

void Swap(int *first, int *second)
{
    int tmp = *first;
    *first = *second;
    *second = tmp;
}

void SortQuick(int *data, int low, int high)
{
    int i = low,
        j = high,
        x = data[(low + high) / 2];

    do
    {
        while(data[i] < x) i++;
        while(data[j] > x) j--;

        if(i <= j)
        {
            Swap(&(data[i]), &(data[j]));
            i++;
            j--;
        }

    } while(i <= j);

    if(i < high) SortQuick(data, i, high);
    if(low < j) SortQuick(data, low, j);
}

void ArrayPrint(int *data, int array_length)
{
    for(int i = 0; i < array_length; i++)
    {
        printf("[%i]: %i\r\n", i, data[i]);
    }
}

void ArrayInit(Resource *data_resource)
{
    data_resource->data = (int*)malloc(sizeof(int) * data_resource->length);

    for(int i = 0; i < data_resource->length; i++)
    {
        data_resource->data[i] = rand();
    }
}

Resource* GlobalInit()
{
    Resource *data_resource;
    srand((unsigned int)rand());

    data_resource = (Resource*)malloc(sizeof(Resource));
    data_resource->low = 0;
    data_resource->length = rand();

    ArrayInit(data_resource);

    return data_resource;
}

void BenchmarkTest(Resource *data_resource)
{
    ArrayPrint(data_resource->data, data_resource->length);
    SortQuick(data_resource->data, data_resource->low, data_resource->length - 1);
    ArrayPrint(data_resource->data, data_resource->length);
}

int main(void)
{
    Resource *data_resource = NULL;

    data_resource = GlobalInit();
    BenchmarkTest(data_resource);

    return 0;
}

Эта часть не имеет смысла:

&(*data_resource)->length - 1);

Вы берете адрес length поле и вычитание 1. Удаление - 1 кажется, заставляет это работать.

Кроме того, вы злоупотребляете указателями. Например ArrayPrint может быть просто

void ArrayPrint(int *data, int array_length)
{
        for(int i = 0; i < array_length; i++)
        {
                printf("[%i]: %i\r\n", i, data[i]);
        }
}
Другие вопросы по тегам