Есть ли способ не использовать указатель в возвращаемом массиве? (предупреждение: передача аргумента 1 в'rangef 'делает указатель из целого числа без приведения.) - PullRequest
2 голосов
/ 04 июня 2019

Я пытался написать 2 подпрограммы, чтобы упорядочить массив в порядке возрастания и убывания, но это дало мне эту проблему с указателями и приведением.Есть ли способ обойти это?

Я попытался поместить все коды в одну большую программу, и она работает без нареканий.Я пытался привести указатели в подпрограммах, но это не сработало.

#include <stdio.h>
#include <math.h>
void arrangef (int a[]){
    int i, j, temp;
    for (i=0;;i++){
        for (j=1;;j++){
            if (a[i]>a[j]) {
                temp = a[i];
                a[i] = a[j];
                a[j] = temp;
            }
        }
    }
}

void arrangeb (int a[]){
    int i, j, temp;
    for (i=0;;i++){
        for (j=1;;j++){
            if (a[i]>a[j]) {}
                else {
                    temp = a[i];
                    a[i] = a[j];
                    a[j] = temp;
            }
        }
    }
}

int main () {
    int i, n;
    printf("What is the size of your array?\t"); scanf("%d",&n);
    int a[n];
    for (i=0;i<n;i++) {
        printf("\nInsert element #%d of array\t",i+1); scanf("%d",&a[i]);
    }
    printf("\n\n");
    for (i=0;i<n;i++) {
        printf("%d\t",a[i]);}

    printf("\n");

    arrangef(a[n]);
    for (i=0;i<n;i++) {
        printf("%d\t",a[i]);}
    printf("\n");

    arrangeb(a[n]);
    for (i=0;i<n;i++) {
        printf("%d\t",a[i]);
    }
}

Я ожидаю, что на выходе будет 3 списка чисел, оригинал, по возрастанию и по убыванию, но программа вылетает.

Ответы [ 2 ]

1 голос
/ 04 июня 2019
for (j=1;;j++){

Эта строка будет зациклена навсегда и будет иметь доступ к *(a+j) в a[i] = a[j] за пределами a.Аналогично с тремя другими циклами в вашем коде.Укажите верхнюю границу:

for (j = 1; j < n; j++) {

Вам также потребуется передать размер массива в функцию и вызвать его с помощью arrangef(a, n);.В данный момент вы передаете значение один после конца массива в функцию, которая ожидает указатель, а не значение.

0 голосов
/ 05 июня 2019

Чтобы передать массив в функцию, просто укажите имя массива 1 :

arrangef( a );
...
arrangeb( a );

a[n] задает один элемент массива, и он проходит после последнего элемента в массиве, поэтому вы передаете выражение неправильного типа (функции arrange* ожидают int *, вы передаете int) и он находится за пределами массива, поэтому значение неизвестно.

За исключением случаев, когда он является операндом операторов sizeof или унарных & или является строковым литералом, используемым для инициализации массива символов в объявлении, N-элемент выражение типа "N" массив T "преобразуется (" распадается ") в выражение типа" указатель на T ", а значением выражения является адрес первого элемента массива.

Итак, когда вы звоните

arrangef( a );

выражение a неявно преобразуется из "n -элемента массива int" в "указатель на int", а значением выражения является адрес a[0], так что arrangef фактически получает значение указателя.

В объявлении параметров функции T a[N] и T a[] "настроены" на T *a - все три объявляют a как указатель на T.

Поскольку все, что получает функция - это адрес первого элемента массива, вы также должны либо передать число элементов в качестве отдельного параметра, либо один элемент должен будет содержать значение Sentinel, которое отмечает конец данных. (например, терминатор 0 в строках). В вашем случае вам нужно передать размер отдельно:

void arrangef( int *a, size_t n ) // or int a[]
{
  for ( int i = 0; i < n; i++ ) // don't loop past the last element in the array
  {
    for ( int j = i; j < n; j++ ) 
    {
      int tmp = a[i];
      a[i] = a[j];
      a[j] = tmp;
    }
  }
}

arrangeb будет выглядеть одинаково, только с другим порядком.

for( i = 0; ; i++ ) будет зацикливаться "навсегда" - он будет зацикливаться за концом вашего массива и в конечном итоге в памяти, которой вы не владеете, что приведет к ошибке времени выполнения. i также в конечном итоге будет переполнен, и поведение при целочисленном переполнении со знаком не будет четко определено. По сути, эта петля взорвется .


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