|
Показать число с leading zeros. |
|
|
|
Jan 21 2015, 14:21
|
Гуру
     
Группа: Свой
Сообщений: 7 946
Регистрация: 25-02-05
Из: Moscow, Russia
Пользователь №: 2 881

|
Что-то у вас косяк с уровнем оптимизации. Это пишется в несколько команд ассемблера. Для особо тупых компиляторов, можно еще подоптимизировать: CODE void ItoA(char * str, int number) { static int num_table[9] = {10000000, 1000000,100000,10000,1000,100,10,1,0}; int p=0; char *str_p = str; int i; int tmp; tmp = num_table[p++]; do { i='0'; while ( (number-=tmp) >= 0) i++; number += tmp; *str_p++=i; } while (tmp=num_table[p++]); *str_p++=0; }
|
|
|
|
|
Jan 21 2015, 14:36
|

Местный
  
Группа: Участник
Сообщений: 329
Регистрация: 23-04-14
Пользователь №: 81 502

|
Цитата(Jenya7 @ Jan 21 2015, 14:18)  в принципе int num_table[9] = {10000000, 1000000,100000,10000,1000,100,10,1,0}; можно вынести из тела функции... Зачем ? Засорять пространство имен всякими локальными именами - очень плохая идея. Объявите этот массив внутри функции как const int num_table[9] = {...} Хотя нормальный компилятор и так должен был догадаться, что это константы.
|
|
|
|
|
Jan 21 2015, 14:40
|
Гуру
     
Группа: Свой
Сообщений: 7 946
Регистрация: 25-02-05
Из: Moscow, Russia
Пользователь №: 2 881

