C | указатель на указатель (или указатель на целочисленный массив), несогласованные уровни косвенности - PullRequest
0 голосов
/ 09 мая 2020

** РЕДАКТИРОВАТЬ: Я изменил идентификаторы, когда скопировал код из своего проекта, поэтому я мог пропустить некоторые из них. Дайте мне знать, если вы что-то нашли.

* EDIT: добавлено #define MAX_COL 5; для ясности.

Мне нужна помощь, чтобы разобраться в этой конкретной проблеме.

Допустим, у меня есть 2-мерный массив с инициализированными значениями. Меня просят найти:

  1. самую длинную последовательность целых чисел в массиве и
  2. адрес конкретного значения в начале этой последовательности.

Для этого я использую функцию, которая принимает:

  • массив,
  • целые числа, представляющие строку и столбец,
  • указатель на адрес самой длинной последовательности (инициализируется адресом первого элемента массива),
  • указатель на целое число для хранения длины последовательности.
max_seq(signed int arr[][5], int row, int col, signed int* ptr, int* seq_len);

Ниже это код:

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

#define MAX_COL 5;

int** max_seq(signed int arr[][5], int row, int col, signed int* ptr, int* seq_len);

int main(void)
{
    signed int arr[4][5] = { -5, 6, 0, 2, 2,
                              2, 2, 2, 9, 3,
                              3, 3, 2, 1, -8,
                              7, -2, 6, 0, 4 };

    signed int *address_seq = &(**arr);
    int seq_length = 0;
    address_seq = max_seq(arr, 4, 5, address_seq, &seq_length);
    return 0;
}

signed int** max_seq(signed int arr[][5], int row, int col, signed int* ptr, int* seq_len)
{
    int i = 0, j = 0,                   /* sentinels */
        temp_r = 0, temp_c = 0,
        seq = 0, new_seq = 0;

    int temp_val = (**arr);

    /* assign the address of the 2dim array to the pointer ptr */
    ptr = &(**arr);

    /* within the ith row */
    for (i = 0; i < row; ++i)
    {
        /* within the jth col */
        for (j = 0; j < col; ++j)
        {
            /* if the new_seq counter exceeds the (old) seq counter, then retains the new seq counter,
               also trace back the row and col values of the value at the start of that sequence */
            if (new_seq > seq)
            {
                seq = new_seq;
                int temp_seq = seq - 1;
                temp_r = i;
                temp_c = j;
                while (temp_seq > 0)
                {
                    --temp_c;
                    --temp_seq;
                    if (temp_c == 0 && temp_seq > 0)
                    {
                        --temp_r;
                        temp_c = MAX_COL;
                        --temp_c;
                        --temp_seq;
                    }
                }
            }

            if (*(*(arr + i) + j) == *(*(arr + i) + j + 1))
            {
                temp_val = *(*(arr + i) + j);
                ++new_seq;
            }
            else if (*(*(arr + i) + j) != *(*(arr + i) + j + 1)) {
                temp_val = *(*(arr + i) + j);
                new_seq = 1;
                continue;
            }
        }
    }

    *seq_len = seq;
    ptr = &(*(*(arr + temp_r) + temp_c));
    return ptr;
}

Особая проблема, которую я хочу понять, заключается в том, что когда я запускаю это в Visual Studio 19, я получаю предупреждение:

/* for the function call in main */
main.c(89,87): warning C4047: '=': 'int *' differs in levels of indirection from 'int **'

/* for the returned pointer value at the end of the function max_seq() */
main.c(146,12): warning C4047: 'return': 'int **' differs in levels of indirection from 'int *'

Несмотря на предупреждения, я по-прежнему получил то, что хотел, то есть адрес значения в начале самой длинной последовательности. Однако меня по-прежнему беспокоит, что указанная переменная, которую я объявил в main (), не совсем указатель на указатель.

Если я не ошибаюсь, имя любого массива вырождается в указатель при передаче в функцию. Следовательно, двумерный массив должен иметь 2 уровня косвенности. Однако, когда я изменил

signed int *address_seq = &(**arr); на signed int **address_seq = arr;

, компилятор VS19 сгенерировал дополнительные предупреждения, а возвращенный ptr вообще не указывает на правильный блок данных.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...