Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: (Не)доработки языков программирования
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > Программирование
Страницы: 1, 2
GetSmart
Почему не делают в ЯВУ возврат из функций несколько переменных?

Вроде бы несложно было бы объявить функцию типо так:
(int,int,char) funcname(char);
а потом аналогично использовать при вызове:
(a,b,c) = funcname('A');
причём даже в некоторых местах так:
(,,e) = funcname('A');
таким образом не используя часть переменных/регистров

То есть по сути ситуация аналогичная передаче параметров через регистры, когда (ну например в АРМ) первые 3 параметра передаются в регистрах. И возврат результата по логике строго аналогичен процессу передачи параметров, только не "в", а "из". Обычно возврат нескольких параметров делают через передачу ссылок, что в некоторой степени универсальнее, т.к. можно часть ссылок не использовать в зависимости от "нити" алгоритма. Однако, такой способ требует выделение места в стеке или в другой раме под ссылочные переменные. Что на современном уровне компиляторостроения не есть гуд. Хранение и передача (возврат) переменных в регистрах - предпочтительнее.
DpInRock
Оккам не одобряет.
Leka
Для софт-процессора с 1К "регистров" у меня результаты функции можно хранить статически, поэтому после "funcname('A')" можно использовать в выражениях(и т.п.) a.funcname ... с.funcname (и т.д. и т.п.). Минимум пересылок.
CaPpuCcino
ну, всё зависит от того, о каких ЯВУ вы говорите. т.е. утверждение собственно говоря изначально не верно, т.к. в современных языках программирования такая возможность есть (Python, Lua, Ruby...)
почему этого не было в Си? ну такая вот концепция была выбрана для этого языка далеко не самого высокого уровня, а потом унаследована Си-подобными языками, а всё потому, что не было достаточно развитых структур данных (точнее их специально старались держать попроще). с другой стороны по упомянутой мною концепции языка, функция ~ переменная, т.к. вызов функции возможен внутри выражения, т.о. если не вводить в язык достаточно абстрактные типы данных как встроенные типы, то компилятор не сможет разобрать выражение.
ну в общем примерно в этом направлении. суть такова, что те языки о которых вы думаете, не являются достаточно высокоуровневыми в нынешнем понимании, а причин, почему было сделано именно так в Си-подобных языках, достаточно много, начиная от оптимизируемости кода компилятором, заканчивая тем что это было невозможно из-за уровня развития технологии.
GetSmart
Да, я говорю о Си к примеру. Паскаль аналогично. Даже если раньше что-то мешало, то могло бы "прокатить" в новой ревизии. По поводу "функция ~ переменная" - ничего этого не мешает введению. Стандарт мог бы выбрать любой из вариантов:
1. Такой "сложный тип" не применяется в выражениях
2. В выражениях применяется первый тип, заключённый в скобках, с присутствующей переменной. Переменные в скобках могут опускаться, но не все сразу.
3. ---//--- последний тип.

По крайней мере Си достаточно мощный язык и он наверняка ещё долго будет жить.

В Паскале (старом) тоже, кстати, одна явная недороботка присутствует. Это вызов функций/процедур без скобок после имени. Минус в том, что внутри функции такой синтаксис мешает читать текущее значение функции, т.к. компилятор воспринимает обращение к имени функции как её вызов. В Делфи из-за этого ввели спец. идентификатор Result. Получилось криво ИМХО.
CaPpuCcino
Цитата(GetSmart @ Feb 22 2010, 16:46) *
Стандарт мог бы выбрать любой из вариантов

конечно, если очень захотеть, можно в космос полететь, но к сожалению история не терпит сослогательных наклонений и концепция языков того времени была выбрана именно такой. менять её кардинально не будут 1) т.к. там есть и более насущные задачи /например те же рег.выр. до сих пор не стандартизованы/ 2) и самое главное это не баг, это фича (!!!)
всех недовольных можно послать к языкам в полной мере обладающих множественным присваиванием
Dog Pawlowa
Цитата(GetSmart @ Feb 22 2010, 16:13) *
Почему не делают в ЯВУ возврат из функций несколько переменных?

Представьте себя на месте разработчиков компилятора и оптимизатора. Крыша не съедет от количества вариантов?
Вот их и пожалели. Тем более, что писал компилятор тот, кто синтаксис продумывал.
biggrin.gif
zltigo
Цитата(GetSmart @ Feb 22 2010, 15:13) *
Однако, такой способ требует выделение места в стеке или в другой раме под ссылочные переменные.

Совершенно не обязательно, если компилятор умеет параметры передавать в регистрах, то и ссылка соответственно попадает в регистр и получаете именно то, что хотели. В плюсах, конечно, хотя и поскрипев мозгами и сишный оптимизатор может теоретически разобраться.
При inline функции глобальные по отношению к функции переменные с ограниченной областью видимости будут с большой вероятностью в регистрах и получим желаемый Вами эффект.
А вообще за много лет программирования, как-то ни разу не пришлось возжелать того, что Вы хотите. Наверное, я что-то делаю не так smile.gif
GetSmart
Цитата(zltigo @ Feb 22 2010, 19:45) *
.. то и ссылка соответственно попадает в регистр и получаете именно то, что хотели.

Это только половина "зла". Переменная всё равно будет нах-ся в раме. Универсальную ссылку на регистр ещё не придумали biggrin.gif
Хотя в AVR8 такое можно "провернуть", но это будет для компиляторописателя экстрим покруче того, что я предлагаю.

Цитата
Наверное, я что-то делаю не так

Вы всегда и всё делаете не так. biggrin.gif Меня это не удивляет.

CaPpuCcino, но ведь дакой синтаксис не отменяет ничего уже существующего. Он только расширяет и ничему не мешает. Why not?
CaPpuCcino
Цитата(GetSmart @ Feb 22 2010, 18:02) *
Why not?

да, я ж говорю, что это возможно, но это не вероятно, т.к. при выходе из своей концепции это будет уже другой язык. и потом ведь множественной присваивание это всего лишь мнемоника. возьмите и в пределах того же С++ опишите соответствующий объект и переопределите правила оперирования с ним и будет вам то же самое O1=O2(х1,х2,х3) с возвратом целого списка аргументов и приведением к какому-то одному правилу, если объект стоящий справа "одномерный"
Leka
"...доработки языков программирования, которые хотели ли бы вы"
- чтобы оптимизирующий компилятор для любой(в т.ч. будущей) архитектуры можно было создать за "пару человеко-вечеров". И чтобы на нем описывались алгоритмы, а не обходы узких мест существующих архитектур.
zltigo
Цитата(GetSmart @ Feb 22 2010, 18:02) *
Это только половина "зла". Переменная всё равно будет нах-ся в раме. Универсальную ссылку на регистр ещё не придумали biggrin.gif

Если Вы пытаетесь рассказывать о 'C', то там передачи параметров по ссылке нет. Совсем нет. Ибо указатель это НЕ ссылка. А в плюсах есть передача параметров по ссылке и посему "придумывать" уже не надо. В обычном 'C', как уже писал, дело сложнее, но принципиальная возможность передать функции не модифицирующей указатель в регистре вместо указателя на int в регистре сам int есть.
GetSmart
Цитата(zltigo @ Feb 22 2010, 21:48) *
1. Если Вы пытаетесь рассказывать о 'C', то там передачи параметров по ссылке нет.
2.В обычном 'C', как уже писал, дело сложнее, но принципиальная возможность передать функции не модифицирующей указатель в регистре вместо указателя на int в регистре сам int есть.

1. Можно сказать, что я перепутал ссылку с указателем. Указатель
2. Не понял что это.
--------------------------
Ещё бы допускалось в командах break и continue (кстати, одинаковые для Си и Паскаля) указывать параметр вложенности = 1 по умолчанию. Тоже ничему не противоречит и не мешает.
zltigo
Цитата(GetSmart @ Feb 22 2010, 20:47) *
Ещё бы допускалось в командах break и continue (кстати, одинаковые для Си и Паскаля) указывать параметр вложенности = 1 по умолчанию. Тоже ничему не противоречит и не мешает.

Аппологет вредности goto smile.gif. Пользуйте и будет счастье. А уровень вложенности глупейшая задумка, криво реализуемая и потворствующая качественным ошибкам при правке кода.
SasaVitebsk
Честно говоря, тоже не понимаю зачем это надо. Как то тоже не возникало необходимости.

