Что затухает массив?

Возможно проблема с зависимостью от плагина. Удалите этот плагин cordova-plugin-firebase, затем используйте эту команду для CLI:

плагин ionic cordova rm cordova-plugin-firebase cordova clean ionic cordova подготовьте android ionic cordova run android Я надеюсь решить вашу проблему.

blockquote>

https://forum.ionicframework.com/t/test-ionic-app-to-actual-device-or-emulator/153300/2

356
задан Peter Mortensen 3 November 2015 в 19:35
поделиться

8 ответов

Говорят, что массивы «распадаются» на указатели. Массив C ++, объявленный как int numbers [5] , не может быть перенаправлен, то есть вы не можете сказать numbers = 0x5a5aff23 . Что еще более важно, термин «распад» означает потерю типа и размера; числа распадаются на int * , теряя информацию о размерности (счет 5), и тип больше не int [5] . Найдите здесь случаев, когда распада не происходит .

Если вы передаете массив по значению, то на самом деле вы копируете указатель - указатель на первый элемент массива копируется в параметр (тип которого также должен быть указателем на тип элемента массива). Это работает из-за разрушающейся природы массива; однажды распался, sizeof больше не дает полный размер массива, потому что по сути становится указателем. Вот почему (среди прочего) предпочтительнее передавать по ссылке или указателю.

Три способа передать массив 1 :

void by_value(const T* array)   // const T array[] means the same
void by_pointer(const T (*array)[U])
void by_reference(const T (&array)[U])

Последние два дадут правильный размер ] информация, в то время как первая не будет, поскольку аргумент массива распался, чтобы быть назначенным параметру.

1 Константа U должна быть известна во время компиляции.

259
ответ дан 23 November 2019 в 00:21
поделиться

Я мог бы быть настолько полужирным, чтобы думать, что существует четыре (4) способа передать массив как аргумент функции. Также вот короткий, но рабочий код для Вашего прочтения.

#include <iostream>
#include <string>
#include <vector>
#include <cassert>

using namespace std;

// test data
// notice native array init with no copy aka "="
// not possible in C
 const char* specimen[]{ __TIME__, __DATE__, __TIMESTAMP__ };

// ONE
// simple, dangerous and useless
template<typename T>
void as_pointer(const T* array) { 
    // a pointer
    assert(array != nullptr); 
} ;

// TWO
// for above const T array[] means the same
// but and also , minimum array size indication might be given too
// this also does not stop the array decay into T *
// thus size information is lost
template<typename T>
void by_value_no_size(const T array[0xFF]) { 
    // decayed to a pointer
    assert( array != nullptr ); 
}

// THREE
// size information is preserved
// but pointer is asked for
template<typename T, size_t N>
void pointer_to_array(const T (*array)[N])
{
   // dealing with native pointer 
    assert( array != nullptr ); 
}

// FOUR
// no C equivalent
// array by reference
// size is preserved
template<typename T, size_t N>
void reference_to_array(const T (&array)[N])
{
    // array is not a pointer here
    // it is (almost) a container
    // most of the std:: lib algorithms 
    // do work on array reference, for example
    // range for requires std::begin() and std::end()
    // on the type passed as range to iterate over
    for (auto && elem : array )
    {
        cout << endl << elem ;
    }
}

int main()
{
     // ONE
     as_pointer(specimen);
     // TWO
     by_value_no_size(specimen);
     // THREE
     pointer_to_array(&specimen);
     // FOUR
     reference_to_array( specimen ) ;
}

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

, Конечно, существуют чрезвычайно строгие проекты без выделения "кучи", никаких исключений и никакого станд.:: lib. Собственная обработка массива C++ является функцией языка в жестком реальном времени, можно было бы сказать.

0
ответ дан 23 November 2019 в 00:21
поделиться

Массивы в основном такие же, как указатели в C / C ++, но не совсем. После преобразования массива:

const int a[] = { 2, 3, 5, 7, 11 };

в указатель (который работает без приведения типов и поэтому в некоторых случаях может происходить неожиданно):

const int* p = a;

вы теряете способность оператора sizeof подсчитывать элементы в array:

assert( sizeof(p) != sizeof(a) );  // sizes are not equal

Эта утраченная способность называется «распадом».

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

95
ответ дан 23 November 2019 в 00:21
поделиться

Это когда массив гниет и на него указывают; -)

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

