Почему программа отображает предупреждение передача аргумента 1 из ‘circularswap’ делает указатель из целого числа без приведения?

#arrays #c #function #pointers

#массивы #c #функция #указатели

Вопрос:

Я работаю над этой проблемой:

 Given an array p[5], write a function to shift it circularly left by two positions. Thus, if p[0] = 15, p[1]= 30, p[2] = 28, p[3]= 19 and p[4] = 61 then after the shift p[0] = 28, p[1] = 19, p[2] = 61, p[3] = 15 and p[4] = 30. Call this function for a (4 x 5 ) matrix and get its rows left shifted.
 

Вот код, который я пробовал:

     #include <stdio.h>
    
#include <stdio.h>
void circularswap(int arr[][5],int n,int m){ int arr1[n][m],i,j;
    for (i=0;i<n;i  ){
        for (j=0;j<m;j  ){
            arr1[i][j]=*(*(arr i) j);
        }
    }
    for (i=0;i<m;i  ){
        *(*(arr i) 0)=arr1[i][2];
        *(*(arr i) 1)=arr1[i][3];
        *(*(arr i) 2)=arr1[i][4];
        *(*(arr i) 3)=arr1[i][0];
        *(*(arr i) 4)=arr1[i][1];
    }
        for (i=0;i<4;i  ){
        for (j=0;j<5;j  ){
            printf ("%d",arr[i][j]);
        }
        printf ("n");
    }
}
int main(){ int i,j;
    int arr[4][5]={(15,30,28,19,61),(15,30,28,19,61),(15,30,28,19,61),(15,30,28,19,61)};
    circularswap((arr,4,5));
    return 0;
}
 

К сожалению, это показывает предупреждения. Может кто-нибудь, пожалуйста, рассказать, почему появляются предупреждения и как их удалить?

Комментарии:

1. «К сожалению, это показывает предупреждения» — как вы думаете, что означают эти предупреждения? И этот код должен выдавать намного больше предупреждений, чем тот, который вы упомянули.

2. Пожалуйста, посмотрите отредактированный код всем

3. Мои извинения @WhozCraig, не могли бы вы, пожалуйста, исправить код, поскольку я новичок в программировании?

4.Пожалуйста, посмотрите стек предупреждений / ошибок здесь.

5. *(*(arr i) j) пожалуйста, отучитесь от этого. Просто всегда пишите arr[i][j] , спасибо!

Ответ №1:

При вызове функции у вас должно быть много круглых скобок.

Выражение (arr,4,5) использует оператор запятой и будет оценивать все подвыражения в списке, но возвращает только 5 .

Т.е. Ваш вызов действительно такой же, как circularswap(5) , что неверно несколькими способами.

Чтобы решить вашу проблему, опустите внутренние круглые скобки:

 circularswap(arr,4,5);
 

У вас аналогичная проблема при инициализации вашего массива: вы используете круглые скобки () вместо фигурных скобок {} .

Таким образом, определение массива действительно равно:

 int arr[4][5]={ { 61 }, { 61 }, { 61 }, { 61 } };
 

[Обратите внимание, как я использую фигурные скобки в примере выше]


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

Это особенно важно при использовании массивов массивов, как вы, где, например *(*(arr i) 0) , можно заменить на arr[i][0] .

Комментарии:

1. Теперь это приводит к ошибке сегментации

2. Любые другие изменения, которые требуются?

Ответ №2:

Вы объявили двумерный массив

  int arr[4][5]
 

Таким образом, элементы массива, в свою очередь, являются одномерными массивами. Вы можете инициализировать одномерный массив списком инициализаторов или строковым литералом, если тип элемента массива — char .

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

 (15,30,28,19,61)
 

Значение выражения — это значение последнего операнда, которое есть 61 . На самом деле ваша инициализация выглядит так

 int arr[4][5]=
{
    [0] = 61,
    [1] = 61,
    [2] = 61,
    [3] = 61
};
 

это под капотом выглядит, например

 a[0] = 61;
 

То есть вы пытаетесь присвоить значение 61 массиву типа int[5] .

Вам нужно заключить списки в фигурные скобки, например

 int arr[4][5] =
{
    { 15, 30, 28, 19, 61 },
    { 15, 30, 28, 19, 61 },
    { 15, 30, 28, 19, 61 },
    { 15, 30, 28, 19, 61 }
};
 

Также в присваивании написано, что вам нужно написать функцию, которая сдвигает элемент одномерного массива влево. Но в вашей программе такой функции нет.

Кроме того, в вашей функции circularswap есть ошибки. Например, в этом цикле

 for (i=0;i<m;i  ){
    *(*(arr i) 0)=arr1[i][2];
    *(*(arr i) 1)=arr1[i][3];
    *(*(arr i) 2)=arr1[i][4];
    *(*(arr i) 3)=arr1[i][0];
    *(*(arr i) 4)=arr1[i][1];
}
 

вместо используется переменная m n и магические числа, подобные 4 . Таким образом, использование переменной m вместо переменной n и использование магического числа 4 вместо использования переменной m во внутреннем цикле делает ваш цикл бессмысленным.

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

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

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

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

void circular_shift_left( int a[], size_t n, size_t pos )
{
    if ( n != 0 )
    {
        pos = pos % n;
    
        if ( pos != 0 )
        {
            for ( size_t i = 0; i < pos; i   )
            {
                int tmp = a[0];
                memmove( a, a   1, ( n - 1 ) * sizeof( *a ) );
                a[n-1] = tmp;
            }
        }           
    }
}

int main(void) 
{
    enum { M = 4, N = 5 };
    int a[M][N] =
    {
        { 15, 30, 28, 19, 61 },
        { 15, 30, 28, 19, 61 },
        { 15, 30, 28, 19, 61 },
        { 15, 30, 28, 19, 61 }
    };
    
    for ( size_t i = 0; i < M; i   )
    {
        for ( size_t j = 0; j < N; j   )
        {
            printf( "%d ", a[i][j] );
        }
        putchar( 'n' );
    }
    
    putchar( 'n' );
    
    for ( size_t i = 0; i < M; i   )
    {
        circular_shift_left( a[i], N, 2 );
    }
    
    for ( size_t i = 0; i < M; i   )
    {
        for ( size_t j = 0; j < N; j   )
        {
            printf( "%d ", a[i][j] );
        }
        putchar( 'n' );
    }
    
    putchar( 'n' );
    
    
    return 0;
}
 

Вывод программы

 15 30 28 19 61 
15 30 28 19 61 
15 30 28 19 61 
15 30 28 19 61 

28 19 61 15 30 
28 19 61 15 30 
28 19 61 15 30 
28 19 61 15 30 
 

Комментарии:

1. Не могли бы вы рассказать, почему мой цикл не имеет смысла?

2. Это код, о котором я говорю, а не тот, который был опубликован в исходном вопросе

3. @GirGr Для начала количество строк задается переменной n, а не переменной m. Во-вторых, вы используете магическое число 4 вместо использования цикла с переменной m.