|
Цитата(CrimsonPig @ Jan 21 2015, 17:36)  const int num_table[9] = {...} не const, а static. Да, это мое упущение. Этому на стеке не место. Вот что генерирует TI CCS из последнего кода (16 инструкций): CODE _ItoA: ;* --------------------------------------------------------------------------* LDR V9, $C$CON1 ; |11| .dwpsn file "ccs.c",line 12,column 0,is_stmt LDR A4, [V9, #0] ; |11| ;* --------------------------------------------------------------------------* ;* BEGIN LOOP ||$C$L1|| ;* ;* Loop source line : 12 ;* Loop closing brace source line : 16 ;* Known Minimum Trip Count : 1 ;* Known Maximum Trip Count : 4294967295 ;* Known Max Trip Count Factor : 1 ;* --------------------------------------------------------------------------* ||$C$L1||: $C$DW$L$_ItoA$2$B: SUBS A2, A2, A4 ; |13| MOV A3, #48 ; |13| BMI ||$C$L3|| ; |13| ; BRANCHCC OCCURS {||$C$L3||} ; |13| $C$DW$L$_ItoA$2$E: ;* --------------------------------------------------------------------------* ;* BEGIN LOOP ||$C$L2|| ;* ;* Loop source line : 13 ;* Loop closing brace source line : 13 ;* Known Minimum Trip Count : 1 ;* Known Maximum Trip Count : 4294967295 ;* Known Max Trip Count Factor : 1 ;* --------------------------------------------------------------------------* ||$C$L2||: $C$DW$L$_ItoA$3$B: .dwpsn file "ccs.c",line 13,column 0,is_stmt SUBS A2, A2, A4 ; |13| ADD A3, A3, #1 ; |13| BPL ||$C$L2|| ; |13| ; BRANCHCC OCCURS {||$C$L2||} ; |13| $C$DW$L$_ItoA$3$E: ;* --------------------------------------------------------------------------* ||$C$L3||: $C$DW$L$_ItoA$4$B: STRB A3, [A1], #1 ; |15| ADD A2, A4, A2 ; |14| LDR A4, [V9, #4]! ; |16| CMP A4, #0 ; |16| .dwpsn file "ccs.c",line 16,column 0,is_stmt BNE ||$C$L1|| ; |16| ; BRANCHCC OCCURS {||$C$L1||} ; |16| $C$DW$L$_ItoA$4$E: ;* --------------------------------------------------------------------------* MOV V9, #0 ; |18| STRB V9, [A1, #0] ; |18| .dwpsn file "ccs.c",line 20,column 1,is_stmt $C$DW$4 .dwtag DW_TAG_TI_branch .dwattr $C$DW$4, DW_AT_low_pc(0x00) .dwattr $C$DW$4, DW_AT_TI_return BX LR ; BRANCH OCCURS {LR}
|
|
|
|
|
Jan 21 2015, 14:47
|
Гуру
     
Группа: Свой
Сообщений: 7 946
Регистрация: 25-02-05
Из: Moscow, Russia
Пользователь №: 2 881

|
Вот еще оптимизация (все время забываю про то, что цикл while, в отличие от do, дает лишнюю команду перехода, а это есть самое зло из всех зол - переходы): CODE void ItoA(char * str, int number) { static const int num_table[9] = {10000000, 1000000,100000,10000,1000,100,10,1,0}; int p=0; char *str_p = str; int i; int tmp; tmp = num_table[p++]; do { i='0'-1; do { i++; } while ( (number-=tmp) >= 0); number += tmp; *str_p++=i; } while (tmp=num_table[p++]); *str_p++=0; }
Листинг 15 инструкций  (а без *str_p++=0; всего 13) CODE _ItoA: ;* --------------------------------------------------------------------------* LDR V9, $C$CON1 ; |11| LDR A4, [V9, #0] ; |11| .dwpsn file "ccs.c",line 13,column 0,is_stmt MOV A3, #47 ; |13| ;* --------------------------------------------------------------------------* ;* BEGIN LOOP ||$C$L1|| ;* ;* Loop source line : 13 ;* Loop closing brace source line : 13 ;* Known Minimum Trip Count : 1 ;* Known Maximum Trip Count : 4294967295 ;* Known Max Trip Count Factor : 1 ;* --------------------------------------------------------------------------* ||$C$L1||: $C$DW$L$_ItoA$2$B: SUBS A2, A2, A4 ; |13| ADD A3, A3, #1 ; |13| BPL ||$C$L1|| ; |13| ; BRANCHCC OCCURS {||$C$L1||} ; |13| $C$DW$L$_ItoA$2$E: ;* --------------------------------------------------------------------------* $C$DW$L$_ItoA$3$B: ADD A2, A4, A2 ; |14| LDR A4, [V9, #4]! ; |16| STRB A3, [A1], #1 ; |15| CMP A4, #0 ; |16| MOVNE A3, #47 ; |13| BNE ||$C$L1|| ; |16| ; BRANCHCC OCCURS {||$C$L1||} ; |16| $C$DW$L$_ItoA$3$E: ;* --------------------------------------------------------------------------* MOV V9, #0 ; |18| STRB V9, [A1, #0] ; |18| .dwpsn file "ccs.c",line 20,column 1,is_stmt $C$DW$4 .dwtag DW_TAG_TI_branch .dwattr $C$DW$4, DW_AT_low_pc(0x00) .dwattr $C$DW$4, DW_AT_TI_return BX LR
так что, разбирайтесь со своим кривым компилятором, из какого пальца он там инструкции высасывает.
|
|
|
|
|
Jan 21 2015, 14:53
|

Местный
  
Группа: Участник
Сообщений: 329
Регистрация: 23-04-14
Пользователь №: 81 502

|
Цитата(SM @ Jan 21 2015, 14:40)  не const, а static. Да, это мое упущение. Этому на стеке не место. Почему static-то ?. Думаю, что компилятору будет сильно проще понять, что если int переменная объявлена как const, то выделять память для нее совсем не надо. Кроме того, если вдруг кто-нибудь скопипастит этот код в Ц++, то следует ожидать некоторых сюрпризов: static переменные внутри функций Ц++ инициализирует _первом_ входе управления в область видимости этой переменной. http://stackoverflow.com/questions/55510/w...ted-initializedТо есть для Ц++ память будет выделена и переменная будет инициализирована при первом вызове Foo. void Foo() { static int A = 13; <use A> } думаю, что тут память вообще не будет выделяьтся void Foo() { const int A = 13; static const int B=4; <use A, B> } Цитата(Jenya7 @ Jan 21 2015, 14:50)  эээ...я тут вспомнил что у меня атолик - фри версия...мля...нулевая оптимизация...все мои листинги не годяться. извиняюсь товарищи. Недаром, один из отцов-основателей сказал: "premature opimisation is a root of all evil"
Сообщение отредактировал CrimsonPig - Jan 21 2015, 14:53
|
|
|
|
|
Jan 21 2015, 15:02
|
Гуру
     
Группа: Свой
Сообщений: 7 946
Регистрация: 25-02-05
Из: Moscow, Russia
Пользователь №: 2 881

|
Цитата(CrimsonPig @ Jan 21 2015, 17:53)  Почему static-то Потому, что любые переменные, не объявленные статическими, но объявленные внутри функции, располагаются на стеке, независимо от того, const они, или нет. И инициализируются динамически после вызова функции. Се ля ви, так сказать. ------------- для ТС: А вот Вам Ваш код, тем же компилятором, с той же оптимизацией. Сравнивайте с 15-ю инструкциями. CODE _Reverse: ;* --------------------------------------------------------------------------* SUB A2, A1, #1 ; |94| STMFD SP!, {V1, V2, V3, LR} LDRB A3, [A2, #1]! ; |96| .dwpsn file "C:/CCStudio_v3.3/tms470_4.6.2/include/string.h",line 96,column 0,is_stmt MVN V9, #0 ; |93| ;* --------------------------------------------------------------------------* ;* BEGIN LOOP ||$C$L1|| ;* ;* Loop source line : 96 ;* Loop closing brace source line : 96 ;* Known Minimum Trip Count : 1 ;* Known Maximum Trip Count : 4294967295 ;* Known Max Trip Count Factor : 1 ;* --------------------------------------------------------------------------* ||$C$L1||: $C$DW$L$_Reverse$2$B: CMP A3, #0 ; |96| LDRNEB A3, [A2, #1]! ; |96| ADD V9, V9, #1 ; |96| BNE ||$C$L1|| ; |96| ; BRANCHCC OCCURS {||$C$L1||} ; |96| $C$DW$L$_Reverse$2$E: ;* --------------------------------------------------------------------------* SUBS A3, V9, #1 ; |97| LDMLEFD SP!, {V1, V2, V3, PC} ; BRANCHCC OCCURS {[SP, #0]} ;* --------------------------------------------------------------------------* ADD V3, V9, V9, LSR #31 ; |36| CMP V9, #4 ; |36| MOV A4, V3, ASR #2 ; |36| MOV LR, #0 ; |34| MOV V9, A1 BLT ||$C$L3|| ; |36| ; BRANCHCC OCCURS {||$C$L3||} ; |36| ;* --------------------------------------------------------------------------* ADD A2, A3, V9 LDRB V1, [A2, #0] ; |37| .dwpsn file "ccs.c",line 34,column 0,is_stmt LDRB V2, [V9, #0] ; |34| ;* --------------------------------------------------------------------------* ;* BEGIN LOOP ||$C$L2|| ;* ;* Loop source line : 34 ;* Loop closing brace source line : 39 ;* Loop Unroll Multiple : 2x ;* Known Minimum Trip Count : 1 ;* Known Maximum Trip Count : 536870911 ;* Known Max Trip Count Factor : 1 ;* --------------------------------------------------------------------------* ||$C$L2||: $C$DW$L$_Reverse$6$B: .dwpsn file "ccs.c",line 35,column 0,is_stmt STRB V1, [V9], #1 ; |37| STRB V2, [A2], #-1 ; |38| LDRB V1, [A2, #0] ; |37| LDRB V2, [V9, #0] ; |36| SUBS A4, A4, #1 ; |34| STRB V1, [V9], #1 ; |37| STRB V2, [A2], #-1 ; |38| LDRNEB V1, [A2, #0] ; |37| LDRNEB V2, [V9, #0] ; |34| ADD LR, LR, #2 ; |36| SUB A3, A3, #2 ; |37| .dwpsn file "ccs.c",line 39,column 0,is_stmt BNE ||$C$L2|| ; |34| ; BRANCHCC OCCURS {||$C$L2||} ; |34| $C$DW$L$_Reverse$6$E: ;* --------------------------------------------------------------------------* ||$C$L3||: TST V3, #2 LDRNEB V9, [A1, +A3] ; |37| LDMEQFD SP!, {V1, V2, V3, PC} ; BRANCHCC OCCURS {[SP, #0]} ;* --------------------------------------------------------------------------* ; Peeled loop iterations for unrolled loop: LDRB A2, [A1, +LR] ; |36| STRB V9, [A1, +LR] ; |37| STRB A2, [A1, +A3] ; |38| .dwpsn file "ccs.c",line 41,column 1,is_stmt $C$DW$3 .dwtag DW_TAG_TI_branch .dwattr $C$DW$3, DW_AT_low_pc(0x00) .dwattr $C$DW$3, DW_AT_TI_return LDMFD SP!, {V1, V2, V3, PC} ; BRANCH OCCURS {[SP, #0]}
CODE _ItoA1: ;* --------------------------------------------------------------------------* STMFD SP!, {V1, V2, V3, LR} LDR A3, $C$CON1 ; |48| .dwpsn file "ccs.c",line 46,column 0,is_stmt MOV A4, A2 ;* --------------------------------------------------------------------------* ;* BEGIN LOOP ||$C$L4|| ;* ;* Loop source line : 46 ;* Loop closing brace source line : 49 ;* Known Minimum Trip Count : 1 ;* Known Maximum Trip Count : 4294967295 ;* Known Max Trip Count Factor : 1 ;* --------------------------------------------------------------------------* ||$C$L4||: $C$DW$L$_ItoA1$2$B: .dwpsn file "ccs.c",line 47,column 0,is_stmt UMULL LR, V9, A3, A1 ; |48| MOV V9, V9, LSR #3 ; |48| SUB A1, A1, V9, LSL #3 ; |48| SUB A1, A1, V9, LSL #1 ; |48| ADD LR, A1, #48 ; |48| MOVS A1, V9 ; |50| STRB LR, [A4], #1 ; |48| MVNEQ V9, #0 ; |93| .dwpsn file "ccs.c",line 49,column 0,is_stmt BNE ||$C$L4|| ; |50| ; BRANCHCC OCCURS {||$C$L4||} ; |50| $C$DW$L$_ItoA1$2$E: ;* --------------------------------------------------------------------------* SUB A1, A2, #1 ; |94| .dwpsn file "C:/CCStudio_v3.3/tms470_4.6.2/include/string.h",line 96,column 0,is_stmt LDRB A3, [A1, #1]! ; |96| ;* --------------------------------------------------------------------------* ;* BEGIN LOOP ||$C$L5|| ;* ;* Loop source line : 96 ;* Loop closing brace source line : 96 ;* Known Minimum Trip Count : 1 ;* Known Maximum Trip Count : 4294967295 ;* Known Max Trip Count Factor : 1 ;* --------------------------------------------------------------------------* ||$C$L5||: $C$DW$L$_ItoA1$4$B: CMP A3, #0 ; |96| LDRNEB A3, [A1, #1]! ; |96| ADD V9, V9, #1 ; |96| BNE ||$C$L5|| ; |96| ; BRANCHCC OCCURS {||$C$L5||} ; |96| $C$DW$L$_ItoA1$4$E: ;* --------------------------------------------------------------------------* SUBS A3, V9, #1 ; |97| LDMLEFD SP!, {V1, V2, V3, PC} ; BRANCHCC OCCURS {[SP, #0]} ;* --------------------------------------------------------------------------* ADD V3, V9, V9, LSR #31 ; |36| CMP V9, #4 ; |36| MOV A4, V3, ASR #2 ; |36| MOV LR, #0 ; |34| MOV V9, A2 BLT ||$C$L7|| ; |36| ; BRANCHCC OCCURS {||$C$L7||} ; |36| ;* --------------------------------------------------------------------------* ADD A1, A3, V9 LDRB V1, [A1, #0] ; |37| .dwpsn file "ccs.c",line 34,column 0,is_stmt LDRB V2, [V9, #0] ; |34| ;* --------------------------------------------------------------------------* ;* BEGIN LOOP ||$C$L6|| ;* ;* Loop source line : 34 ;* Loop closing brace source line : 39 ;* Loop Unroll Multiple : 2x ;* Known Minimum Trip Count : 1 ;* Known Maximum Trip Count : 536870911 ;* Known Max Trip Count Factor : 1 ;* --------------------------------------------------------------------------* ||$C$L6||: $C$DW$L$_ItoA1$8$B: .dwpsn file "ccs.c",line 35,column 0,is_stmt STRB V1, [V9], #1 ; |37| STRB V2, [A1], #-1 ; |38| LDRB V1, [A1, #0] ; |37| LDRB V2, [V9, #0] ; |36| SUBS A4, A4, #1 ; |34| STRB V1, [V9], #1 ; |37| STRB V2, [A1], #-1 ; |38| LDRNEB V1, [A1, #0] ; |37| LDRNEB V2, [V9, #0] ; |34| ADD LR, LR, #2 ; |36| SUB A3, A3, #2 ; |37| .dwpsn file "ccs.c",line 39,column 0,is_stmt BNE ||$C$L6|| ; |34| ; BRANCHCC OCCURS {||$C$L6||} ; |34| $C$DW$L$_ItoA1$8$E: ;* --------------------------------------------------------------------------* ||$C$L7||: TST V3, #2 LDRNEB V9, [A2, +A3] ; |37| LDMEQFD SP!, {V1, V2, V3, PC} ; BRANCHCC OCCURS {[SP, #0]} ;* --------------------------------------------------------------------------* ; Peeled loop iterations for unrolled loop: LDRB A1, [A2, +LR] ; |36| STRB V9, [A2, +LR] ; |37| STRB A1, [A2, +A3] ; |38| .dwpsn file "ccs.c",line 53,column 1,is_stmt $C$DW$11 .dwtag DW_TAG_TI_branch .dwattr $C$DW$11, DW_AT_low_pc(0x00) .dwattr $C$DW$11, DW_AT_TI_return LDMFD SP!, {V1, V2, V3, PC} ; BRANCH OCCURS {[SP, #0]}
|
|
|
|
|
Jan 21 2015, 15:09
|

Местный
  
Группа: Участник
Сообщений: 329
Регистрация: 23-04-14
Пользователь №: 81 502

|
Цитата(SM @ Jan 21 2015, 15:02)  Потому, что любые переменные, не объявленные статическими, но объявленные внутри функции, располагаются на стеке, независимо от того, const они, или нет. И инициализируются динамически после вызова функции. Се ля ви, так сказать. Припадаем к источникам: http://stackoverflow.com/questions/93039/w...s-stored-in-c-cКакая разница с т.з. потребляемой RAM, если компилятор решит разместить automatic variable на стеке или такую же static в .DATA или .BSS ? В то время как const имеет больше шансов стать просто числом (по аналогии с "#define A (23)" )
|
|
|
|
|
Jan 21 2015, 15:19
|
Гуру
     
Группа: Свой
Сообщений: 7 946
Регистрация: 25-02-05
Из: Moscow, Russia
Пользователь №: 2 881

|
Цитата(CrimsonPig @ Jan 21 2015, 18:09)  Какая разница Две большие разницы. На стек надо каждый раз при входе в фунцию предопределенные данные копировать. В .data они попадают на этапе загрузки программы один раз. А в .const (или .rodata), так они, вообще могут браться прямо из флеш-памяти прямой адресацией туда. Таким образом, имеем оверхед на копирование массива констант в стек, если без static, но с const. А вот с static, и, все равно, с const или без, не имеем этого оверхеда. Причем, проверено совсем недавно тут - http://electronix.ru/forum/index.php?showtopic=125422Цитата(CrimsonPig @ Jan 21 2015, 17:53)  В то время как const имеет больше шансов стать просто числом (по аналогии с "#define A (23)" ) Давайте ближе к теме, в сторону не уходить. У нас массив, по которому проводится доступ по индексу. А не просто число.
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|