Единственное, что я пользовал в Pascal, а в С этого нет - так это вложенные процедуры.
Типа:
Код
void a(void)
{
  integer i,j;

  void b(void)
  {
  }
}

Смысл, что переменные i,j являются видимыми для b и локальными для остальных.

Раньше, мне казалось, это существенным ограничением. Теперь, посмотрев как компилятор работает с переменными, вижу что концепция C, в принципе как раз верна.

==========================
Давайте глубже посмотрим на Вашу претензию. Например ч/з призму того же AVR.
Итак допустим у нас есть такая возможность. Как компилятор раскрутит. Фактически обращение к параметрам больше 2 будет осуществляться косвенно. Иными словами не быстрее, чем при обращении к статическим переменным. А в ряде случаев медленнее.
Так зачем этот прикол? Просто для простоты оформления/написания, для абстрактности? Так для этого имеются средства в виде интегральных типов, в том числе объектов и структур.

По моему в рамках языка, существует куча способов свободно "выразится". На мой взгляд, итак языки перегружены понятиями и возможностями. И процесс продолжается.
Xenia
Отчего бы не помечтать smile.gif
Тогда я и свою мечто озвучу. Хочу... оператор сразу на две квадратные скобочки smile.gif, например, вот такой:
double operator [][]( int i, int j);
чтобы с матрицами стало удобно работать. Чтобы определив матрицу в виде объекта (создав ей кроме двумерного массива еще габариты, тип и прочее), можно было доставать из ее числа обычным способом, как Mat[i][j]. Для линейного объекта оператор [] решает все проблемы, а на двемерном случае это не работает, т.к. продукт оператора [] должен быть указателем, чтобы вторые скобочки сработали.
Можно конечно исхитриться, создав промеждуточный класс, указатель на который возвращает оператор [], а в том классе снова переопределить оператор [], но тогда управление перейдет в промежуточный класс, а не в исходный.
На худой случай можно было разрешить оператору [] иметь несколько аргументов, например:
double operator []( int i, int j, int k);
Кстати такое определение которые компиляторы кушают без ошибки. Однако тут подразумевается, что станут возможны выражения типа:
Mat[i, j, k]
что для C++ слишком непривычно.
ReAl
Цитата(zltigo @ Feb 22 2010, 20:46) *
А уровень вложенности глупейшая задумка, криво реализуемая и потворствующая качественным ошибкам при правке кода.
+1
Замахаешься потом править уровни в случае чего.
Единственный приемлемый вариант - именованные блоки кода (break без имени - из ближайшего) - что-то в духе
Код
    for(;; ) : mainloop {
        int i = 8;
        do : bitloop {
              while( aaa ) {
                  if( bbb )
                      break mainloop;
              }
              if( ccc )
                   break bitloop;                  
        } while(--i);
    }
vmp
Цитата(GetSmart @ Feb 22 2010, 15:13) *
Почему не делают в ЯВУ возврат из функций несколько переменных?

Вроде бы несложно было бы объявить функцию типо так:
(int,int,char) funcname(char);


Хмм... А чем вас возврат функцией структуры не устраивает?
Код
typedef struct {
int a;
char b;
char c;
} T_S3;

T_S3 s3func(int i)
{
T_S3 s3;
s3.a = i+1;
s3.b = i+2;
s3.c = i+3;
return s3;
}

int test3(void)
{
int i;
i = s3func(1).a;
return s3func(i).b;
}


Листинг от IAR ARM 5.2
CODE
\ In section .text, align 4, keep-with-next
1325 T_S3 s3func(int i)
1326 {
\ s3func:
\ 00000000 0200 MOVS R2,R0
\ 00000002 82B0 SUB SP,SP,#+8
1327 T_S3 s3;
1328 s3.a = i+1;
\ 00000004 481C ADDS R0,R1,#+1
\ 00000006 0090 STR R0,[SP, #+0]
1329 s3.b = i+2;
\ 00000008 881C ADDS R0,R1,#+2
\ 0000000A 6B46 MOV R3,SP
\ 0000000C 1871 STRB R0,[R3, #+4]
1330 s3.c = i+3;
\ 0000000E C91C ADDS R1,R1,#+3
\ 00000010 6846 MOV R0,SP
\ 00000012 4171 STRB R1,[R0, #+5]
1331 return s3;
\ 00000014 03C8 LDM R0!,{R0,R1}
\ 00000016 02B0 ADD SP,SP,#+8
\ 00000018 03C2 STM R2!,{R0,R1}
\ 0000001A 7047 BX LR ;; return
1332 }
1333

\ In section .text, align 4, keep-with-next
1334 int test3(void)
1335 {
\ test3:
\ 00000000 00B5 PUSH {LR}
\ 00000002 83B0 SUB SP,SP,#+12
1336 int i;
1337 i = s3func(1).a;
\ 00000004 0121 MOVS R1,#+1
\ 00000006 6846 MOV R0,SP
\ 00000008 ........ BL s3func
\ 0000000C 0099 LDR R1,[SP, #+0]
1338 return s3func(i).b;
\ 0000000E 6846 MOV R0,SP
\ 00000010 ........ BL s3func
\ 00000014 6846 MOV R0,SP
\ 00000016 0079 LDRB R0,[R0, #+4]
\ 00000018 03B0 ADD SP,SP,#+12
\ 0000001A 00BD POP {PC} ;; return
1339 }
_Pasha
Я бы хотел, чтоб в сях(да и паскале тоже) наконец-то исчез бардак в типе результата целочисленного умножения. Т.е. результат mul16x16 по умолчанию все же 32-битный должен быть, а 8*8 16-битный. Мы же все-таки в реальном мире находимся?
И чтобы препроцессор был рискованно рекурсивным biggrin.gif
Цитата
в командах break и continue (кстати, одинаковые для Си и Паскаля)

Нифига они не одинаковые изначально. В паскале это intrinsic procedures.
sigmaN
Сэр, по-моему у вас возникают дурные мысли по причине кризисного положения и недостатка реальной работы smile.gif

Ну а по теме если: как и многие отписавшиеся, я не вижу ни надобности ни реального профита от задействования идей, предложенных Вами.
Но моё мнение так...мало что значит...программерская моя практика не так уж и велика....

Про структуру тоже хотел напомнить. Опередили smile.gif
_Pasha
В принципе, было бы на 100% эффективным введение средств для задания идиоматических выражений (звучит смешно, вспоминая русский язык). Это, извините, не кривой плюсовый operator, а реальное средство, ускоряющее развитие оптимизаторов.
AlexandrY
LUA может возвращать переменные пачками.
http://www.lua.ru/doc/

LUA самый пожалуй удобный движок для портирования на микроконтроллеры. Занимает всего 100K памяти вместе с компилятором.

M-язык в среде MATLAB (тож можно exe-шники создавать на нем) возвращает переменные любыми способами.

Идея стара как мир.

А общее мнение таково: удобнее делать надо не языки, а средства разработки.

Совершенствовать броузинг кода и средства рефакторинга.
Языки же надо расширять стандартными общепринятыми либами и средствами генерации произвольных представлений.
Так чтобы был возможен автоматический ремапинг из одного языка в другой как это продвигает Microsoft в .NET технологии.
GetSmart
vmp, это то же самое как и передавать указатель на структуру в качестве параметра функции. Код будет 100% одинаковым. Переменнаяя/результат будет располагаться в стеке. Но т.к. современные компиляторы (сами) стараются располагать переменные в регистрах, то вместо этого устаревшего варианта возврата результата через стек пора бы уже вводить возврат результата (множественного) через регистры. Раньше было рано, а теперь в самый раз smile.gif
dxp
Цитата(GetSmart @ Feb 24 2010, 15:20) *
vmp, это то же самое как и передавать указатель на структуру в качестве параметра функции. Код будет 100% одинаковым. Переменнаяя/результат будет располагаться в стеке.

Не факт. Структура по семантике языка возвращается по значению. Как на самом деле реализуется, зависит от платформы, тут надо смотреть доку на конкретную платформу. Например, у Blackfin/VDSP по поводу структур сказано следующее:

Return Values

•For functions returning aggregate values occupying fewer than or
equal to 32 bits, the result is returned in R0.

•For aggregate values occupying greater than 32 bits, and fewer than
or equal to 64 bits, the result is returned in register pair R0, R1.

•For functions returning aggregate values occupying more than 64
bits, the caller allocates the return value object on the stack and the
address of this object is passed to the callee as a hidden argument in
register P0.

И примеры приведены:

Код
---------------------------------------------------------------------------------
Function Prototype    |  Parameters Passed as   |    Return Location
---------------------------------------------------------------------------------
struct s2 {           |          a in R0,       |        in R0 (s.t and s.u)
char t;               |          b in R1,       |        and in R1 (s.v)    
char u;               |          c in R2        |
int v;                |                         |
}                     |                         |
                      |                         |
struct s2 test(int a, |                         |
int b, int c)         |                         |
---------------------------------------------------------------------------------
struct s3 {           |        a in R0,         |     in *P0 (based on value
char t;               |        b in R1,         |     of P0 at the call, not
char u;               |        c in R2          |     necessarily at the    
int v;                |                         |     return)                
int w;                |                         |
}                     |                         |
                      |                         |
struct s3 test(int a, |                         |
int b, int c)         |                         |
---------------------------------------------------------------------------------


Цитата(GetSmart @ Feb 24 2010, 15:20) *
Но т.к. современные компиляторы (сами) стараются располагать переменные в регистрах, то вместо этого устаревшего варианта возврата результата через стек пора бы уже вводить возврат результата (множественного) через регистры. Раньше было рано, а теперь в самый раз smile.gif

Это всегда было и было отдано на откуп реализации. А если структура не лезет в регистры, то тут никакие новые правила языка не помогут - все равно будет передавать через память.
_Pasha
Цитата(GetSmart @ Feb 24 2010, 12:20) *
Переменнаяя/результат будет располагаться в стеке.

avr-gcc возвращает структуру, располагая ее в регистрах согласно calling conventions, либо на стеке, если она не вмещается.
GetSmart
Структура - структурой. А я предлагаю "симметрию" в описании параметров и результата функции. Чем не фича? ИМХО красивый концепт получается.
GetSmart
Ещё недоработку обнаружил. Volatile.

Этот квалификатор действует глобально на всю прогу и заставляет компилятор не оптимизировать переменную. Используется обычно тогда, когда в разных тредах, равно как и в программе+прерывании используется переменная. Но. Когда в программе юзается эта переменная, то она конечно может измениться и оптимизировать её не надо. Но когда в прерывании она юзается, то там было бы оптимальным снимать этот квалификатор. Но вроде бы это не предусмотрено. (?)
vitan
Цитата(GetSmart @ Feb 22 2010, 16:13) *
Почему не делают в ЯВУ возврат из функций несколько переменных?

Вроде бы несложно было бы объявить функцию типо так:
(int,int,char) funcname(char);
а потом аналогично использовать при вызове:
(a,b,c) = funcname('A');
причём даже в некоторых местах так:
(,,e) = funcname('A');

Возможно, немного не по теме, но, например, в AHDL (тоже язык высокого уровня) это возможно. Только синтаксис немного другой, но суть та же.
Так что - смотря о каких языках речь...
_Pasha
Цитата(GetSmart @ Jan 28 2012, 08:29) *
Но вроде бы это не предусмотрено. (?)

Код
volatile int some;
int *someptr = &some;
*someptr += 2;

Ы?
toweroff
Цитата(GetSmart @ Jan 28 2012, 09:29) *
Ещё недоработку обнаружил. Volatile.

Этот квалификатор действует глобально на всю прогу и заставляет компилятор не оптимизировать переменную. Используется обычно тогда, когда в разных тредах, равно как и в программе+прерывании используется переменная. Но. Когда в программе юзается эта переменная, то она конечно может измениться и оптимизировать её не надо. Но когда в прерывании она юзается, то там было бы оптимальным снимать этот квалификатор. Но вроде бы это не предусмотрено. (?)

а если прерывание вложенное?
sonycman
Цитата(GetSmart @ Jan 28 2012, 09:29) *
Ещё недоработку обнаружил. Volatile.

Этот квалификатор действует глобально на всю прогу и заставляет компилятор не оптимизировать переменную. Используется обычно тогда, когда в разных тредах, равно как и в программе+прерывании используется переменная. Но. Когда в программе юзается эта переменная, то она конечно может измениться и оптимизировать её не надо. Но когда в прерывании она юзается, то там было бы оптимальным снимать этот квалификатор. Но вроде бы это не предусмотрено. (?)

А если обработчики прерываний вынести в отдельный файл, там объявить необходимую переменную int val, а в другие файлы добавить эту переменную как extern volatile int val?
В результате обработчики прерываний будут работать с оптимизированной переменной, а вся остальная прога - с volatile.
Сергей Борщ
QUOTE (sonycman @ Jan 28 2012, 15:44) *
А если обработчики прерываний вынести в отдельный файл,
Как-то слишком сложно. _Pasha правильно предложил - завести временную переменную (только не указатель, на Пашин пример будет справедливо ругаться, ибо указатель должен быть на volatile), когда надо считывать в эту переменную, проводить с ней вычисления и когда надо записывать обратно в volatile-переменную. Лишь только программист в состоянии определить, когда наступает этот момент "когда надо". Ни один компилятор угадать его не сможет.
sasamy
Цитата(SasaVitebsk @ Feb 23 2010, 00:12) *
Единственное, что я пользовал в Pascal, а в С этого нет - так это вложенные процедуры.


Если очень хочется - в gcc есть расширение
http://gcc.gnu.org/onlinedocs/gcc/Nested-Functions.html

хотя наверно вы знаете. На практике - я не встречал чтобы этим кто-то пользовался.
GetSmart
Цитата(Сергей Борщ @ Jan 28 2012, 19:37) *
Лишь только программист в состоянии определить, когда наступает этот момент "когда надо". Ни один компилятор угадать его не сможет.

Это почему?
Внутри прерывания переменную можно оптимизировать как угодно. Не важно, вложенное оно или нет и есть ли другие прерывания c таким же или меньшим приоритетом, юзающие эту переменную. В идеале лучше задавать (отменять volatile) каким-то квалификатором внутри какой-то зоны видимости, будь то обработчик или {}.

Вручную копировать volatile в простую переменную, которую потом юзать не есть хорошо. Т.к. переменная volatile, то она сразу будет скопирована куда-то и отнимать место там (рег/рама). В конце обработчика та же беда. С указателем (вариант Паши) чем-то лучше, чем-то хуже. Как именно, зависит от компилятора по части разных методов оптимизации указателей и значений переменных. Указатель придётся грубо приводить к обычной переменной, но и фиг с ним.

=================================

Ещё одну недоработку родил. Хотя, может есть вариант прямого обхода, а не через переменную.

Когда в выражении юзаются две или более volatile, то компилер выдаёт варнинг, что "доступ к volatile не определён (не обозначен?) в выражении". Не очень понятно, как он расчитывает чтобы я его обозначил. Но можно было бы например задать скобками. Бувквально так ggg = abc + (volvar1) + volvar2; Тогда уровень вложенности скобок для volatile будет задавать приоритет доступа. Чем больше скобок, тем раньше доступ. При равном количестве - варнинг, означающий что реализация вычисления на откуп компилятора.

У меня такая ситуация происходит при сравнении (вне прерывания) volatile переменной временнОй метки и значения таймера, когда прерывание может изменить значение этой временнОй метки. При этом обязательно временнУю метку нужно прочитать раньше значения таймера, если произойдёт наоборот, то временнАя метка может "обогнать" значение из таймера, что вери вери бэд. Щас сделано через врЕменную переменную. Но из-за этого компилятор её суёт в стек (ИАР MCS-51). Upd. Хотя вот тут щас уже не суёт, но это не принципиально.
_Ivana
А мне бы хотелось вот какую доработку - чтобы написать в редакторе прямо русскими словами "Уважаемый компилятор с оптимизатором, сделай мне хороший, быстрый и правильно работающий код" - и он бы сам все сделал rolleyes.gif

ЗЫ МК всегда все делает "правильно", честно бежит по РИСК или ЦИСК командам и выполняет их. И если результат не нравится разработчику, то пусть ищет свои ошибки. А если он (разработчик) не опускается до asm, а пишет на ЯВУ (наяву - каламбурчик rolleyes.gif ), то вдобавок к логике необходимо знать все тонкости и особенности компилятора вплоть до индивидуальных багов/фичей используемой версии. Это в принципе непросто, вот поэтому и получается типа "пишу одно а он мне делает не так". Закон Джоэла Спольски - все нетривиальные абстракции дырявы rolleyes.gif
Вот тут http://electronix.ru/forum/index.php?showtopic=95060 я безуспешно пытался многабуквенно это имховыражать.
_Pasha
Цитата(GetSmart @ Jan 29 2012, 05:42) *
Чем больше скобок, тем раньше доступ. При равном количестве - варнинг, означающий что реализация вычисления на откуп компилятора.

Дык, слева направо! laughing.gif И при этом CSE идёт лесом.

Цитата(_Ivana @ Jan 29 2012, 13:03) *
Вот тут http://electronix.ru/forum/index.php?showtopic=95060 я безуспешно пытался многабуквенно это имховыражать.

Так Вы спрашивайте! В определенный период каждый первый страдает подобным.
Кстати, при изучении любого вопроса имхо полезно "в пику" создавать свой вариант решения.
Для облегчения понимания, прежде всего.
GetSmart
Цитата(_Pasha @ Jan 29 2012, 16:42) *
Дык, слева направо! laughing.gif И при этом CSE идёт лесом.

А мне скобки больше нравятся. Больше гибкость.
Мне например будет не нравиться такая штука
time = -stamp+timer;
чтобы временнАя метка прочиталась раньше.

Причём скобки можно оптимизировать как обычно, удаляя лишние, но при разборе выражения для волатилов запоминать уровень.
sigmaN
Я тут про прерывания подумал...
В стандарте языка они не определены и являются расширением конкретного компилятора, который всё-же должен следовать стандарту. И если сказано, что volatile пишется/читается всегда - он должен это делать.
Тем более, предложенная вами оптимизация может приводить и к негативным последствиям.
К примеру у меня регистр какой-нибудь переферии определен как volatile. И вот я его в прерывании читаю,пишу, а он мне берет всё это оптимизирует и только перед выходом записывает. Аналогично и считывает только один раз. А у меня в это время по UART байтик пришел. Как я его увижу, если всё соптимизировано )
Тогда получится нужно ещё и вводить типа super volatile который в прерываниях уже не оптимизируется ))

Ну т.е. сомнительная такая оптимизация получается.
GetSmart
Цитата(_Pasha @ Jan 28 2012, 14:00) *
Код
volatile int some;
int *someptr = &some;
*someptr += 2;

Ы?

Внезапно обнаружил такую вещь.
Код
volatile int *someptr;        // компилятор может запросто оптимизируя удалить присванивание этой переменной

int *volatile someptr;        // а этой компилятор не удалит

Вобщем это и понятно.
Но тогда вопрос к знатокам: если в самом начале строки с объявлением переменной будет "static", то всегда ли это (вне функций допустим) будет означать видимость переменной внутри модуля, или в первом случае (как и действие volatile) квалификатор будет засчитан к объекту, на который ссылается переменная, а не к самой переменной?
Alex-sh
Добрый вечер. Я знаю что мой вопрос несколько не в тему, поэтому заранее извеняюсь. Подскажите пожалуйста кто может помочь в написании программ на Ассемблере для микроконтроллеров PIC и MCS. Вот пример одного из заданий. Составить алгоритм и программу на языке Ассемблер для МП типа MCS –51, выполняющую логическое умножение содержимого порта Р1 и аккумулятора, в случае равенства результата нулю, устанавливающую в единицу флаг 22h. Для знающего человека это пара минут, а для меня полный мрак и даже хуже. Помогите, кто чем сможет!!!
ReAl
Цитата(Сергей Борщ @ Jan 28 2012, 16:37) *
Лишь только программист в состоянии определить, когда наступает этот момент "когда надо". Ни один компилятор угадать его не сможет.
Компилятору можно попробовать объяснить областями видимости, кешировать нужные переменные в нужных блоках кода, запись назад при выходе кеша из области видимости:
http://electronix.ru/forum/index.php?showt...mp;#entry535341

А вообще — разве не так?
Код
class foo {
public:
    state_t get_state() volatile // volatile переехало сюда -- для пользователей класса
    {
        return state; // ну при sizeof(state_t) > sizeof(sig_atomic_t) ещё заворачивать в крит. секцию
    }
private:
    state_t state; // не-volatile для обработчика прерываний
    INLINE void isr(); // обработчик прерываний топчется по state как хочет
};
GetSmart
Цитата(ReAl @ Mar 7 2012, 11:58) *
А вообще — разве не так?
...

А паблик волатил запись не нужна?
ReAl
Не понял вопрос.
Какая запись и где должна быть нужна. Имеется ввиду очередная собака - "сеттер"? (Витус Вагнер недавно говорил о том, что геттеры надо бы ретриверами называть, вместе с сеттерами и пойнтерами отличная псарня была бы)
Так пример короткий для общего понимания, setter-функция часто и не нужна.
_Pasha
До кучи
GetSmart
Цитата(_Pasha @ Mar 9 2012, 12:46) *
До кучи

Ну вот. И эти товарищи встали на грабли. На самом деле из двух объявлений, только одно объявление волатильной переменной. Второе объявление есть объявление обычной переменной - указателя на волатильную.
GetSmart
Хотел красиво оптимизировать Си-код, выполняющий общие действия для сложносоставного условия-алгоритма, содержащего в себе вызов void-функций между несколькими булевыми выражениями внутри if-условия. Чтобы обходиться без goto или дублирования исполняемого выражения (тела) if.
Код
void foo1(int);
...

void foo2(void);
...


int main()
{
    .....
    if (expr1) goto do_foo2;
    foo1(a);
    if (expr2) {
    do_foo2:
        foo2();
    }
    .....
}


Получилось так
Код
{
    if (expr1 || (foo1(a), expr2)) {
        foo2();
    }
}


Но понял, что разработчик неудачно выбрал оператор/символ для функции Comma. Удачнее было бы нагрузить двоеточие этой функцией. А запятая оставалась бы только разделителем множества элементов. С двоеточием появились бы новые плюшки. Например, внутри первого выражения в for в режиме C99 можно было бы создавать несколько разнотипных переменных. И некрасивое do {....} while(0) в дефайнах не понадобилось бы, т.к. двоеточием можно было бы "склеить" несколько независимых выражений/действий, выполняющихся строго вместе. И, если пофантазировать, то в режиме C2100 можно было бы создавать (локальные) переменные внутри многих мест, где пока это запрещено. Например внутри условных выражений if, while, прочих, с ограничением области видимости переменной только внутри границ ключевого слова (if, while,...).

И ещё, касательно unions. Бросается в глаза удобство варианта, когда при описании членов union, массив, а так же список однотипных членов, разделённых запятой, делаются по логике создания структуры. То есть это будут члены/переменные, следующие в адресном пространстве друг за другом. И только после точки с запятой адрес следущего члена обнуляется.
iiv
Цитата(SasaVitebsk @ Feb 23 2010, 01:12) *
Единственное, что я пользовал в Pascal, а в С этого нет - так это вложенные процедуры.


в GNU-C это есть где-то с 1999 года, ужасно удобно, так как пространство имен вспомогательных вложенных функций и вспомогательных переменных не засоряется, но в ISO стандарт так и не попало, посему GNU поддерживает это на общественных началах, и, как я понимаю, не на всех архитектурах.

Конечно можно возразить, что де пиши на С++, но там аналогичный код становится достаточно большим, поэтому если вам платят не за число строк, а за результат, то вложенные С-шные функции - крайне полезная конструкция.
sigmaN
bb-offtopic.gif
Цитата
что де пиши на С++, но там аналогичный код становится достаточно большим,
Нда, шел 2017год, а наш народ по прежнему рассказывал, как на с++ код становится достаточно большим..... Грустно sad.gif
ar__systems
Цитата(GetSmart @ Apr 13 2017, 11:08) *
Хотел красиво оптимизировать Си-код,
Код
    if (expr1) goto do_foo2;
    foo1(a);
    if (expr2) {
    do_foo2:
        foo2();
    }
    
}


Получилось так
Код
{
    if (expr1 || (foo1(a), expr2)) {
        foo2();
    }
}

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

Код
if ( ! expr1 )
    foo1();
if ( expr1 || expr2 )
    foo2();


Зачем мудрить-то?
Эдди
Цитата(iiv @ Apr 29 2017, 18:19) *
в GNU-C это есть где-то с 1999 года

В gcc5 это посчитали вредным, поэтому в опции компилятора теперь нужно добавлять -Wno-trampoline, иначе не соберется (я всегда указываю -Wall -Wextra, чтобы не было соблазна игнорировать предупреждения).
А вот что мне не нравится, так это работа с сокетами! Ну никак не обойтись без таймаутов...
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2024 Invision Power Services, Inc.