8
ответ дан 23 November 2019 в 00:21
поделиться

Распад массива означает, что когда массив передается в качестве параметра функции, он обрабатывается так же, как («распадается на») указатель.

void do_something(int *array) {
  // We don't know how big array is here, because it's decayed to a pointer.
  printf("%i\n", sizeof(array));  // always prints 4 on a 32-bit machine
}

int main (int argc, char **argv) {
    int a[10];
    int b[20];
    int *c;
    printf("%zu\n", sizeof(a)); //prints 40 on a 32-bit machine
    printf("%zu\n", sizeof(b)); //prints 80 on a 32-bit machine
    printf("%zu\n", sizeof(c)); //prints 4 on a 32-bit machine
    do_something(a);
    do_something(b);
    do_something(c);
}

Есть два осложнения или исключения для

Во-первых, при работе с многомерными массивами в C и C ++ теряется только первое измерение. Это связано с тем, что массивы расположены в памяти непрерывно, поэтому компилятор должен знать все измерения, кроме первого, чтобы иметь возможность вычислять смещения в этом блоке памяти.

void do_something(int array[][10])
{
    // We don't know how big the first dimension is.
}

int main(int argc, char *argv[]) {
    int a[5][10];
    int b[20][10];
    do_something(a);
    do_something(b);
    return 0;
}

Во-вторых, в C ++ вы можете использовать шаблоны для определения размера массивы. Microsoft использует это для версий C ++ функций Secure CRT, таких как strcpy_s , и вы можете использовать аналогичный прием, чтобы надежно получить количество элементов в массиве .

3
ответ дан 23 November 2019 в 00:21
поделиться

Массивы в C не имеют значения.

Везде, где ожидается значение объекта, но объект является массивом вместо этого используется адрес ее первого элемента с указателем типа на (тип элементов массива) .

В функции все параметры передаются по значению (массивы не исключение). Когда вы передаете массив в функцию, он «превращается в указатель» (sic); когда вы сравниваете массив с чем-то другим, он снова «превращается в указатель» (sic); ...

void foo(int arr[]);

Функция foo ожидает значение массива. Но в C массивы не имеют значения! Таким образом, foo получает вместо этого адрес первого элемента массива.

int arr[5];
int *ip = &(arr[1]);
if (arr == ip) { /* something; */ }

В приведенном выше сравнении arr не имеет значения, поэтому он становится указателем. Он становится указателем на int.

13
ответ дан 23 November 2019 в 00:21
поделиться

Вот что говорит стандарт (C99 6.3.2.1/3 - Другие операнды - Lvalue, массивы и указатели функций):

За исключением случаев, когда это операнд оператора sizeof или унарный оператор &, или строковый литерал, используемый для инициализации массива, выражение, имеющее тип "массив типа", является преобразовано в выражение с типом "указатель на тип", которое указывает на начальный элемент объект массива и не является lvalue.

Это означает, что почти каждый раз, когда имя массива используется в выражении, оно автоматически преобразуется в указатель на 1-й элемент в массиве.

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

Стандарт C ++ (4.2 Array-to -поинтер-преобразование) ослабляет требования к преобразованию в (выделено мной):

lvalue или rvalue типа «массив NT» или «массив неизвестной границы T» может быть преобразован в rvalue of type “pointer to T.”

So the conversion doesn't have to happen like it pretty much always does in C (this lets functions overload or templates match on the array type).

This is also why in C you should avoid using array parameters in function prototypes/definitions (in my opinion - I'm not sure if there's any general agreement). They cause confusion and are a fiction anyway - use pointer parameters and the confusion might not go away entirely, but at least the parameter declaration isn't lying.

43
ответ дан 23 November 2019 в 00:21
поделиться

«Распад» относится к неявному преобразованию выражения из типа массива в тип указателя. В большинстве случаев, когда компилятор видит выражение массива, он преобразует тип выражения из «N-элементного массива T» в «указатель на T» и устанавливает значение выражения равным адресу первого элемента массива. . Исключениями из этого правила являются случаи, когда массив является операндом операторов sizeof или & , либо массив является строковым литералом, используемым в качестве инициализатора в объявлении.

Предположим, что следующий код:

char a[80];
strcpy(a, "This is a test");

