Использование extern с многомерным массивом в C [duplicate]

Полагаю, я понимаю, о чем вы спрашиваете. Хотя вы говорите, что хотите «вернуть» его (по сути) из метода выборки, достаточно сказать, что вы просто хотите использовать значение, полученное после завершения выборки. Если это так, это то, что вам нужно сделать:

  1. Создать переменную в верхней части вашего класса
  2. Извлечь ваше значение (которое вы сделали в основном правильно)
  3. Установите общедоступную переменную в вашем классе, равную полученному значению

. После того, как ваша выборка завершится успешно, вы можете делать много вещей с переменной. 4а и 4b - некоторые простые примеры:

4a. Изменить. В качестве примера использования вы можете запустить все, что вам нужно для запуска в вашем классе, который использует yourNameVariable (и вы можете быть уверены, что yourNameVariable не является нулевым)

4b. Изменить: в качестве примера использования вы можете использовать переменную в функции, которая запускается кнопкой onClickListener.


Попробуйте это.

// 1. Create a variable at the top of your class
private String yourNameVariable;

// 2. Retrieve your value (which you have done mostly correctly)
private void getUserName(String uid) {
    databaseReference.child(String.format("users/%s/name", uid))
            .addListenerForSingleValueEvent(new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {
            // 3. Set the public variable in your class equal to value retrieved
            yourNameVariable = dataSnapshot.getValue(String.class);
            // 4a. EDIT: now that your fetch succeeded, you can trigger whatever else you need to run in your class that uses `yourNameVariable`, and you can be sure `yourNameVariable` is not null.
            sayHiToMe();
        }

        @Override
        public void onCancelled(DatabaseError databaseError) {}
    });
}

// (part of step 4a)
public void sayHiToMe() {
  Log.d(TAG, "hi there, " + yourNameVariable);
}

// 4b. use the variable in a function triggered by the onClickListener of a button.
public void helloButtonWasPressed() {
  if (yourNameVariable != null) {
    Log.d(TAG, "hi there, " + yourNameVariable);
  }
}

Затем вы может использовать yourNameVariable, где бы вы ни захотели на протяжении всего вашего класса.


Примечание: просто убедитесь, что вы проверяете, что yourNameVariable не является нулевым при его использовании, поскольку onDataChange является асинхронным и может не завершиться в то время, когда вы пытаетесь использовать его в другом месте.

0
задан user1955184 12 April 2013 в 22:00
поделиться

2 ответа

Я попробовал следующее объяснение, но не уверен, является ли это «правильным» объяснением.

Не совсем, но он несколько близок.

t содержит адрес A[0], но поскольку A является массивом, а A[0] является указателем на массив

A[0] является массивом , в частности, его тип - int[4].

(который является «не совсем» указателем), C не выделяет память для указателя A или A[0] специально НЕОБХОДИМО другие переменные указателя.

Массивы и указатели представляют собой принципиально разные типы объектов. Не путайте их.

Тот факт, что в большинстве случаев выражение типа array of T преобразуется в значение типа pointer to T (указывающее на первый элемент массива), несомненно, способствует путанице, но нельзя забывать, что это преобразование . В частности, для многомерных массивов или массивов массивов тип элемента массива сам по себе является типом массива, поэтому результат преобразования является указателем на массив.

It выделяет память только для массива в целом. Таким образом, адрес A[0] и A[0] (который является адресом A[0][0]), по сути, один и тот же,

Нет, они существенно отличаются друг от друга, один - A[0] - это массив, int[4], другой - &A[0] - указатель на массив из четырех int, int(*)[4]. Также &A[0][0].

Но когда A[0] преобразуется в указатель на его первый элемент, &A[0][0], результирующий адрес обычно совпадает с адресом A[0] (обычно, a указатель на объект содержит адрес байта с наименьшим адресом, принадлежащим этому объекту, и поскольку A[0] принадлежит (является частью) объекта A, тот, у которого самый младший адрес, первый байт, который является частью A[0] является первым байтом, который является частью A).

Итак, &A[0] и &A[0][0] обычно имеют одно и то же представление, но одно - int(*)[4], другое - [int*.

оба принадлежат под одной крышей и не являются «отдельными» сущностями. В результате t в свою очередь косвенно удерживает адрес A[0][0] и *t, дает значение A[0][0], которое равно 1.

Эта часть, кроме несоответствие типа, которое делает разыменование t неопределенным поведением более или менее правильным. Формально неопределенное поведение допускает что-либо.

На практике, если sizeof(int) == sizeof(int*), разыменование t интерпретирует int 1, который является A[0][0] в качестве адреса, и если вы печатаете это как int (еще одно неопределенное поведение), вы получите 1. Если sizeof(int*) == 2*sizeof(int), как это обычно бывает в 64-битных системах, разыменование t обычно интерпретирует два int s A[0][0] и A[0][1] вместе как адрес - 0x200000001 или 0x100000002 в зависимости от того, .

0
ответ дан Daniel Fischer 27 August 2018 в 00:33
поделиться

Массивы не являются указателями.

Ну, еще больше ...

Многомерные массивы не являются двойными, тройными и т. д. указатели.

Итак, все, что у вас есть, неверно, ваша программа несколько раз вызывает неопределенное поведение, и вы ничего не можете ожидать.

Учитывая, что массивы смежны в памяти , вы можете переписать свой пример следующим образом:

int A[3][4] = {{1,2,3,4},{5,6,7,8,},{9,10,11,12}};
int *p = &A[0][0];

printf("%d %d %p\n", A[0][0], *p, (void *)p);
2
ответ дан user 27 August 2018 в 00:33
поделиться
Другие вопросы по тегам:

Похожие вопросы: