Как перебрать и скопировать двойной указатель в C - PullRequest
0 голосов
/ 22 марта 2019

Я создал двумерный целочисленный массив в C, инициализировал его значениями, а затем привел к int** (я должен сделать это, потому что это для домашней работы).
Мне удалось перебрать его и установить все значения на 0. Однако, когда я перебираю его снова и печатаю его значения, выходные данные не все нули.

Вот минимальный рабочий пример:

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

#define ROWS    3
#define COLS    2

int main(void)
{
    /* Create array and convert to double pointer */
    int c[ROWS][COLS] = {{1,2},{3,5},{8,13}};
    int **ptr = (int **)c;

    /* Loop through entire array and print then double each value. */
    int *temp[ROWS];
    for(int i = 0; i<ROWS; i++){
        temp[i] = (int*)(ptr+i);
        for(int j = 0; j<COLS; j++){
            printf("Before setting: %i\n", temp[i][j]);
            temp[i][j] = temp[i][j]*2;
        }
    }

    /* Copy temp back into ptr */
    memcpy(ptr, temp, sizeof(ptr));

    /* Loop through array and print values */
    int *temp2[ROWS];
    for(int i = 0; i<ROWS; i++){
        temp2[i] = (int*)(ptr+i);
        for(int j = 0; j<COLS; j++){
            printf("After setting: %i\n", temp2[i][j]);
        }
    }

}

Проблема в том, что результаты не соответствуют ожиданиям. Однажды я запустил его, это был вывод:

Перед настройкой: 1
Перед установкой: 2
Перед установкой: 3
Перед установкой: 5
Перед установкой: 8
Перед установкой: 13
После настройки: -1193330832
После настройки: 32764
После настройки: 6
После настройки: 10
После настройки: 16
После настройки: 26

Значение 32764 одинаково при каждом запуске программы, но значение -1193330832 меняется каждый раз (я предполагаю, что это адрес памяти массива).

Результат, который я ожидал:

Перед настройкой: 1
Перед установкой: 2
Перед установкой: 3
Перед установкой: 5
Перед установкой: 8
Перед установкой: 13
После настройки: 1
После настройки: 4
После настройки: 6
После настройки: 10
После настройки: 16
После настройки: 26
потому что значения в первом цикле были удвоены.

Что я сделал не так? Почему значения меняются и как мне на самом деле это исправить?

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

1 Ответ

2 голосов
/ 22 марта 2019

int **ptr = (int **)c; не является допустимым преобразованием указателя, так как вы не можете использовать указатель-указатель для указания на 2D-массив.Потому что это не имеет ничего общего с 2D-массивами.

Вместо этого вы можете использовать указатель на 2D-массив, int (*)[ROWS][COLS];.Однако наиболее удобно использовать указатель на одномерный массив и указывать его на первый элемент двумерного массива:

int (*ptr)[COLS] = &c[0];

...

ptr[i][j] = ...;

Фиксированный пример:

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

#define ROWS    3
#define COLS    2

int main(void)
{
    /* Create array and convert to double pointer */
    int c[ROWS][COLS] = {{1,2},{3,5},{8,13}};
    int (*ptr)[COLS] = &c[0];

    /* Loop through entire array and print then double each value. */
    for(int i = 0; i<ROWS; i++){
        for(int j = 0; j<COLS; j++){
            printf("Before setting: %i\n", ptr[i][j]);
            ptr[i][j] = ptr[i][j]*2;
        }
    }

    /* Loop through array and print values */
    for(int i = 0; i<ROWS; i++){
        for(int j = 0; j<COLS; j++){
            printf("After setting: %i\n", ptr[i][j]);
        }
    }
}

(Вопрос стиля, но ваш порядок ROWS и COLS немного странный, чаще всего int[COLS][ROWS], чем for(i=0; i<COLS; i++))

...