Я предполагаю, что следующее даст мне 10 энергозависимых ints
volatile int foo[10];
Однако я не думаю, что следующее сделает то же самое.
volatile int* foo;
foo = malloc(sizeof(int)*10);
Исправьте меня, если я неправ относительно этого и как у меня может быть энергозависимый массив объектов с помощью malloc.
Спасибо.
int volatile * foo;
читается справа налево «foo - указатель на изменчивый int»
, поэтому к любому int, к которому вы обращаетесь через foo, int будет непостоянным.
P.S.
int * volatile foo; // "foo is a volatile pointer to an int"
==
volatile int * foo; // foo is a pointer to an int, volatile
Значение foo изменчиво. Второй случай на самом деле является остатком общего правила написания справа налево. Урок, который нужно усвоить, - это выработать привычку использовать
char const * foo;
вместо более распространенного
const char * foo;
. Если вы хотите большего такие сложные вещи, как «указатель на функцию, возвращающую указатель на int», имеют какой-то смысл.
P.S., И это большая проблема (и основная причина, по которой я добавляю ответ):
Я заметил, что вы включили «многопоточность» в качестве тега. Понимаете ли вы, что volatile не дает ничего хорошего в отношении многопоточности?
PyLog :
-121--2964652-PyLog является логической библиотекой первого порядка включая модуль PROLOG в Python.
Обычно рекомендуется сделать это в onCreate ()
/ onDestroy ()
или onStart ()
/ onStop ()
, в зависимости от желаемой семантики:
Если операция
должна взаимодействовать с услугой
в течение всего времени ее работы (например, он может получить некоторые данные из сети для вас и вернет данные, когда они будут готовы, и вы хотите, чтобы это произошло в фоновом режиме, так что если пользователь вернет вы будете готовы данные), то onCreate ()
/ onDestroy ()
, вероятно, подходит. Следует отметить, что семантика состоит в том, что в течение всего времени выполнения операции
требуется Сервис
, поэтому, если Сервис
выполняется в другом процессе, вес этого процесса увеличивается, что повышает вероятность его уничтожения в фоновом режиме.
Если функция Activity
предназначена только для работы со службой Service
во время отображения, то onStart ()
/ onStop ()
является подходящей. Это означает, что операция
отменяет привязку к услуге
, когда пользователь покидает ее (и она больше не видна), и выполняет резервное копирование при следующем возврате, а затем повторно запускается и возобновляется.
Обычно не рекомендуется выполнять привязку/отмену привязки в onResume ()
и onPause ()
. Это, как правило, значительно не уменьшает количество, которое вы используете Сервис
(и, следовательно, ваши накладные расходы), и фактически, поскольку пауза и возобновление происходят при каждом переходе активности, это путь кода, который вы хотите сохранить как можно более легким. Это может иметь и другие неожиданные негативные последствия: например, если несколько действий
в приложении привязываются к одной и той же службе
, то при переходе между двумя из этих действий служба
также может быть уничтожена и воссоздана, поскольку текущее действие
приостановлено перед возобновлением следующего.
Также эти пары ( onCreate ()
/ onDestroy ()
, onStart ()
/ onStop ()
, onPause ()
/ onResume ()
) предназначены, чтобы быть надлежащими парами для приобретения и затем высвободить средства (такие как соединение с Обслуживание
с, регистрация приемников, и т.д.), чтобы гарантировать, что они правильно приобретены до того, чтобы быть необходимым и выпущены (и не пропущены), когда больше не необходимый.
volatile int* foo;
- это путь. Квалификатор типа volatile работает так же, как квалификатор типа const . Если бы вам нужен был указатель на постоянный массив целых чисел, вы бы написали:
const int* foo;
, тогда как
int* const foo;
является постоянным указателем на целое число, которое само по себе может быть изменено. volatile работает в одном и том же пути.
Да, это сработает. Нет ничего особенного в фактической памяти, которая является энергозависимой
. Это просто способ сообщить компилятору, как взаимодействовать с этой памятью.
Я думаю, что второй объявляет указатель изменчивым, а не то, на что он указывает. Чтобы получить это, я думаю, он должен быть
int * volatile foo;
Этот синтаксис приемлем для gcc
, но мне трудно убедить себя , что он делает что-то другое.
Я обнаружил разницу с gcc -O3
(полная оптимизация).Для этого (глупого) тестового кода:
volatile int v [10];
int * volatile p;
int main (void)
{
v [3] = p [2];
p [3] = v [2];
return 0;
}
С volatile
и опусканием (x86) инструкций, которые не меняются:
movl p, %eax
movl 8(%eax), %eax
movl %eax, v+12
movl p, %edx
movl v+8, %eax
movl %eax, 12(%edx)
Без volatile, он пропускает перезагрузку p
:
movl p, %eax
movl 8(%eax), %edx ; different since p being preserved
movl %edx, v+12
; 'p' not reloaded here
movl v+8, %edx
movl %edx, 12(%eax) ; p reused
После множества научных экспериментов, пытающихся найти разницу, я пришел к выводу, что разницы нет. volatile
отключает все оптимизации, связанные с переменной, которая будет повторно использовать впоследствии установленное значение. По крайней мере, с x86 gcc (GCC) 4.1.2 20070925 (Red Hat 4.1.2-33). : -)
Выполните следующие действия:
int showLimit = 20;
/* Get all Tasks available (with limit set). */
ActivityManager mgr = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
List<ActivityManager.RunningTaskInfo> allTasks = mgr.getRunningTasks(showLimit);
/* Loop through all tasks returned. */
for (ActivityManager.RunningTaskInfo aTask : allTasks)
{
Log.i("MyApp", "Task: " + aTask.baseActivity.getClassName());
if (aTask.baseActivity.getClassName().equals("com.android.email.activity.MessageList"))
running=true;
}
-121--731745- var firstImage = imgList.Cast<Image>().First();
-121--1712600- Благодаря блеску, я смог разработать код, использующий его метод для создания сборки, чтобы доказать себе разницу между различными методами указателей.
с помощью кода: и компиляции с -03
int main (void)
{
while(p[2]);
return 0;
}
, когда p просто объявлен как указатель, мы застрянем в цикле, из которого невозможно выбраться. Заметим, что если бы это была многопоточная программа и другой поток записывал p [2] = 0, то программа вырвалась бы из цикла while и завершилась бы нормально.
int * p;
============
LCFI1:
movq _p(%rip), %rax
movl 8(%rax), %eax
testl %eax, %eax
jne L6
xorl %eax, %eax
leave
ret
L6:
jmp L6
обратите внимание, что единственной инструкцией для L6 является переход к L6.
, когда p является энергозависимым указателем
int * volatile p;
==============
L3:
movq _p(%rip), %rax
movl 8(%rax), %eax
testl %eax, %eax
jne L3
xorl %eax, %eax
leave
ret
, указатель p перегружается на каждую итерацию цикла, и, как следствие, массив предмета также перезагружается. Однако, это было бы неправильно, если бы мы хотели массив изменчивых целых чисел, так как это было бы возможно:
int* volatile p;
..
..
int* j;
j = &p[2];
while(j);
и привело бы к циклу, который было бы невозможно завершить в многопоточной программе.
наконец, это правильное решение, как хорошо объяснили Тони.
int volatile * p;
LCFI1:
movq _p(%rip), %rdx
addq $8, %rdx
.align 4,0x90
L3:
movl (%rdx), %eax
testl %eax, %eax
jne L3
leave
ret
В этом случае адрес p [2] сохраняется в регистровом значении и не загружается из памяти, но значение p [2] перезагружается из памяти в каждом цикле цикла.
также следует отметить, что
int volatile * p;
..
..
int* j;
j = &p[2];
while(j);
создаст ошибку компиляции.