Вы должны взглянуть на рекомендованный ContactsContract.PhoneLookup провайдера
Таблица, которая представляет собой результат поиска номера телефона, например, для идентификации вызывающего абонента. Чтобы выполнить поиск, вы должны добавить номер, который вы хотите найти, к CONTENT_FILTER_URI. Этот запрос высоко оптимизирован.
Uri uri = Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, Uri.encode(phoneNumber));
resolver.query(uri, new String[]{PhoneLookup.DISPLAY_NAME,...
В Perl они приводят к одним и тем же кодам операций:
$ perl -MO=Concise -e 'for(;;) { print "foo\n" }'
a <@> leave[1 ref] vKP/REFC ->(end)
1 <0> enter ->2
2 <;> nextstate(main 2 -e:1) v ->3
9 <2> leaveloop vK/2 ->a
3 <{> enterloop(next->8 last->9 redo->4) v ->4
- <@> lineseq vK ->9
4 <;> nextstate(main 1 -e:1) v ->5
7 <@> print vK ->8
5 <0> pushmark s ->6
6 <$> const[PV "foo\n"] s ->7
8 <0> unstack v ->4
-e syntax OK
$ perl -MO=Concise -e 'while(1) { print "foo\n" }'
a <@> leave[1 ref] vKP/REFC ->(end)
1 <0> enter ->2
2 <;> nextstate(main 2 -e:1) v ->3
9 <2> leaveloop vK/2 ->a
3 <{> enterloop(next->8 last->9 redo->4) v ->4
- <@> lineseq vK ->9
4 <;> nextstate(main 1 -e:1) v ->5
7 <@> print vK ->8
5 <0> pushmark s ->6
6 <$> const[PV "foo\n"] s ->7
8 <0> unstack v ->4
-e syntax OK
Аналогично в GCC:
#include <stdio.h>
void t_while() {
while(1)
printf("foo\n");
}
void t_for() {
for(;;)
printf("foo\n");
}
.file "test.c"
.section .rodata
.LC0:
.string "foo"
.text
.globl t_while
.type t_while, @function
t_while:
.LFB2:
pushq %rbp
.LCFI0:
movq %rsp, %rbp
.LCFI1:
.L2:
movl $.LC0, %edi
call puts
jmp .L2
.LFE2:
.size t_while, .-t_while
.globl t_for
.type t_for, @function
t_for:
.LFB3:
pushq %rbp
.LCFI2:
movq %rsp, %rbp
.LCFI3:
.L5:
movl $.LC0, %edi
call puts
jmp .L5
.LFE3:
.size t_for, .-t_for
.section .eh_frame,"a",@progbits
.Lframe1:
.long .LECIE1-.LSCIE1
.LSCIE1:
.long 0x0
.byte 0x1
.string "zR"
.uleb128 0x1
.sleb128 -8
.byte 0x10
.uleb128 0x1
.byte 0x3
.byte 0xc
.uleb128 0x7
.uleb128 0x8
.byte 0x90
.uleb128 0x1
.align 8
.LECIE1:
.LSFDE1:
.long .LEFDE1-.LASFDE1
.LASFDE1:
.long .LASFDE1-.Lframe1
.long .LFB2
.long .LFE2-.LFB2
.uleb128 0x0
.byte 0x4
.long .LCFI0-.LFB2
.byte 0xe
.uleb128 0x10
.byte 0x86
.uleb128 0x2
.byte 0x4
.long .LCFI1-.LCFI0
.byte 0xd
.uleb128 0x6
.align 8
.LEFDE1:
.LSFDE3:
.long .LEFDE3-.LASFDE3
.LASFDE3:
.long .LASFDE3-.Lframe1
.long .LFB3
.long .LFE3-.LFB3
.uleb128 0x0
.byte 0x4
.long .LCFI2-.LFB3
.byte 0xe
.uleb128 0x10
.byte 0x86
.uleb128 0x2
.byte 0x4
.long .LCFI3-.LCFI2
.byte 0xd
.uleb128 0x6
.align 8
.LEFDE3:
.ident "GCC: (Ubuntu 4.3.3-5ubuntu4) 4.3.3"
.section .note.GNU-stack,"",@progbits
Итак, я думаю, ответ таков: они одинаковы во многих компиляторах. Конечно, для некоторых других компиляторов это не обязательно так, но есть вероятность, что код внутри цикла в любом случае будет в несколько тысяч раз дороже, чем сам цикл, так что кого это волнует?
Я бы подумал, что оба они одинаковы по производительности. Но я бы предпочел while (1) для удобства чтения, но я сомневаюсь, зачем вам бесконечный цикл.
Они такие же. Есть гораздо более важные вопросы, над которыми стоит задуматься.
в то время как (1)
- это идиома для для (;;)
, которая распознается большинством компиляторов.
Я был рад увидеть, что perl распознает С до (0)
тоже.
В оптимизированной сборке скомпилированного языка между ними не должно быть заметной разницы. Ни один из них не должен выполнять никаких сравнений во время выполнения, они просто будут выполнять код цикла, пока вы вручную не выйдете из цикла (например, с break
).
Для всех людей, которые утверждают, что вы не должны использовать неопределенные циклы while, и предлагают глупые вещи, такие как использование open goto (серьезно, ой)
while (1) {
last if( condition1 );
code();
more_code();
last if( condition2 );
even_more_code();
}
Can ' На самом деле это может быть эффективно представлено любым другим способом. Не обошлось и без создания переменной выхода и использования черной магии для ее синхронизации.
Если у вас есть склонность к синтаксису в стиле goto, используйте что-нибудь разумное, ограничивающее область действия.
flow: {
if ( condition ){
redo flow;
}
if ( othercondition ){
redo flow;
}
if ( earlyexit ){
last flow;
}
something(); # doesn't execute when earlyexit is true
}
В конечном итоге скорость не так важна.
Беспокойство о том, насколько эффективны с точки зрения скорости различные циклические конструкции, - огромная трата времени. Преждевременная оптимизация насквозь. Я не могу вспомнить ни одной ситуации, которую я когда-либо видел, когда код профилирования обнаруживал узкие места в моем выборе конструкции цикла.
Обычно это how цикла и what цикла.
Вы должны «оптимизировать» для удобочитаемости и лаконичности и писать то, что лучше всего объясняет проблему следующему бедолаге, который найдет ваш код.
Если вы используете уловку "goto LABEL", о которой упоминал кто-то, и я должен использовать ваш код, будьте готовы спать с одним открытым глазом, особенно если вы делаете это более одного раза, потому что такого рода вещи создают ужасающе спагетти-код.
Тот факт, что вы можете создать код спагетти, не означает, что вы должны
for (;;)
- это на один символ меньше для ввода, если вы хотите пойти в этом направлении для оптимизации.
There is no difference according to the standard. 6.5.3/1 has:
The for statement
for ( for-init-statement ; conditionopt ; expressionopt ) statement
is equivalent to
{
for-init-statement
while ( condition ) {
statement
expression ;
}
}
And 6.5.3/2 has:
Either or both of the condition and the expression can be omitted. A missing condition makes the implied while clause equivalent to while(true).
So according to the C++ standard the code:
for (;;);
is exactly the same as:
{
while (true) {
;
;
}
}
Компилятор Visual C ++, используемый для выдачи предупреждения для
while (1)
(постоянное выражение), но не для
for (;;)
. Я продолжил практику, предпочитая для ( ;;)
по этой причине, но я не знаю, продолжает ли компилятор это делать в наши дни.
Нет особых причин предпочитать одно другому. Я действительно думаю, что while (1)
и особенно while (true)
более читабельны, чем для (;;)
, но это только мое предпочтение.
Используя GCC, кажется, что они оба компилируются на один и тот же язык ассемблера:
L2:
jmp L2
Другим решением было бы отделение кода от макетов с помощью соответствующего механизма создания шаблонов.
-121--2478554-Посмотрите на WGL4 . Это список символов, которые должны быть правильно показаны на оконных машинах, и я думаю, что это означает, что они будут показаны правильно на большинстве устройств.
-121--1918258-От Stroustup, TC++ PL (3-е издание), § 6,1,1:
Любопытное обозначение
для (;;)
является стандартным способом задания бесконечного цикла; ты можешь произнести это «навсегда.» [...], в то время как (true)
является альтернативой.
Я предпочитаю для (;)
.
Теоретически полностью наивный компилятор мог бы сохранить литерал '1' в двоичном файле (тратя пространство) и проверить, не 1 == 0 на каждой итерации (тратя время и больше места).
В действительности, однако, даже без оптимизаций, компиляторы все равно сводят их к одному и тому же. Они также могут выдавать предупреждения, поскольку это может указывать на логическую ошибку. Например, аргумент , в то время как
может быть определен где-то еще, и вы не понимаете, что он постоянный.
Я удивлен, что никто не предложил более прямую форму, соответствующую желаемой сборке:
forever:
do stuff;
goto forever;