Программа не находит максимальное число в массиве, как предполагалось

Эта программа должна возвращать наибольшее число в массиве «массив». Но он возвращает только наибольшее число между первым и вторым числами. Почему?

#include <stdio.h>
#include <stdlib.h>
int HighestNumber(int* array)
{
    int highest = INT_MIN;
    for(size_t x = 0; x < sizeof(array) / sizeof(array[0]); x++)
        if (array[x] > highest)
            highest = array[x];
    return highest;
}
int main()
{
    int *array = (int*)malloc(4*sizeof(int));
    array[0] = 66;
    array[1] = 552;
    array[2] = -17;
    array[3] = 1000;
    printf("%d", HighestNumber(array));
    return 0;
}

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

Aconcagua 16.02.2023 14:11

Отвечает ли это на ваш вопрос? Как узнать размер массива (по указателю, указывающему на первый элемент массива)?

mch 16.02.2023 14:56

Возможные другие дубликаты: stackoverflow.com/questions/5493281/c-sizeof-a-passed-array stackoverflow.com/questions/25680014/…

mch 16.02.2023 14:56
T - 1Bits: Генерация последовательного массива
T - 1Bits: Генерация последовательного массива
По мере того, как мы пишем все больше кода, мы привыкаем к определенным способам действий. То тут, то там мы находим код, который заставляет нас...
Что такое деструктуризация массива в JavaScript?
Что такое деструктуризация массива в JavaScript?
Деструктуризация позволяет распаковывать значения из массивов и добавлять их в отдельные переменные.
1
3
66
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

В тот момент, когда вы передаете array функции HighestNumber(), вы теряете информацию о размере массива. Это называется распадом массива к указателю.

На функцию HighestNumber() она видит только указатель, ничего не зная о массиве.

Рассмотрите возможность передачи размера массива в качестве второго параметра функции, например

int HighestNumber(int* array, size_t num) {
    // ..
}

Массив распадается на указатель в параметрах функции. sizeof на указателе возвращает размер указателя, а не указанный на данные.

Возможное решение:

Передайте размер массива в качестве второго аргумента.

int HighestNumber(int* array, size_t size) {
    //...
}

Sentinel на самом деле проблематичен, поскольку он уменьшает диапазон допустимых значений в массиве (если он все еще используется, алгоритм прерывается преждевременно), поэтому в данном случае менее рекомендуется, если иное не гарантирует, что он не будет использоваться. Если использование дозорного INT_MIN является хорошим выбором, так как он укажет, что минимум не найден (массив размера 0) без необходимости каких-либо изменений, и, кроме того, он делает (в дополнении до двух) положительный и отрицательный диапазон одинакового размера;)

Aconcagua 16.02.2023 14:37

Параметр функции array имеет тип указателя int *.

int HighestNumber(int* array);

Таким образом, выражение sizeof(array) / sizeof(array[0]) эквивалентно выражению sizeof( int * ) / sizeof( int ) и обычно дает значение 2 или 1 в зависимости от размеров указателей и целых чисел.

Вам нужно явно передать количество элементов в массиве. Например,

int HighestNumber(int* array, size_t n );

Обратите внимание, что пользователь может передать 0 для параметра n. В этом случае при вашем подходе к определению функции функция может вернуть недопустимое значение.

Функция должна быть объявлена ​​и определена следующим образом. Поскольку функция не изменяет обрабатываемый массив, то первый параметр должен иметь квалификатор const.

size_t HighestNumber( const int *array, size_t n )
{
    size_t highest = 0;

    for ( size_t i = 1; i < n; i++ )
    {
        if ( array[highest] < array[i] )
        {
            highest = i;
        }
    }

    return highest;
}

И функция называется как

printf("%d\n",  array[HighestNumber(array, 4 )] );

Или

size_t highest = HighestNumber(array, 4 );

printf( "The largest number is %d at the position %zu\n",
        array[highest], highest);

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

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

free( array );
size_t highestNumber(...) — действительно хорошее дополнение, хотя я бы подумал о возврате указателя, но более высокого уровня (при этом NULL, возможно, указывает на отсутствие максимума для n == 0), поэтому я бы тоже упомянул.
Aconcagua 16.02.2023 14:40
Ответ принят как подходящий

Трюк sizeof не работает с указателями!

Применительно к указателям вы получаете (усеченное) соотношение между размером указателя, который всегда одинаков, независимо от того, насколько велик ваш массив, и размером одного элемента в этом массиве, поэтому в вашем случае с int* большинство скорее всего либо 2 (64-битная система, обычно 8-байтовые указатели, 4-байтовые int), либо 1 (32-битная система, обычно 4-байтовые указатели, 4-байтовые int), хотя другие системы могут давать и другие значения, но все еще не требуется (кроме случайного совпадения размера массива...).

Чтобы использовать размеры в массиве, вам нужно явно передать его другим параметром:

int highestNumber(size_t length, int* array)
{
    int highest = INT_MIN;
    while(length--)
    {
        if (*array > highest)
        {
           highest = *array;
        }
        ++array;
    }
    return highest;
}

В то время как вы можете применить трюк sizeof к передаваемому массиву:

int array[4];
// assign values to

// array has not yet decayed to pointer, thus you can do:
int highest = highestNumber(sizeof(array)/sizeof(*array), array);

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

size_t length = 4;
int* array = malloc(length * sizeof(*array));
// assign values
int highest = highestNumber(length, array);

Последнее замечание: конечно, вы можете использовать длину/размер в качестве второго параметра; наличие его в качестве первого позволит:

int highestNumber(size_t length, int array[length]);

Что полностью эквивалентно, так как для самого внешнего измерения явно указанный размер массива игнорируется, и параметр по-прежнему остается указателем (обратите внимание, что это не применяется для дальнейших измерений), но это объявление более явно выражает то, что функция фактически ожидает в качестве аргументов.

Редактировать (украл у Влада из Москвы ответ):

Поскольку вы не (намереваетесь) изменять массив внутри функции, то хорошим выбором является принятие указателя на const — это позволяет использовать как неконстантные, так и константные массивы, в то время как исходная сигнатура функции исключает последний без необходимости:

int highestNumber(size_t length, int const* array)
int highestNumber(size_t length, int const array[length]);

Определение int highestNumber() ничего не возвращает.

chux - Reinstate Monica 16.02.2023 17:31

Несколько забавно для Аконкагуа обсуждать на высшем уровне. 😉

chux - Reinstate Monica 16.02.2023 17:33

Другие вопросы по теме