Назначение разыменованного указателя C ++

0

Я пытаюсь изучить C++, сначала просматривая детали низкого уровня, прежде чем начинать использовать абстракции, такие как std :: copy или memcpy. В настоящее время я застрял в попытке выяснить, почему этот код никогда не присваивается переменной "sortedArray", когда вы смотрите с отладчиком, я разыскиваю значение из "данных" правильно, но никогда не назначается "sortedArray". Я вижу значение, такое как "-842150451" вместо "14" для первого значения. Не могли бы вы помочь мне выяснить, что я делаю неправильно? И любые другие проблемы, которые могут быть, что я не вижу, или совет будет очень признателен!

void swap(int* bigger, int* smaller){
    *bigger += *smaller;
    *smaller = *bigger - *smaller;
    *bigger = *bigger - *smaller;
}

int* bubbleSort(int *data, int size){
    bool swapped = true;
    int *sortedArray = (int*)malloc(size*sizeof(int));
    for (int i = 0; i < size;i++){
        *(sortedArray++) = *(data++);
    }

    while (swapped){
        swapped = false;
        for (int i = 1; i <= size - 1; i++){
            if (sortedArray[i - 1] > sortedArray[i]){
                swap(&sortedArray[i - 1], &sortedArray[i]);
                swapped = true;
            }
        }
        size--;
    }
    return sortedArray;
}
  • 0
    Вот ваша проблема: *(sortedArray++) = *(data++);
  • 0
    Вот еще один: swap(&sortedArray[i - 1], &sortedArray[i]);
Показать ещё 10 комментариев
Теги:
pointers
visual-c++
dereference

4 ответа

7
Лучший ответ

*(sortedArray++) = *(data++); изменяет указатель, чтобы он больше не указывал на начало выделенной памяти. Итак, позже sortedArray[i] - это то, что происходит в памяти за массивом, и доступ к нему - неопределенное поведение.

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

int *sortedArray = (int*)malloc(size*sizeof(int));
int* s = sortedArray;
for (int i = 0; i < size;i++){
    *s++ = *data++;
}

Другой способ:

int *sortedArray = (int*)malloc(size*sizeof(int));
for (int i = 0; i < size;i++){
    sortedArray[i] = data[i];
}

Но лучшим способом было бы использовать стандартные контейнеры и алгоритмы, такие как vector и sort.

Вот демонстрация первого исправления в действии.

  • 0
    Спасибо за объяснение, теперь кажется вполне очевидным ... Я планирую вскоре посмотреть на контейнеры, спасибо :)
  • 0
    error: 'malloc' was not declared in this scope поэтому нужно добавить только одну строку #include <cstdlib>
Показать ещё 1 комментарий
2

+ Изменить

*(sortedArray++) = *(data++);

в

sortedArray[i] = data[i];

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

Обратите внимание, что ничего не получается, используя синтаксис *(x+y) вместо x[y], они эквивалентны, но последние легче читать.

В C++ вы не должны использовать malloc. Вместо этого используйте new int[size]. Для int нет никакой разницы, кроме снижения риска создания опечатки, однако для нетривиальных типов malloc не будет правильно их строить.

  • 0
    Спасибо за совет относительно нового [], я буду использовать его отныне.
1

Вы первый указатель sortedArray указывает на некоторую выделенную память.

Затем в первом цикле for вы увеличиваете указатель. не он больше не указывает на эту память.

Просто используйте временный указатель для копии памяти.

int* t = sortedArray ;

И теперь используйте t в вашем цикле for, который копирует данные.

Вместо временной переменной вы можете посчитать количество раз, когда вы sortedArray++ в цикле for.

Если вы посмотрите: for (int я = 0; я < size;i++) вы увидите, что контур взял точно size число итераций.

Просто вычтите размер из указателя после цикла, и вы вернетесь в выделенную память.

sortedArray -= size ;
  • 0
    Спасибо за ваш ответ, который не t make use of a auxiliary variable, I didn заметил эту деталь.
  • 0
    Вы действительно рекомендуете арифметику указателей? Такого рода ответ должен вынести OP (или любой новый программист)? Я сомневаюсь в этом.
Показать ещё 13 комментариев
1

Это совсем не C++. Вы можете написать общий код, который принимает итератор begin и end итератор, чтобы он работал с любым контейнером, который поддерживает такую семантику.

template<typename IT>
void bubble_sort(IT begin, IT end) {
    while (true) {
        bool swapped = false;
        for (IT i = begin; i != end-1; i = i+1) {
            if (*i > *(i+1)) {
                std::iter_swap(i, i+1);
                swapped = true;
            }
        }
        if (swapped == false) return;
    }
}

Live demo

Где std::iter_swap похож на std::swap но работает на итераторах. Вы можете видеть итераторы как пару указателей на начало и (конец) конца контейнера.

  • 0
    Можете ли вы получить еще более загадочный, это не поможет ОП.
  • 2
    @self. Я считаю его код гораздо более загадочным.
Показать ещё 5 комментариев

Ещё вопросы

Сообщество Overcoder
Наверх
Меню