Выражение a имеет тип «80-элементный массив символов», а выражение «Это тест» имеет тип «16-элементный массив символов. "(в C; в C ++ строковые литералы - это массивы const char). Однако в вызове strcpy () ни одно выражение не является операндом sizeof или & , поэтому их типы неявно преобразуются в «указатель на char» , и их значения устанавливаются на адрес первого элемента в каждом. strcpy () получает не массивы, а указатели, как видно из его прототипа:

char *strcpy(char *dest, const char *src);

Это не то же самое, что указатель на массив. Например:

char a[80];
char *ptr_to_first_element = a;
char (*ptr_to_array)[80] = &a;

Оба ptr_to_first_element и ptr_to_array имеют одинаковое значение ; базовый адрес a. Однако они бывают разных типов и обрабатываются по-разному, как показано ниже:

a[i] == ptr_to_first_element[i] == (*ptr_to_array)[i] != *ptr_to_array[i] != ptr_to_array[i]

Помните, что выражение a [i] интерпретируется как * (a + i) (которое работает только в том случае, если тип массива преобразован в тип указателя), поэтому оба a [i] и ptr_to_first_element [i] работают одинаково. Выражение (* ptr_to_array) [i] интерпретируется как * (* a + i) . Выражения * ptr_to_array [i] и ptr_to_array [i] могут приводить к предупреждениям или ошибкам компилятора в зависимости от контекста; они определенно поступят неправильно, если вы ожидаете, что они оценят как a [i] .

sizeof a == sizeof *ptr_to_array == 80

Опять же, когда массив является операндом sizeof , это не преобразован в тип указателя.

sizeof *ptr_to_first_element == sizeof (char) == 1
sizeof ptr_to_first_element == sizeof (char *) == whatever the pointer size
                                                  is on your platform

ptr_to_first_element - простой указатель на char.

поэтому оба a [i] и ptr_to_first_element [i] работают одинаково. Выражение (* ptr_to_array) [i] интерпретируется как * (* a + i) . Выражения * ptr_to_array [i] и ptr_to_array [i] могут приводить к предупреждениям или ошибкам компилятора в зависимости от контекста; они определенно поступят неправильно, если вы ожидаете, что они оценят как a [i] .

sizeof a == sizeof *ptr_to_array == 80

Опять же, когда массив является операндом sizeof , это не преобразован в тип указателя.

sizeof *ptr_to_first_element == sizeof (char) == 1
sizeof ptr_to_first_element == sizeof (char *) == whatever the pointer size
                                                  is on your platform

ptr_to_first_element - простой указатель на char.

поэтому оба a [i] и ptr_to_first_element [i] работают одинаково. Выражение (* ptr_to_array) [i] интерпретируется как * (* a + i) . Выражения * ptr_to_array [i] и ptr_to_array [i] могут приводить к предупреждениям или ошибкам компилятора в зависимости от контекста; они определенно поступят неправильно, если вы ожидаете, что они оценят как a [i] .

sizeof a == sizeof *ptr_to_array == 80

Опять же, когда массив является операндом sizeof , это не преобразован в тип указателя.

sizeof *ptr_to_first_element == sizeof (char) == 1
sizeof ptr_to_first_element == sizeof (char *) == whatever the pointer size
                                                  is on your platform

ptr_to_first_element - простой указатель на char.

Выражения * ptr_to_array [i] и ptr_to_array [i] могут приводить к предупреждениям или ошибкам компилятора в зависимости от контекста; они определенно поступят неправильно, если вы ожидаете, что они оценят как a [i] .

sizeof a == sizeof *ptr_to_array == 80

Опять же, когда массив является операндом sizeof , это не преобразован в тип указателя.

sizeof *ptr_to_first_element == sizeof (char) == 1
sizeof ptr_to_first_element == sizeof (char *) == whatever the pointer size
                                                  is on your platform

ptr_to_first_element - простой указатель на char.

Выражения * ptr_to_array [i] и ptr_to_array [i] могут приводить к предупреждениям или ошибкам компилятора в зависимости от контекста; они определенно поступят неправильно, если вы ожидаете, что они оценят как a [i] .

sizeof a == sizeof *ptr_to_array == 80

Опять же, когда массив является операндом sizeof , это не преобразован в тип указателя.

sizeof *ptr_to_first_element == sizeof (char) == 1
sizeof ptr_to_first_element == sizeof (char *) == whatever the pointer size
                                                  is on your platform

ptr_to_first_element - простой указатель на char.

26
ответ дан 23 November 2019 в 00:21
поделиться