реклама на сайте
подробности

 
 
> (Не)доработки языков программирования, которые хотели ли бы вы
GetSmart
сообщение Feb 22 2010, 12:13
Сообщение #1


.
******

Группа: Участник
Сообщений: 4 005
Регистрация: 3-05-06
Из: Россия
Пользователь №: 16 753



Почему не делают в ЯВУ возврат из функций несколько переменных?

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

То есть по сути ситуация аналогичная передаче параметров через регистры, когда (ну например в АРМ) первые 3 параметра передаются в регистрах. И возврат результата по логике строго аналогичен процессу передачи параметров, только не "в", а "из". Обычно возврат нескольких параметров делают через передачу ссылок, что в некоторой степени универсальнее, т.к. можно часть ссылок не использовать в зависимости от "нити" алгоритма. Однако, такой способ требует выделение места в стеке или в другой раме под ссылочные переменные. Что на современном уровне компиляторостроения не есть гуд. Хранение и передача (возврат) переменных в регистрах - предпочтительнее.

Сообщение отредактировал Omen_13 - Feb 22 2010, 14:14
Причина редактирования: Тема переименованна по просьбе автора


--------------------
Заблуждаться - Ваше законное право :-)
Go to the top of the page
 
+Quote Post
7 страниц V   1 2 3 > »   
Start new topic
Ответов (1 - 90)
DpInRock
сообщение Feb 22 2010, 12:25
Сообщение #2


Гуру
******

Группа: Участник
Сообщений: 2 254
Регистрация: 4-05-07
Из: Moscow
Пользователь №: 27 515



Оккам не одобряет.


--------------------
On the road again (Canned Heat)
Go to the top of the page
 
+Quote Post
Leka
сообщение Feb 22 2010, 12:56
Сообщение #3


Профессионал
*****

Группа: Участник
Сообщений: 1 075
Регистрация: 30-09-05
Пользователь №: 9 118



Для софт-процессора с 1К "регистров" у меня результаты функции можно хранить статически, поэтому после "funcname('A')" можно использовать в выражениях(и т.п.) a.funcname ... с.funcname (и т.д. и т.п.). Минимум пересылок.
Go to the top of the page
 
+Quote Post
CaPpuCcino
сообщение Feb 22 2010, 13:25
Сообщение #4


тоже уже Гуру
******

Группа: Свой
Сообщений: 2 047
Регистрация: 13-06-05
Из: Кёлн - Санкт-Петербург
Пользователь №: 5 973



ну, всё зависит от того, о каких ЯВУ вы говорите. т.е. утверждение собственно говоря изначально не верно, т.к. в современных языках программирования такая возможность есть (Python, Lua, Ruby...)
почему этого не было в Си? ну такая вот концепция была выбрана для этого языка далеко не самого высокого уровня, а потом унаследована Си-подобными языками, а всё потому, что не было достаточно развитых структур данных (точнее их специально старались держать попроще). с другой стороны по упомянутой мною концепции языка, функция ~ переменная, т.к. вызов функции возможен внутри выражения, т.о. если не вводить в язык достаточно абстрактные типы данных как встроенные типы, то компилятор не сможет разобрать выражение.
ну в общем примерно в этом направлении. суть такова, что те языки о которых вы думаете, не являются достаточно высокоуровневыми в нынешнем понимании, а причин, почему было сделано именно так в Си-подобных языках, достаточно много, начиная от оптимизируемости кода компилятором, заканчивая тем что это было невозможно из-за уровня развития технологии.


--------------------
И снова на арене цирка - дрессированные клоуны!! Оказываем консультации по электронике за симпу круглосуточно.
Go to the top of the page
 
+Quote Post
GetSmart
сообщение Feb 22 2010, 13:46
Сообщение #5


.
******

Группа: Участник
Сообщений: 4 005
Регистрация: 3-05-06
Из: Россия
Пользователь №: 16 753



Да, я говорю о Си к примеру. Паскаль аналогично. Даже если раньше что-то мешало, то могло бы "прокатить" в новой ревизии. По поводу "функция ~ переменная" - ничего этого не мешает введению. Стандарт мог бы выбрать любой из вариантов:
1. Такой "сложный тип" не применяется в выражениях
2. В выражениях применяется первый тип, заключённый в скобках, с присутствующей переменной. Переменные в скобках могут опускаться, но не все сразу.
3. ---//--- последний тип.

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

В Паскале (старом) тоже, кстати, одна явная недороботка присутствует. Это вызов функций/процедур без скобок после имени. Минус в том, что внутри функции такой синтаксис мешает читать текущее значение функции, т.к. компилятор воспринимает обращение к имени функции как её вызов. В Делфи из-за этого ввели спец. идентификатор Result. Получилось криво ИМХО.


--------------------
Заблуждаться - Ваше законное право :-)
Go to the top of the page
 
+Quote Post
CaPpuCcino
сообщение Feb 22 2010, 14:40
Сообщение #6


тоже уже Гуру
******

Группа: Свой
Сообщений: 2 047
Регистрация: 13-06-05
Из: Кёлн - Санкт-Петербург
Пользователь №: 5 973



Цитата(GetSmart @ Feb 22 2010, 16:46) *
Стандарт мог бы выбрать любой из вариантов

конечно, если очень захотеть, можно в космос полететь, но к сожалению история не терпит сослогательных наклонений и концепция языков того времени была выбрана именно такой. менять её кардинально не будут 1) т.к. там есть и более насущные задачи /например те же рег.выр. до сих пор не стандартизованы/ 2) и самое главное это не баг, это фича (!!!)
всех недовольных можно послать к языкам в полной мере обладающих множественным присваиванием


--------------------
И снова на арене цирка - дрессированные клоуны!! Оказываем консультации по электронике за симпу круглосуточно.
Go to the top of the page
 
+Quote Post
Dog Pawlowa
сообщение Feb 22 2010, 14:45
Сообщение #7


Гуру
******

Группа: Свой
Сообщений: 2 702
Регистрация: 14-07-06
Пользователь №: 18 823



Цитата(GetSmart @ Feb 22 2010, 16:13) *
Почему не делают в ЯВУ возврат из функций несколько переменных?

Представьте себя на месте разработчиков компилятора и оптимизатора. Крыша не съедет от количества вариантов?
Вот их и пожалели. Тем более, что писал компилятор тот, кто синтаксис продумывал.
biggrin.gif


--------------------
Уходя, оставьте свет...
Go to the top of the page
 
+Quote Post
zltigo
сообщение Feb 22 2010, 14:45
Сообщение #8


Гуру
******

Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244



Цитата(GetSmart @ Feb 22 2010, 15:13) *
Однако, такой способ требует выделение места в стеке или в другой раме под ссылочные переменные.

Совершенно не обязательно, если компилятор умеет параметры передавать в регистрах, то и ссылка соответственно попадает в регистр и получаете именно то, что хотели. В плюсах, конечно, хотя и поскрипев мозгами и сишный оптимизатор может теоретически разобраться.
При inline функции глобальные по отношению к функции переменные с ограниченной областью видимости будут с большой вероятностью в регистрах и получим желаемый Вами эффект.
А вообще за много лет программирования, как-то ни разу не пришлось возжелать того, что Вы хотите. Наверное, я что-то делаю не так smile.gif


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
GetSmart
сообщение Feb 22 2010, 15:02
Сообщение #9


.
******

Группа: Участник
Сообщений: 4 005
Регистрация: 3-05-06
Из: Россия
Пользователь №: 16 753



Цитата(zltigo @ Feb 22 2010, 19:45) *
.. то и ссылка соответственно попадает в регистр и получаете именно то, что хотели.

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

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

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

CaPpuCcino, но ведь дакой синтаксис не отменяет ничего уже существующего. Он только расширяет и ничему не мешает. Why not?

Сообщение отредактировал GetSmart - Feb 22 2010, 15:03


--------------------
Заблуждаться - Ваше законное право :-)
Go to the top of the page
 
+Quote Post
CaPpuCcino
сообщение Feb 22 2010, 15:28
Сообщение #10


тоже уже Гуру
******

Группа: Свой
Сообщений: 2 047
Регистрация: 13-06-05
Из: Кёлн - Санкт-Петербург
Пользователь №: 5 973



Цитата(GetSmart @ Feb 22 2010, 18:02) *
Why not?

да, я ж говорю, что это возможно, но это не вероятно, т.к. при выходе из своей концепции это будет уже другой язык. и потом ведь множественной присваивание это всего лишь мнемоника. возьмите и в пределах того же С++ опишите соответствующий объект и переопределите правила оперирования с ним и будет вам то же самое O1=O2(х1,х2,х3) с возвратом целого списка аргументов и приведением к какому-то одному правилу, если объект стоящий справа "одномерный"


--------------------
И снова на арене цирка - дрессированные клоуны!! Оказываем консультации по электронике за симпу круглосуточно.
Go to the top of the page
 
+Quote Post
Leka
сообщение Feb 22 2010, 15:37
Сообщение #11


Профессионал
*****

Группа: Участник
Сообщений: 1 075
Регистрация: 30-09-05
Пользователь №: 9 118



"...доработки языков программирования, которые хотели ли бы вы"
- чтобы оптимизирующий компилятор для любой(в т.ч. будущей) архитектуры можно было создать за "пару человеко-вечеров". И чтобы на нем описывались алгоритмы, а не обходы узких мест существующих архитектур.
Go to the top of the page
 
+Quote Post
zltigo
сообщение Feb 22 2010, 16:48
Сообщение #12


Гуру
******

Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244



Цитата(GetSmart @ Feb 22 2010, 18:02) *
Это только половина "зла". Переменная всё равно будет нах-ся в раме. Универсальную ссылку на регистр ещё не придумали biggrin.gif

Если Вы пытаетесь рассказывать о 'C', то там передачи параметров по ссылке нет. Совсем нет. Ибо указатель это НЕ ссылка. А в плюсах есть передача параметров по ссылке и посему "придумывать" уже не надо. В обычном 'C', как уже писал, дело сложнее, но принципиальная возможность передать функции не модифицирующей указатель в регистре вместо указателя на int в регистре сам int есть.


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
GetSmart
сообщение Feb 22 2010, 17:47
Сообщение #13


.
******

Группа: Участник
Сообщений: 4 005
Регистрация: 3-05-06
Из: Россия
Пользователь №: 16 753



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

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


--------------------
Заблуждаться - Ваше законное право :-)
Go to the top of the page
 
+Quote Post
zltigo
сообщение Feb 22 2010, 18:46
Сообщение #14


Гуру
******

Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244



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

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


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
SasaVitebsk
сообщение Feb 22 2010, 20:12
Сообщение #15


Гуру
******

Группа: Свой
Сообщений: 2 712
Регистрация: 28-11-05
Из: Беларусь, Витебск, Строителей 18-4-220
Пользователь №: 11 521



Честно говоря, тоже не понимаю зачем это надо. Как то тоже не возникало необходимости.

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

  void b(void)
  {
  }
}

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

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

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

По моему в рамках языка, существует куча способов свободно "выразится". На мой взгляд, итак языки перегружены понятиями и возможностями. И процесс продолжается.
Go to the top of the page
 
+Quote Post
Xenia
сообщение Feb 22 2010, 21:02
Сообщение #16


Гуру
******

Группа: Модератор FTP
Сообщений: 4 479
Регистрация: 20-02-08
Из: Москва
Пользователь №: 35 237



Отчего бы не помечтать 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++ слишком непривычно.
Go to the top of the page
 
+Quote Post
ReAl
сообщение Feb 22 2010, 22:37
Сообщение #17


Нечётный пользователь.
******

Группа: Свой
Сообщений: 2 033
Регистрация: 26-05-05
Из: Бровари, Україна
Пользователь №: 5 417



Цитата(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);
    }


--------------------
Ну, я пошёл… Если что – звоните…
Go to the top of the page
 
+Quote Post
vmp
сообщение Feb 24 2010, 06:38
Сообщение #18


Местный
***

Группа: Свой
Сообщений: 426
Регистрация: 20-01-05
Из: Зеленоград
Пользователь №: 2 070



Цитата(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 }
Go to the top of the page
 
+Quote Post
_Pasha
сообщение Feb 24 2010, 07:22
Сообщение #19


;
******

Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509



Я бы хотел, чтоб в сях(да и паскале тоже) наконец-то исчез бардак в типе результата целочисленного умножения. Т.е. результат mul16x16 по умолчанию все же 32-битный должен быть, а 8*8 16-битный. Мы же все-таки в реальном мире находимся?
И чтобы препроцессор был рискованно рекурсивным biggrin.gif
Цитата
в командах break и continue (кстати, одинаковые для Си и Паскаля)

Нифига они не одинаковые изначально. В паскале это intrinsic procedures.
Go to the top of the page
 
+Quote Post
sigmaN
сообщение Feb 24 2010, 07:32
Сообщение #20


I WANT TO BELIEVE
******

Группа: Свой
Сообщений: 2 617
Регистрация: 9-03-08
Пользователь №: 35 751



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

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

Про структуру тоже хотел напомнить. Опередили smile.gif


--------------------
The truth is out there...
Go to the top of the page
 
+Quote Post
_Pasha
сообщение Feb 24 2010, 07:35
Сообщение #21


;
******

Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509



В принципе, было бы на 100% эффективным введение средств для задания идиоматических выражений (звучит смешно, вспоминая русский язык). Это, извините, не кривой плюсовый operator, а реальное средство, ускоряющее развитие оптимизаторов.
Go to the top of the page
 
+Quote Post
AlexandrY
сообщение Feb 24 2010, 08:25
Сообщение #22


Ally
******

Группа: Модераторы
Сообщений: 6 232
Регистрация: 19-01-05
Пользователь №: 2 050



LUA может возвращать переменные пачками.
http://www.lua.ru/doc/

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

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

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

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

Совершенствовать броузинг кода и средства рефакторинга.
Языки же надо расширять стандартными общепринятыми либами и средствами генерации произвольных представлений.
Так чтобы был возможен автоматический ремапинг из одного языка в другой как это продвигает Microsoft в .NET технологии.
Go to the top of the page
 
+Quote Post
GetSmart
сообщение Feb 24 2010, 09:20
Сообщение #23


.
******

Группа: Участник
Сообщений: 4 005
Регистрация: 3-05-06
Из: Россия
Пользователь №: 16 753



vmp, это то же самое как и передавать указатель на структуру в качестве параметра функции. Код будет 100% одинаковым. Переменнаяя/результат будет располагаться в стеке. Но т.к. современные компиляторы (сами) стараются располагать переменные в регистрах, то вместо этого устаревшего варианта возврата результата через стек пора бы уже вводить возврат результата (множественного) через регистры. Раньше было рано, а теперь в самый раз smile.gif


--------------------
Заблуждаться - Ваше законное право :-)
Go to the top of the page
 
+Quote Post
dxp
сообщение Feb 24 2010, 10:04
Сообщение #24


Adept
******

Группа: Свой
Сообщений: 3 469
Регистрация: 6-12-04
Из: Novosibirsk
Пользователь №: 1 343



Цитата(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

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


--------------------
«Отыщи всему начало, и ты многое поймёшь» К. Прутков
Go to the top of the page
 
+Quote Post
_Pasha
сообщение Feb 24 2010, 13:06
Сообщение #25


;
******

Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509



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

avr-gcc возвращает структуру, располагая ее в регистрах согласно calling conventions, либо на стеке, если она не вмещается.
Go to the top of the page
 
+Quote Post
GetSmart
сообщение Feb 24 2010, 15:04
Сообщение #26


.
******

Группа: Участник
Сообщений: 4 005
Регистрация: 3-05-06
Из: Россия
Пользователь №: 16 753



Структура - структурой. А я предлагаю "симметрию" в описании параметров и результата функции. Чем не фича? ИМХО красивый концепт получается.


--------------------
Заблуждаться - Ваше законное право :-)
Go to the top of the page
 
+Quote Post
GetSmart
сообщение Jan 28 2012, 05:29
Сообщение #27


.
******

Группа: Участник
Сообщений: 4 005
Регистрация: 3-05-06
Из: Россия
Пользователь №: 16 753



Ещё недоработку обнаружил. Volatile.

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


--------------------
Заблуждаться - Ваше законное право :-)
Go to the top of the page
 
+Quote Post
vitan
сообщение Jan 28 2012, 07:49
Сообщение #28


не указал(а) ничего о себе.
******

Группа: Свой
Сообщений: 3 325
Регистрация: 6-04-06
Пользователь №: 15 887



Цитата(GetSmart @ Feb 22 2010, 16:13) *
Почему не делают в ЯВУ возврат из функций несколько переменных?

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

Возможно, немного не по теме, но, например, в AHDL (тоже язык высокого уровня) это возможно. Только синтаксис немного другой, но суть та же.
Так что - смотря о каких языках речь...
Go to the top of the page
 
+Quote Post
_Pasha
сообщение Jan 28 2012, 09:00
Сообщение #29


;
******

Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509



Цитата(GetSmart @ Jan 28 2012, 08:29) *
Но вроде бы это не предусмотрено. (?)

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

Ы?
Go to the top of the page
 
+Quote Post
toweroff
сообщение Jan 28 2012, 13:36
Сообщение #30


Гуру
******

Группа: Свой
Сообщений: 2 957
Регистрация: 19-09-06
Из: Москва
Пользователь №: 20 514



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

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

а если прерывание вложенное?
Go to the top of the page
 
+Quote Post
sonycman
сообщение Jan 28 2012, 13:44
Сообщение #31


Любитель
*****

Группа: Свой
Сообщений: 1 864
Регистрация: 20-08-06
Из: Тольятти
Пользователь №: 19 695



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

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

А если обработчики прерываний вынести в отдельный файл, там объявить необходимую переменную int val, а в другие файлы добавить эту переменную как extern volatile int val?
В результате обработчики прерываний будут работать с оптимизированной переменной, а вся остальная прога - с volatile.
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Jan 28 2012, 14:37
Сообщение #32


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



QUOTE (sonycman @ Jan 28 2012, 15:44) *
А если обработчики прерываний вынести в отдельный файл,
Как-то слишком сложно. _Pasha правильно предложил - завести временную переменную (только не указатель, на Пашин пример будет справедливо ругаться, ибо указатель должен быть на volatile), когда надо считывать в эту переменную, проводить с ней вычисления и когда надо записывать обратно в volatile-переменную. Лишь только программист в состоянии определить, когда наступает этот момент "когда надо". Ни один компилятор угадать его не сможет.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
sasamy
сообщение Jan 28 2012, 21:27
Сообщение #33


Знающий
****

Группа: Участник
Сообщений: 783
Регистрация: 22-11-08
Пользователь №: 41 858



Цитата(SasaVitebsk @ Feb 23 2010, 00:12) *
Единственное, что я пользовал в Pascal, а в С этого нет - так это вложенные процедуры.


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

хотя наверно вы знаете. На практике - я не встречал чтобы этим кто-то пользовался.
Go to the top of the page
 
+Quote Post
GetSmart
сообщение Jan 29 2012, 02:42
Сообщение #34


.
******

Группа: Участник
Сообщений: 4 005
Регистрация: 3-05-06
Из: Россия
Пользователь №: 16 753



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

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

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

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

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

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

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

Сообщение отредактировал GetSmart - Jan 29 2012, 08:37


--------------------
Заблуждаться - Ваше законное право :-)
Go to the top of the page
 
+Quote Post
_Ivana
сообщение Jan 29 2012, 10:03
Сообщение #35


Местный
***

Группа: Свой
Сообщений: 352
Регистрация: 13-08-11
Из: Воронеж
Пользователь №: 66 710



А мне бы хотелось вот какую доработку - чтобы написать в редакторе прямо русскими словами "Уважаемый компилятор с оптимизатором, сделай мне хороший, быстрый и правильно работающий код" - и он бы сам все сделал rolleyes.gif

ЗЫ МК всегда все делает "правильно", честно бежит по РИСК или ЦИСК командам и выполняет их. И если результат не нравится разработчику, то пусть ищет свои ошибки. А если он (разработчик) не опускается до asm, а пишет на ЯВУ (наяву - каламбурчик rolleyes.gif ), то вдобавок к логике необходимо знать все тонкости и особенности компилятора вплоть до индивидуальных багов/фичей используемой версии. Это в принципе непросто, вот поэтому и получается типа "пишу одно а он мне делает не так". Закон Джоэла Спольски - все нетривиальные абстракции дырявы rolleyes.gif
Вот тут http://electronix.ru/forum/index.php?showtopic=95060 я безуспешно пытался многабуквенно это имховыражать.
Go to the top of the page
 
+Quote Post
_Pasha
сообщение Jan 29 2012, 11:42
Сообщение #36


;
******

Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509



Цитата(GetSmart @ Jan 29 2012, 05:42) *
Чем больше скобок, тем раньше доступ. При равном количестве - варнинг, означающий что реализация вычисления на откуп компилятора.

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

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

Так Вы спрашивайте! В определенный период каждый первый страдает подобным.
Кстати, при изучении любого вопроса имхо полезно "в пику" создавать свой вариант решения.
Для облегчения понимания, прежде всего.
Go to the top of the page
 
+Quote Post
GetSmart
сообщение Jan 29 2012, 12:10
Сообщение #37


.
******

Группа: Участник
Сообщений: 4 005
Регистрация: 3-05-06
Из: Россия
Пользователь №: 16 753



Цитата(_Pasha @ Jan 29 2012, 16:42) *
Дык, слева направо! laughing.gif И при этом CSE идёт лесом.

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

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


--------------------
Заблуждаться - Ваше законное право :-)
Go to the top of the page
 
+Quote Post
sigmaN
сообщение Jan 30 2012, 01:34
Сообщение #38


I WANT TO BELIEVE
******

Группа: Свой
Сообщений: 2 617
Регистрация: 9-03-08
Пользователь №: 35 751



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

Ну т.е. сомнительная такая оптимизация получается.


--------------------
The truth is out there...
Go to the top of the page
 
+Quote Post
GetSmart
сообщение Mar 6 2012, 05:49
Сообщение #39


.
******

Группа: Участник
Сообщений: 4 005
Регистрация: 3-05-06
Из: Россия
Пользователь №: 16 753



Цитата(_Pasha @ Jan 28 2012, 14:00) *
Код
volatile int some;
int *someptr = &some;
*someptr += 2;

Ы?

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

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

Вобщем это и понятно.
Но тогда вопрос к знатокам: если в самом начале строки с объявлением переменной будет "static", то всегда ли это (вне функций допустим) будет означать видимость переменной внутри модуля, или в первом случае (как и действие volatile) квалификатор будет засчитан к объекту, на который ссылается переменная, а не к самой переменной?


--------------------
Заблуждаться - Ваше законное право :-)
Go to the top of the page
 
+Quote Post
Alex-sh
сообщение Mar 6 2012, 19:16
Сообщение #40





Группа: Новичок
Сообщений: 2
Регистрация: 6-03-12
Пользователь №: 70 658



Добрый вечер. Я знаю что мой вопрос несколько не в тему, поэтому заранее извеняюсь. Подскажите пожалуйста кто может помочь в написании программ на Ассемблере для микроконтроллеров PIC и MCS. Вот пример одного из заданий. Составить алгоритм и программу на языке Ассемблер для МП типа MCS –51, выполняющую логическое умножение содержимого порта Р1 и аккумулятора, в случае равенства результата нулю, устанавливающую в единицу флаг 22h. Для знающего человека это пара минут, а для меня полный мрак и даже хуже. Помогите, кто чем сможет!!!
Go to the top of the page
 
+Quote Post
ReAl
сообщение Mar 7 2012, 06:58
Сообщение #41


Нечётный пользователь.
******

Группа: Свой
Сообщений: 2 033
Регистрация: 26-05-05
Из: Бровари, Україна
Пользователь №: 5 417



Цитата(Сергей Борщ @ 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 как хочет
};


--------------------
Ну, я пошёл… Если что – звоните…
Go to the top of the page
 
+Quote Post
GetSmart
сообщение Mar 7 2012, 07:17
Сообщение #42


.
******

Группа: Участник
Сообщений: 4 005
Регистрация: 3-05-06
Из: Россия
Пользователь №: 16 753



Цитата(ReAl @ Mar 7 2012, 11:58) *
А вообще — разве не так?
...

А паблик волатил запись не нужна?


--------------------
Заблуждаться - Ваше законное право :-)
Go to the top of the page
 
+Quote Post
ReAl
сообщение Mar 7 2012, 17:22
Сообщение #43


Нечётный пользователь.
******

Группа: Свой
Сообщений: 2 033
Регистрация: 26-05-05
Из: Бровари, Україна
Пользователь №: 5 417



Не понял вопрос.
Какая запись и где должна быть нужна. Имеется ввиду очередная собака - "сеттер"? (Витус Вагнер недавно говорил о том, что геттеры надо бы ретриверами называть, вместе с сеттерами и пойнтерами отличная псарня была бы)
Так пример короткий для общего понимания, setter-функция часто и не нужна.


--------------------
Ну, я пошёл… Если что – звоните…
Go to the top of the page
 
+Quote Post
_Pasha
сообщение Mar 9 2012, 07:46
Сообщение #44


;
******

Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509



До кучи
Go to the top of the page
 
+Quote Post
GetSmart
сообщение Mar 9 2012, 11:23
Сообщение #45


.
******

Группа: Участник
Сообщений: 4 005
Регистрация: 3-05-06
Из: Россия
Пользователь №: 16 753



Цитата(_Pasha @ Mar 9 2012, 12:46) *
До кучи

Ну вот. И эти товарищи встали на грабли. На самом деле из двух объявлений, только одно объявление волатильной переменной. Второе объявление есть объявление обычной переменной - указателя на волатильную.
Эскизы прикрепленных изображений
Прикрепленное изображение
 


--------------------
Заблуждаться - Ваше законное право :-)
Go to the top of the page
 
+Quote Post
GetSmart
сообщение Apr 13 2017, 16:08
Сообщение #46


.
******

Группа: Участник
Сообщений: 4 005
Регистрация: 3-05-06
Из: Россия
Пользователь №: 16 753



Хотел красиво оптимизировать Си-код, выполняющий общие действия для сложносоставного условия-алгоритма, содержащего в себе вызов 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, массив, а так же список однотипных членов, разделённых запятой, делаются по логике создания структуры. То есть это будут члены/переменные, следующие в адресном пространстве друг за другом. И только после точки с запятой адрес следущего члена обнуляется.

Сообщение отредактировал GetSmart - Apr 13 2017, 21:25


--------------------
Заблуждаться - Ваше законное право :-)
Go to the top of the page
 
+Quote Post
iiv
сообщение Apr 29 2017, 15:19
Сообщение #47


вопрошающий
*****

Группа: Свой
Сообщений: 1 726
Регистрация: 24-01-11
Пользователь №: 62 436



Цитата(SasaVitebsk @ Feb 23 2010, 01:12) *
Единственное, что я пользовал в Pascal, а в С этого нет - так это вложенные процедуры.


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

Конечно можно возразить, что де пиши на С++, но там аналогичный код становится достаточно большим, поэтому если вам платят не за число строк, а за результат, то вложенные С-шные функции - крайне полезная конструкция.
Go to the top of the page
 
+Quote Post
sigmaN
сообщение Apr 30 2017, 08:29
Сообщение #48


I WANT TO BELIEVE
******

Группа: Свой
Сообщений: 2 617
Регистрация: 9-03-08
Пользователь №: 35 751



bb-offtopic.gif
Цитата
что де пиши на С++, но там аналогичный код становится достаточно большим,
Нда, шел 2017год, а наш народ по прежнему рассказывал, как на с++ код становится достаточно большим..... Грустно sad.gif


--------------------
The truth is out there...
Go to the top of the page
 
+Quote Post
ar__systems
сообщение May 4 2017, 03:27
Сообщение #49


self made
****

Группа: Свой
Сообщений: 855
Регистрация: 7-03-09
Из: Toronto, Canada
Пользователь №: 45 795



Цитата(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();


Зачем мудрить-то?
Go to the top of the page
 
+Quote Post
Эдди
сообщение May 4 2017, 05:20
Сообщение #50


Знающий
****

Группа: Участник
Сообщений: 825
Регистрация: 16-04-15
Из: КЧР, Нижний Архыз
Пользователь №: 86 250



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

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

Сообщение отредактировал Эдди - May 4 2017, 05:21
Go to the top of the page
 
+Quote Post
ar__systems
сообщение May 4 2017, 11:40
Сообщение #51


self made
****

Группа: Свой
Сообщений: 855
Регистрация: 7-03-09
Из: Toronto, Canada
Пользователь №: 45 795



Цитата(Эдди @ May 4 2017, 00:20) *
В gcc5 это посчитали вредным, поэтому в опции компилятора теперь нужно добавлять -Wno-trampoline, иначе не соберется (я всегда указываю -Wall -Wextra, чтобы не было соблазна игнорировать предупреждения).
А вот что мне не нравится, так это работа с сокетами! Ну никак не обойтись без таймаутов...

socket ы это библиотека а не язык....
Go to the top of the page
 
+Quote Post
Эдди
сообщение May 4 2017, 15:22
Сообщение #52


Знающий
****

Группа: Участник
Сообщений: 825
Регистрация: 16-04-15
Из: КЧР, Нижний Архыз
Пользователь №: 86 250



Вообще-то, сокеты входят в stdlib — для работы с ними дополнительных библиотек линковать не надо.
Но сама по себе реализация как-то не очень… Скажем, если write в закрытый сокет вернет ошибку, то read вернет просто 0 — как будто бы данных нет! И select/poll с закрытым сокетом ошибку не дадут.
Go to the top of the page
 
+Quote Post
Grizzzly
сообщение May 4 2017, 17:55
Сообщение #53


Знающий
****

Группа: Свой
Сообщений: 565
Регистрация: 22-02-13
Пользователь №: 75 748



Цитата(Эдди @ May 4 2017, 18:22) *
Вообще-то, сокеты входят в stdlib — для работы с ними дополнительных библиотек линковать не надо.

Ну, дык, это всё равно же библиотека. Причем реализаций этой библиотеки довольно много.
Go to the top of the page
 
+Quote Post
Эдди
сообщение May 4 2017, 18:01
Сообщение #54


Знающий
****

Группа: Участник
Сообщений: 825
Регистрация: 16-04-15
Из: КЧР, Нижний Архыз
Пользователь №: 86 250



Предлагаю не рассматривать всякие альтернативы. Обычный "стандартный" gcc и stdlib. Дома я еще на 4.9.3 сижу, на работе давно уже на 5.4.0 перешел.
Go to the top of the page
 
+Quote Post
Kane
сообщение May 5 2017, 14:32
Сообщение #55


Участник
*

Группа: Участник
Сообщений: 36
Регистрация: 10-02-06
Пользователь №: 14 185



Цитата(Эдди @ May 4 2017, 21:01) *
Предлагаю не рассматривать всякие альтернативы. Обычный "стандартный" gcc и stdlib.

Вы б с содержимым стандартов для начала ознакомились. Не входят сокеты в стандартную библиотеку С99/11. C++ я не знаю, но поиском по pdf С++2014 ничего похожего на сокеты тоже не нашел.
Go to the top of the page
 
+Quote Post
Guest_TSlicer_*
сообщение May 5 2017, 17:17
Сообщение #56





Guests






Цитата(Kane @ May 5 2017, 15:32) *
Вы бы с содержимым стандартов для начала ознакомились.

В горах - все по другому. Там звезды ближе и телескопы есть.
Go to the top of the page
 
+Quote Post
RabidRabbit
сообщение May 7 2017, 11:00
Сообщение #57


Местный
***

Группа: Свой
Сообщений: 397
Регистрация: 3-12-09
Из: Россия, Москва
Пользователь №: 54 040



Цитата(Эдди @ May 4 2017, 18:22) *
Скажем, если write в закрытый сокет вернет ошибку, то read вернет просто 0 — как будто бы данных нет!

Ну не знаю, как у Вас, а у меня 0, полученный от read() для сокета однозначно идентифицирует, что он был закрыт с другой стороны.
Вот если удалённый хост упал - да, вы будете ждать некоторое время, пока стек решит, что связи больше не будет, но это решается, например, уровнем выше sm.gif

А вообще, вот очень хороший материал:
Снейдер Йон: Эффективное программирование TCP/IP.
Go to the top of the page
 
+Quote Post
GetSmart
сообщение May 21 2018, 17:32
Сообщение #58


.
******

Группа: Участник
Сообщений: 4 005
Регистрация: 3-05-06
Из: Россия
Пользователь №: 16 753



Продолжаем фантазировать.
Надо что-то вроде инкомплит-тайп-каст'а. Чтобы сделать "принудительное" чтение переменной типа result = *(volatile *)&var; которая объявлена конечно же неволатильной. Скажете: сделай сразу переменную волатильной. А я отвечу: хочу массив неволатильных переменных, а первый элемент волатильный))) Ну и для всяческих приблуд pack/align/const.

Хотя инкомплит неудачное название. Лучше что-то вроде "атрибут-тайп-каст". Понятно, что что-то похожее можно сделать через стандартный тайп-каст, но хочется чтобы это работало без явного указания ширины переменной, вобщем лишней инфы. И из этой же оперы, хотелось делать тайп-каст (signed) или (unsigned). Это уже инкомплит-тип.

Сообщение отредактировал GetSmart - May 21 2018, 19:42


--------------------
Заблуждаться - Ваше законное право :-)
Go to the top of the page
 
+Quote Post
jcxz
сообщение May 22 2018, 03:16
Сообщение #59


Гуру
******

Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713



1. Было-бы лучше, если бы в си, при объявлении инициализированного массива с явно указанной размерностью
int m[N] = {1, 2, 3};
компилятор выдавал бы ошибку компиляции если количество инициализаторов не равно N.
Это очень полезно для создания связанных списков: define_значение/значение_константы.
2. Было бы очень полезно, если бы в константных выражениях можно было смешивать строки и значения:
enum {z1 = 5};
char const t[] = "string" z1 " - " (z1+2)*9;
3. Было бы классно если бы строковые константы можно было задавать не только в форме ASCIIZ (завершающийся нулём набор символов), но и в виде:
длина_строки "строка" (без 0 в конце). Хотя это решается автоматически при выполнении пункта 2.
4. Полезно было бы в stdlib в обязательном порядке внести прототип функции _Printf(void *(*)(void *), void *, char *, ...) - т.е. функцию из семейства printf...() передающую поток выводимых символов не на stdout (printf()) или в память (sprintf()), а в callback-функцию (первый аргумент _Printf()).
5. Было бы очень полезно наличие в языке возможностей задания списков define-ов (или enum) с уникальными значениями. Т.е. чтобы на:
enum {V_1 = 11, V_2 = 12, V_3 = 13, V_4 = 11, ...};
вылетало на ошибке компиляции типа: "V_4 - duplicate value".
Часто приходится задавать или списки define ног контроллера или каналов DMA, портов и пр. ресурсов, в которых каждый элемент списка должен иметь уникальное значение, не совпадающее с другими. При каждом редактировании очень неудобно каждый раз перепроверять весь список на наличие конфликтов, особенно если значения справа от "=" - это не литеральные константы, а выражения.
Приходится выкручиваться через проверяющие макросы.
Go to the top of the page
 
+Quote Post
haker_fox
сообщение May 22 2018, 05:31
Сообщение #60


Познающий...
******

Группа: Свой
Сообщений: 2 963
Регистрация: 1-09-05
Из: г. Иркутск
Пользователь №: 8 125



QUOTE (jcxz @ May 22 2018, 11:16) *
1. Было-бы лучше, если бы в си, при объявлении инициализированного массива с явно указанной размерностью
int m[N] = {1, 2, 3};
компилятор выдавал бы ошибку компиляции если количество инициализаторов не равно N.

Да, либо сделать эту опцию управлемой ключом.
QUOTE (jcxz @ May 22 2018, 11:16) *
enum {V_1 = 11, V_2 = 12, V_3 = 13, V_4 = 11, ...};
вылетало на ошибке компиляции типа: "V_4 - duplicate value".

И здесь согласен. Можно также ключом.

Теперь вопрос, кому позвонить. чтобы добавили в IAR 8.22)()))


--------------------
Выбор.
Go to the top of the page
 
+Quote Post
Forger
сообщение May 22 2018, 06:57
Сообщение #61


Профессионал
*****

Группа: Свой
Сообщений: 1 215
Регистрация: 22-02-05
Пользователь №: 2 831



Цитата(jcxz @ May 22 2018, 06:16) *
1. Было-бы лучше, если бы в си, при объявлении инициализированного массива с явно указанной размерностью
int m[N] = {1, 2, 3};компилятор выдавал бы ошибку компиляции если количество инициализаторов не равно N.

Дык, он и так ругается, но лишь в одном случае - число инициализаторов больше размерности массива.
Увы, не ругается, если меньше. Просто "забивает" недостающие нулями. Это действительно неудобно.

Цитата
2. Было бы очень полезно, если бы в константных выражениях можно было смешивать строки и значения:

В голом виде (без STL и типа того), подобная затея - это рассадник опасных и довольно коварных ошибок на абсолютно ровном месте:
как минимум нужно контролировать размерности типов данных на разных платформах, в т. ч. "банальный" char.
Вангую головную боль, в принципе, на ровном месте.
К тому же такое "оружие" опасно отдавать в руки новичками.

Цитата
3. Было бы классно если бы строковые константы можно было задавать не только в форме ASCIIZ (завершающийся нулём набор символов), но и в виде:
длина_строки "строка" (без 0 в конце).

Код
const char t1[] = "012";
const char t2[3] = { '0', '1', '2' };

t1 будет иметь длину 4 байта, а t2 - 3 байта.
Определить длину t1 можно лишь найдя ноль в конце, у t2 размер указан явно. Все логично.

Но, если убрать ноль у t1, сделав его длину 3 байта, то как в коде понять, что он имеет размер в 3 байта?
Как отличить его с "классической" строкой в 4 байта?
Путаница на абсолютно ровном месте. Имхо, опасная блажь!

Цитата
4. Полезно было бы в stdlib в обязательном порядке внести прототип функции _Printf(void *(*)(void *), void *, char *, ...) - т.е. функцию из семейства printf...() передающую поток выводимых символов не на stdout (printf()) или в память (sprintf()), а в callback-функцию (первый аргумент _Printf()).

Это легко делается и сейчас: достаточно лишь "перегрузить" встроенную функцию "putc" своей собственной реализацией, игнорируя второй параметр FILE *.
Вот ее прототип: int putc(int ch, FILE *stream);
В этом случае при сборке проекта линкер "возьмет" реализацию putc из вашего кода, а не штатную из библиотеки stdio.


Цитата
5. Было бы очень полезно наличие в языке возможностей задания списков define-ов (или enum) с уникальными значениями. Т.е. чтобы на:
enum {V_1 = 11, V_2 = 12, V_3 = 13, V_4 = 11, ...};
вылетало на ошибке компиляции типа: "V_4 - duplicate value".

Очень спорная потребность: могут начаться проблемы как минимум со сторонним кодом, где дублированные значения могут быть созданы намеренно.


--------------------
Кругозор некоторых людей - круг с нулевым радиусом. Они называют его "точкой зрения".
Go to the top of the page
 
+Quote Post
ViKo
сообщение May 22 2018, 07:42
Сообщение #62


Универсальный солдатик
******

Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362



Цитата(jcxz @ May 22 2018, 06:16) *
5. Было бы очень полезно наличие в языке возможностей задания списков define-ов (или enum) с уникальными значениями. Т.е. чтобы на:
enum {V_1 = 11, V_2 = 12, V_3 = 13, V_4 = 11, ...};
вылетало на ошибке компиляции типа: "V_4 - duplicate value".

Не согласен. Личный пример, как описываю альтернативные функции для портов STM32:
CODE

//! GPIO Alternate Functions
typedef enum {
AF_SYSTEM, //!< AF0 - SYSTEM*
AF_TIM1, //!< AF1 - TIM1/2
AF_TIM2 = 1, //!< AF1 - TIM1/2
AF_TIM3, //!< AF2 - TIM3/4/5
AF_TIM4 = 2, //!< AF2 - TIM3/4/5
AF_TIM5 = 2, //!< AF2 - TIM3/4/5
AF_TIM8, //!< AF3 - TIM9/10/11
AF_TIM9 = 3, //!< AF3 - TIM9/10/11
AF_TIM10 = 3, //!< AF3 - TIM9/10/11
AF_TIM11 = 3, //!< AF3 - TIM9/10/11
AF_I2C1, //!< AF4 - I2C1/2/3
AF_I2C2 = 4, //!< AF4 - I2C1/2/3
AF_I2C3 = 4, //!< AF4 - I2C1/2/3
AF_SPI1, //!< AF5 - SPI1/2
AF_SPI2 = 5, //!< AF5 - SPI1/2
AF_SPI3, //!< AF6 - SPI3
AF_USART1, //!< AF7 - USART1/2/3
AF_USART2 = 7, //!< AF7 - USART1/2/3
AF_USART3 = 7, //!< AF7 - USART1/2/3
AF_USART4, //!< AF8 - USART4/5/6
AF_USART5 = 8, //!< AF8 - USART4/5/6
AF_USART6 = 8, //!< AF8 - USART4/5/6
AF_CAN1, //!< AF9 - CAN1/2
AF_CAN2 = 9, //!< AF9 - CAN1/2
AF_TIM12 = 9, //!< AF9 - TIM12/13/14
AF_TIM13 = 9, //!< AF9 - TIM12/13/14
AF_TIM14 = 9, //!< AF9 - TIM12/13/14
AF_OTGFS, //!< AF10 - OTGFS
AF_OTGHS = 10, //!< AF10 - OTGHS
AF_ETH, //!< AF11 - ETH
AF_FSMC, //!< AF12 - FSMC
AF_SDIO = 12, //!< AF12 - SDIO
AF_OTGHS_ = 12, //!< AF12 - OTGHS
AF_DCMI, //!< AF13 - DCMI
AF_AF14, //!< AF14 - RI
AF_EVENT //!< AF15 - SYSTEM (EVENTOUT)
} GPIO_AFLH_t;
Go to the top of the page
 
+Quote Post
jcxz
сообщение May 22 2018, 08:15
Сообщение #63


Гуру
******

Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713



Цитата(Forger @ May 22 2018, 09:57) *
Дык, он и так ругается, но лишь в одном случае - число инициализаторов больше размерности массива.

Я писал, что хотелось бы ошибку при не равно, а не только при больше. Что будет при меньше я прекрасно знаю, именно поэтому и написал такой пункт.

Цитата(Forger @ May 22 2018, 09:57) *
В голом виде (без STL и типа того), подобная затея - это рассадник опасных и довольно коварных ошибок на абсолютно ровном месте:

В чём именно опасность? Не понял. wacko.gif
Да, программировать нужно уметь и язык знать - это вроде не должно вызывать сомнений.
И в ассемблерах такая возможность часто имеется.

Цитата(Forger @ May 22 2018, 09:57) *
Но, если убрать ноль у t1, сделав его длину 3 байта, то как в коде понять, что он имеет размер в 3 байта?
Как отличить его с "классической" строкой в 4 байта?

Прочитайте моё сообщение внимательнее прежде чем критиковать.
Я пишу, что хотелось бы не только "классические" строки (это называется обычно ASCIIZ), а и строки в формате длина,символы_без_0_в_конце.

Цитата(Forger @ May 22 2018, 09:57) *
Путаница на абсолютно ровном месте. Имхо, опасная блажь!

Теперь расскажите это создателям Паскаля и тем десяткам тысяч программистов кто его использует. laughing.gif
Если Вы не в состоянии понять для чего это нужно, это ещё не повод говорить "блажь".
Например: программа получает текстовый поток данных, который разбивает на лексемы (слова) заменяя строковые значения лексем их номерами из некоего словаря. Значит - в программе есть некий массив лексем, константный и возможно довольно большой.
Теперь объясните, пожалуйста, как эффективно (т.е. - быстро) организовать поиск лексем в таком массиве, если принять, что лексемы имеют сильно разные размеры и что для удобства читаемости (и редактирования) исходника лексемы очень желательно иметь в виде строк (а не в виде {'a','b',...}) и лексемы нельзя расположить в некоем удобном для поиска порядке, а порядок их расположения одна относительно другой определяется другими критериями (разбивка на логические группы, связь со значениями define-ов и т.п.) ???
Так вот: с байтом длины поиск в таком списке лексем будет идти гораздо быстрее чем со списком ASCIIZ-строк.

Цитата(Forger @ May 22 2018, 09:57) *
Это легко делается и сейчас: достаточно лишь "перегрузить" встроенную функцию "putc" своей собственной реализацией, игнорируя второй параметр FILE *.

Данный пункт скорее касается компиляторов для PC, потому что в тех компиляторах для МК, с коими я работал (IAR и в CCS) такая функция и так имеется (_Printf()).
А в компиляторах на PC часто нежелательно перегружать putc(), потому что она может быть нужна.

Цитата(Forger @ May 22 2018, 09:57) *
Очень спорная потребность: могут начаться проблемы как минимум со сторонним кодом, где дублированные значения могут быть созданы намеренно.

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

Цитата(ViKo @ May 22 2018, 10:42) *
Не согласен. Личный пример, как описываю альтернативные функции для портов STM32:

И что? Как это поможет от дубликатов? Вот у Вас AF_TIM1 и AF_TIM2 имеют одинаковые значения и при этом это нормально скомпилится. А не должно компилиться.
Go to the top of the page
 
+Quote Post
ViKo
сообщение May 22 2018, 08:25
Сообщение #64


Универсальный солдатик
******

Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362



Цитата(jcxz @ May 22 2018, 11:15) *
И что? Как это поможет от дубликатов? Вот у Вас AF_TIM1 и AF_TIM2 имеют одинаковые значения и при этом это нормально скомпилится. А не должно компилиться.

Не согласен с вашим предложением, вот что. rolleyes.gif Потому что хочу иметь одинаковые значения в перечислении.
Go to the top of the page
 
+Quote Post
jcxz
сообщение May 22 2018, 08:45
Сообщение #65


Гуру
******

Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713



Цитата(ViKo @ May 22 2018, 11:25) *
Не согласен с вашим предложением, вот что. rolleyes.gif Потому что хочу иметь одинаковые значения в перечислении.

Блин! Ещё раз: я не предлагал изменить логику работы enum конечно же! А добавить новый механизм, в котором одинаковые значения запрещены.
Я тоже использую enum-ы с одинаковыми значениями. Когда это надо.
Go to the top of the page
 
+Quote Post
Forger
сообщение May 22 2018, 08:49
Сообщение #66


Профессионал
*****

Группа: Свой
Сообщений: 1 215
Регистрация: 22-02-05
Пользователь №: 2 831



Цитата(jcxz @ May 22 2018, 11:15) *
Теперь расскажите это создателям Паскаля и тем десяткам тысяч программистов кто его использует. laughing.gif

Тогда тоже пишите в паскале. В чем проблема? smile3046.gif

К слову, в C# со строками все это сделано гораздо удобнее, чем в голом C/C++, но опять-таки в основном за счет очень толстых библиотек.

А речь как я понял про С/C++. Коли так, то почти все ваши пожелания - пока что фантастика.
Посмотрите историю эволюции C++ (03 - 11 - 14 - 17) - там появляются новые фишки, но совсем другого рода. К вашим паскале-подобным "удобствам" отношения не имеют.
И наверняка на то есть причины - новые стандарты появляются в голове не одного человека, в этом участвует сообщество серьезных мега-программеров.

Поэтому я согласен лишь с одним пунктом (1): за более жесткий контроль числа инициализаторов массива. Имхо, весьма полезная "фишка".
Пусть и не ошибка "вылетает", но хотя бы варнинг.

Цитата(jcxz @ May 22 2018, 11:45) *
А добавить новый механизм, в котором одинаковые значения запрещены.

Это легко реализовать в run-time, всего один раз запускать проверку на дубликаты значений.
Я бы сделал так: const struct, или лучше: constexpr struct, дав значения каждом полю прямо при объявлении (С++11).

Кстати, мне еще никогда не приходилось сталкиваться с таким - механизм, в котором одинаковые значения запрещены, и в чужом коде тоже.
По мне - экзотика laughing.gif .


--------------------
Кругозор некоторых людей - круг с нулевым радиусом. Они называют его "точкой зрения".
Go to the top of the page
 
+Quote Post
ViKo
сообщение May 22 2018, 09:03
Сообщение #67


Универсальный солдатик
******

Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362



Цитата(jcxz @ May 22 2018, 11:45) *
Блин! Ещё раз: я не предлагал изменить логику работы enum конечно же! А добавить новый механизм, в котором одинаковые значения запрещены.
Я тоже использую enum-ы с одинаковыми значениями. Когда это надо.

Что-то типа unique_case в SV? Атрибут такой ввести? Ну, пусть. santa2.gif
Go to the top of the page
 
+Quote Post
Nixon
сообщение May 22 2018, 09:13
Сообщение #68


Гуру
******

Группа: Админы
Сообщений: 2 736
Регистрация: 17-06-04
Из: Киев
Пользователь №: 48



Цитата(Forger @ May 22 2018, 11:49) *
Поэтому я согласен лишь с одним пунктом (1): за более жесткий контроль числа инициализаторов массива. Имхо, весьма полезная "фишка".
Пусть и не ошибка "вылетает", но хотя бы варнинг.

Код
const int array_size = 3;
int array[] = {1,2};
static_assert(sizeof(array)/sizeof(array[0]) == array_size, "ERROR!!!");



--------------------
Вам помочь или не мешать?
Go to the top of the page
 
+Quote Post
k155la3
сообщение May 22 2018, 09:18
Сообщение #69


Профессионал
*****

Группа: Свой
Сообщений: 1 123
Регистрация: 8-03-09
Из: Днепр
Пользователь №: 45 848



Цитата(jcxz @ May 22 2018, 06:16) *
1. Было-бы лучше, если бы в си, при объявлении инициализированного массива с явно указанной размерностью
int m[N] = {1, 2, 3};
компилятор выдавал бы ошибку компиляции если количество инициализаторов не равно N.
. . . .

Код
#ifdef DEBUG
if( m[N-1] == 0x00 ) . . . .
#endif
Ошибка вылезет на этапе исполнения. Но тут вопрос шашечек или ехать. Да и не всегда это ошибка.
А включать-выключать warning - лишние хлопоты. (например 20 процентов массивов надо контролировать на заполнение, а остальные - нет).
Go to the top of the page
 
+Quote Post
Forger
сообщение May 22 2018, 09:25
Сообщение #70


Профессионал
*****

Группа: Свой
Сообщений: 1 215
Регистрация: 22-02-05
Пользователь №: 2 831



Цитата(Nixon @ May 22 2018, 12:13) *
Код
const int array_size = 3;
int array[] = {1,2};
static_assert(sizeof(array)/sizeof(array[0]) == array_size, "ERROR!!!");

Отличное решение!
Но, увы, оно не работает, если явно указать размер массива:
int array[3] = {1,2};
Компилятор не ругается, а последнее значение array[2] он тупо заполнит нулем.
А если речь, например, про float array[3] = { 1, 2 }, то в array[2] будет не ожидаемый float 0.0, а просто 4 нулевых байта... Скверная ситуация ((
И то не факт, что именно так поступит тот или иной компилятор - нужно проверять. Отсюда вопрос: а надо ли?

На край хотя бы встроенная локальная #pragma для анализа подобных массивов.


--------------------
Кругозор некоторых людей - круг с нулевым радиусом. Они называют его "точкой зрения".
Go to the top of the page
 
+Quote Post
Nixon
сообщение May 22 2018, 10:07
Сообщение #71


Гуру
******

Группа: Админы
Сообщений: 2 736
Регистрация: 17-06-04
Из: Киев
Пользователь №: 48



Код
template < int...Params > struct AAA {
  static_assert(sizeof...(Params) == 4, "ERROR!!!");
  int aaa[4] = {Params...};
};
AAA<1,2,3,4> aaa;
Обертку для удобства сделайте сами.

А вообще при желании всяческих проверок и т.п. добро пожаловать в метапрограммирование и stl


--------------------
Вам помочь или не мешать?
Go to the top of the page
 
+Quote Post
Forger
сообщение May 22 2018, 10:33
Сообщение #72


Профессионал
*****

Группа: Свой
Сообщений: 1 215
Регистрация: 22-02-05
Пользователь №: 2 831



Цитата(Nixon @ May 22 2018, 13:07) *
добро пожаловать в метапрограммирование

В данном случае это уже некий сарказм sm.gif




--------------------
Кругозор некоторых людей - круг с нулевым радиусом. Они называют его "точкой зрения".
Go to the top of the page
 
+Quote Post
haker_fox
сообщение May 22 2018, 13:00
Сообщение #73


Познающий...
******

Группа: Свой
Сообщений: 2 963
Регистрация: 1-09-05
Из: г. Иркутск
Пользователь №: 8 125



QUOTE (Forger @ May 22 2018, 18:33) *
В данном случае это уже некий сарказм sm.gif

А чего такого) Мы уже используем прелести Си++11 для микроконтроллеров. Можно и Си++14. Удобно.


--------------------
Выбор.
Go to the top of the page
 
+Quote Post
Forger
сообщение May 22 2018, 13:47
Сообщение #74


Профессионал
*****

Группа: Свой
Сообщений: 1 215
Регистрация: 22-02-05
Пользователь №: 2 831



Цитата(haker_fox @ May 22 2018, 16:00) *
Мы уже используем прелести Си++11 для микроконтроллеров. Можно и Си++14. Удобно.

Аналогично! wink.gif
Сокращается объем текста кода, его проще читать, да и размер прошивки тоже выходит меньше.
Имхо, С++14 пока что рановат в обычных МК-проектах, да и мало кто из компиляторов под МК его полностью держит, но ... (С) "еще не вечер" wink.gif

Но городить метапрограммированием банальную проверку массива на недостающие инициализаторы - это, имхо, уже перебор. Это уже прям "масло масляное", имхо ))
Наверно, проще будет вообще отказаться от таких "странных" инициализируемых не нулем массивов и переделать их под constexpr структуры с явной инициализацией полей.
Например: коды команд, строковые коды запросов/ответов для, например, внешнего модема.

Я знаю лишь одно применение массивов, инициализируемых при объявлении: внешний ресурс в виде jpg-картинки, растровых шрифтов и т. п.
Но обычно они все инициализируются не вручную, а с помощью соотв. внешнего софта.


--------------------
Кругозор некоторых людей - круг с нулевым радиусом. Они называют его "точкой зрения".
Go to the top of the page
 
+Quote Post
Nixon
сообщение May 22 2018, 13:54
Сообщение #75


Гуру
******

Группа: Админы
Сообщений: 2 736
Регистрация: 17-06-04
Из: Киев
Пользователь №: 48



Цитата(Forger @ May 22 2018, 16:47) *
Имхо, С++14 пока что рановат в обычных МК-проектах, да и мало кто из компиляторов под МК его полностью держит, но ... (С) "еще не вечер" wink.gif
IAR ARM начиная с версии 8 поддерживает как 11 так и 14. Да и разница между 11 и 14 заметна не любому глазу.

Цитата
Но городить проверку массива на недостающие инициализаторы метапрограммированием - это, имхо, уже перебор. Это уже масло масляное, имхо ))
Наверно, проще будет вообще отказаться от таких "странных" инициализируемых не нулем массивов и переделать их под constexpr структуры с явной инициализацией полей.

Посмотрите в сторону std::array. С ним можно делать все тоже самое.


--------------------
Вам помочь или не мешать?
Go to the top of the page
 
+Quote Post
Forger
сообщение May 22 2018, 14:05
Сообщение #76


Профессионал
*****

Группа: Свой
Сообщений: 1 215
Регистрация: 22-02-05
Пользователь №: 2 831



Цитата(Nixon @ May 22 2018, 16:54) *
IAR ARM начиная с версии 8 поддерживает как 11 так и 14.

ARM со своими компиляторами (встроены в Keil и DS-5) тоже держит 14.
11 - полностью держит только v6, а v5 - почти все, кроме "мелочей," которые скорее всего мало кто использует.
14 - ни кто из них де не поддерживает полностью ((
17 - не пришло время, рано еще ))

Цитата
Да и разница между 11 и 14 заметна не любому глазу.

Я бы сказал больше - не многие заметят разницу между C++03 и C++11 wink.gif

Цитата
Посмотрите в сторону std::array. С ним можно делать все тоже самое.

Знаю, но в силу гораздо бОльшей абстракции std::array, увы, не везде можно прямо использовать ((
Особенно, если речь идет про куски кода, критичные к скорости выполнения или чужие куски кода, в который порой лучше и не соваться.



--------------------
Кругозор некоторых людей - круг с нулевым радиусом. Они называют его "точкой зрения".
Go to the top of the page
 
+Quote Post
jcxz
сообщение May 22 2018, 14:20
Сообщение #77


Гуру
******

Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713



Цитата(Forger @ May 22 2018, 11:49) *
Это легко реализовать в run-time, всего один раз запускать проверку на дубликаты значений.

Всё что может делаться в build-time там и должно делаться. Хотя бы потому что эти данные являются аргументами для других вычислений выполняемых также в build-time. Тогда и все их придётся тоже в runtime переносить добавляя кучу лишнего кода, снижая эффективность.

Цитата(Forger @ May 22 2018, 11:49) *
Кстати, мне еще никогда не приходилось сталкиваться с таким - механизм, в котором одинаковые значения запрещены, и в чужом коде тоже.
По мне - экзотика laughing.gif .

Я выше писал области применения этого.
Я не знаю как Вы свои исходники пишете, но у меня есть общий файл описания ресурсов периферии для проекта, где описываются используемые ноги, каналы DMA, вектора прерывания, номера UART-ов, таймеров и пр. Между ними есть зависимости. И если я меняю скажем UART0 на UART1, то потом нужно вспоминать какие с ним связаны UART-ы или DMA-каналы или вектора прерываний. И кроме того - проверять ещё все остальные на возможные конфликты с ними. Это куча ненужной работы. Которую лучше поручить компилятору.
Это одна из очевидных областей применения. Очень важная.
Или Вы всё пересчитываете вручную и используемые ресурсы записываете числами в исходник? Тогда сочувствую тем, кто будет это сопровождать/модифицировать laughing.gif

Цитата(ViKo @ May 22 2018, 12:03) *
Что-то типа unique_case в SV? Атрибут такой ввести? Ну, пусть. santa2.gif

Типа того. Или просто отдельное зарезервированное слово.

Цитата(Forger @ May 22 2018, 16:47) *
Наверно, проще будет вообще отказаться от таких "странных" инициализируемых не нулем массивов и переделать их под constexpr структуры с явной инициализацией полей.

Отказаться от константных массивов??? wacko.gif А как жить?
И что странного в массивах констант и зачем их инициализировать нулями??? blink.gif
Go to the top of the page
 
+Quote Post
Forger
сообщение May 22 2018, 14:41
Сообщение #78


Профессионал
*****

Группа: Свой
Сообщений: 1 215
Регистрация: 22-02-05
Пользователь №: 2 831



Цитата(jcxz @ May 22 2018, 17:20) *
Всё что может делаться в build-time там и должно делаться. Хотя бы потому что эти данные являются аргументами для других вычислений выполняемых также в build-time. Тогда и все их придётся тоже в runtime переносить добавляя кучу лишнего кода, снижая эффективность.

Элементы массива будут использоваться в build-time только если массив идет как constexpr. В противном случае от run-time никуда не деться.
С другой стороны проверку числа инициализаторов можно делать в run-time через обычный assert.
В Release сборку такие проверки разумеется никогда не должны попадать. Полагаю, что это подразумевается само собой.


Цитата
Но у меня есть общий файл описания ресурсов периферии для проекта, где описываются используемые ноги, каналы DMA, вектора прерывания, номера UART-ов, таймеров и пр. Между ними есть зависимости. И если я меняю скажем UART0 на UART1, то потом нужно вспоминать какие с ним связаны UART-ы или DMA-каналы или вектора прерываний. И кроме того - проверять ещё все остальные на возможные конфликты с ними. Это куча ненужной работы. Которую лучше поручить компилятору.


У меня почти все эти зависимости заложены внутри соотв. библиотеки, однажды отлажены и подключаются к проектам в виде библиотеки.
Построение проекта иное - все сложено не в один файл, а разложены по соотв. модулям с целью минимизации связей модулей друг с другом.
Так проще переносить модули из одного проекта в другой. Камень (ядро) значения не имеет. Изменения в коде весьма минимальные и касаются лишь соотв hpp-файла модуля.

Цитата
Отказаться от константных массивов??? wacko.gif А как жить?

Я к этому не призывал, а предложил заменить такие массивы на другие сущности.
Это позволяет вообще отказаться от проверки числа инициализаторов. "Проблема" отпадает сама собой, да и код читается проще.
Кстати, приведите какой-нить конкретный пример. Попробуем сообща разобраться, как это лучше "обойти" wink.gif А то мне на ум, увы, ничего не приходит ((

Цитата
и зачем их инициализировать нулями???
В этом случае я имел ввиду обычные массивы в ОЗУ.


--------------------
Кругозор некоторых людей - круг с нулевым радиусом. Они называют его "точкой зрения".
Go to the top of the page
 
+Quote Post
jcxz
сообщение May 22 2018, 15:11
Сообщение #79


Гуру
******

Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713



Цитата(Forger @ May 22 2018, 17:41) *
Элементы массива будут использоваться в build-time только если массив идет как constexpr. В противном случае от run-time никуда не деться.

Какого массива? Вы вообще о чём??? Хотя-бы смотрите на что отвечаете. Отвечаете на вот это сообщение:
https://electronix.ru/forum/index.php?showt...t&p=1562937
причём тут какие-то массивы?

Цитата(Forger @ May 22 2018, 17:41) *
У меня почти все эти зависимости заложены внутри соотв. библиотеки, однажды отлажены и подключаются к проектам в виде библиотеки.
Построение проекта иное - все сложено не в один файл, а разложены по соотв. модулям с целью минимизации связей модулей друг с другом.
Так проще переносить модули из одного проекта в другой. Камень (ядро) значения не имеет.

Вы кому эти сказки рассказываете? Здесь форум не домохозяек вроде как.
Как Вы умудрились создать такую универсальную библиотеку, которая и на STM32 знает какие каналы DMA к какой периферии подключены и какие вектора прерываний и на какие ноги какая периферия выходит. И эта же либа и на LPC и на Tiva и на Infenion и на куче других МК? И всё она одна сама всё определяет?
Она видимо и про новые ещё только выходящие МК уже всё знает что и с чем связано и "давно отлажена"... biggrin.gif
Видимо она сразу даташиты сама читает и куда что надо туда и подключает. Супер-мега либа! biggrin.gif biggrin.gif biggrin.gif

Цитата(Forger @ May 22 2018, 17:41) *
Кстати, приведите какой-нить конкретный пример. Попробуем сообща разобраться, как это лучше "обойти" wink.gif А то мне на ум, увы, ничего не приходит ((

например имеем некий список:
enum {
OSCSRC_ADC_IU, OSCSRC_ADC_IV, OSCSRC_ADC_IW, OSCSRC_ADC_POWER, OSCSRC_RATE,
OSCSRC_n};
последнее значение - кол-во элементов списка значений OSCSRC_...
Для каждого из элемента есть свойство 1:
static u8 const oscsrcSize[OSCSRC_n] = {2, 2, 2, 2, 10};
А также есть свойство 2:
static char const oscsrcName[OSCSRC_n * 5 + 1] = "Iu\0\0\0" "Iv\0\0\0" "Iw\0\0\0" "Uz\0\0\0" "Rate\0";
А также есть свойство 3:
struct {
u8 typ;
u8 index;
} static u32 const oscsrcFormat[OSCSRC_n] = {{1, 0}, {1, 0}, {1, 0}, {2, 0}, {3, 2}};
Эти свойства раскиданы по разным файлам, а enum - в хидере. И очень хочется, чтобы при добавлении элемента в enum и забывании внесения изменения в один из массивов свойств, он бы не скомпилился, а вылетел по ошибке при компиляции.
Go to the top of the page
 
+Quote Post
Forger
сообщение May 22 2018, 16:00
Сообщение #80


Профессионал
*****

Группа: Свой
Сообщений: 1 215
Регистрация: 22-02-05
Пользователь №: 2 831



Цитата(jcxz @ May 22 2018, 18:11) *
Как Вы умудрились создать такую универсальную библиотеку,

Не библиотеку, а библиотекИ. Под каждое семейство своя библиотека (lib-файл), но интерфейс практически одинаковый - базовый класс, шаблоны-наследники и т. п. Поэтому легко переносится платфморозависимый код от проекта к проекту.
Учесть все вариации невозможно, поэтому контроль за правильностью подключения тех же каналов DMA возлагается на программера, т.е. на меня. И без даташита, разумеется, никуда.

Цитата
например имеем некий список:...
Эти свойства раскиданы по разным файлам, а enum - в хидере. И очень хочется, чтобы при добавлении элемента в enum и забывании внесения изменения в один из массивов свойств, он бы не скомпилился, а вылетел по ошибке при компиляции.

Если эта конструкция может эволюционировать и ее функционал может в будущем сильно измениться, то я бы весь этот толстый функционал сделал бы на плюсах (классы/шаблоны).
Более конкретное решение в этом случае сильно зависит от того, как это будет использоваться в коде.

Как это у вас все используется и как должно размещаться в С и H файлах?


--------------------
Кругозор некоторых людей - круг с нулевым радиусом. Они называют его "точкой зрения".
Go to the top of the page
 
+Quote Post
_pv
сообщение May 22 2018, 16:08
Сообщение #81


Гуру
******

Группа: Свой
Сообщений: 2 563
Регистрация: 8-04-05
Из: Nsk
Пользователь №: 3 954



Цитата(jcxz @ May 22 2018, 21:11) *
Эти свойства раскиданы по разным файлам, а enum - в хидере. И очень хочется, чтобы при добавлении элемента в enum и забывании внесения изменения в один из массивов свойств, он бы не скомпилился, а вылетел по ошибке при компиляции.

http://www.pixelbeat.org/programming/gcc/static_assert.html
Go to the top of the page
 
+Quote Post
jcxz
сообщение May 22 2018, 16:35
Сообщение #82


Гуру
******

Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713



Цитата(Forger @ May 22 2018, 19:00) *
Учесть все вариации невозможно, поэтому контроль за правильностью подключения тех же каналов DMA возлагается на программера, т.е. на меня.

А программёру свойственно ошибаться, ибо человек. Вот для этого это и нужно - чтобы возложить всю рутинную работу на компилятор.

Цитата(Forger @ May 22 2018, 19:00) *
Как это у вас все используется и как должно размещаться в С и H файлах?

Я же написал: в хидере прописан список (enum), а в тех местах где для элементов этого списка надо получать какие-то константные значения (свойства), прописаны указанные массивы.
Сейчас пока обхожусь просто: при добавлении/удалении элемента список - поиск по всем исходникам последнего элемента списка OSCSRC_n (последний элемент в таких списках у меня - это количество элементов). А в каждом массиве есть это количество (OSCSRC_n).
Но лучше чтобы такую работы делал компилятор, если вдруг отвлекусь на что-то и не скорректирую количество элементов в одном из массивов - чтобы он пнул меня.
Go to the top of the page
 
+Quote Post
Forger
сообщение May 22 2018, 16:57
Сообщение #83


Профессионал
*****

Группа: Свой
Сообщений: 1 215
Регистрация: 22-02-05
Пользователь №: 2 831



Цитата(jcxz @ May 22 2018, 19:35) *
А программёру свойственно ошибаться, ибо человек. Вот для этого это и нужно - чтобы возложить всю рутинную работу на компилятор.

Это у меня в планах, но пока обхожусь без этого. Ошибок пока что не было. Наверно, дело в том, что уже научился быстро находить ошибки и приучил так себя писать код, что потом было несложно искать в нем ошибки.
Тут как и везде - главное найти некий компромисс ))

Цитата
Я же написал: в хидере прописан список (enum), а в тех местах где для элементов этого списка надо получать какие-то константные значения (свойства), прописаны указанные массивы.

Я имел ввиду применение конкретно этого примера в конкретном коде (куски кода). Ну да ладно, в целом более-менее понятно.

Цитата
Сейчас пока обхожусь просто: при добавлении/удалении элемента список - поиск по всем исходникам последнего элемента списка OSCSRC_n (последний элемент в таких списках у меня - это количество элементов). А в каждом массиве есть это количество (OSCSRC_n).

Тут уже предложили что-нить готовое из std:: array , map.
Конечно, это не совсем compile-time, но тем не менее wink.gif

Цитата
Но лучше чтобы такую работы делал компилятор, если вдруг отвлекусь на что-то и не скорректирую количество элементов в одном из массивов - чтобы он пнул меня.

Еще бы!

Я наверно в подобном случае применил бы фишки от с++11: constexpr и инициализация полей структур прямо в самих структурах. Заодно это позволить вообще отказаться от этих невнятных "магических" наборов в стиле: { 3, 7, 54 }.
Но также придется каждому полю давать имена и конечный код придется корректировать под все это. Правда, однажды.


--------------------
Кругозор некоторых людей - круг с нулевым радиусом. Они называют его "точкой зрения".
Go to the top of the page
 
+Quote Post
Моисей Самуилови...
сообщение May 22 2018, 18:19
Сообщение #84


Частый гость
**

Группа: Участник
Сообщений: 94
Регистрация: 31-03-18
Пользователь №: 102 799



Цитата(DpInRock @ Feb 22 2010, 15:25) *
Оккам не одобряет.

А мы, русские, говорим "Есть такая простота, которая хуже воровства"

Например, "Чем меньше элементов в схеме - тем она надёжней"
За такую простоту и желание "не плодить лишние сущности" УБИВАТЬ надо maniac.gif
Go to the top of the page
 
+Quote Post
haker_fox
сообщение May 23 2018, 00:33
Сообщение #85


Познающий...
******

Группа: Свой
Сообщений: 2 963
Регистрация: 1-09-05
Из: г. Иркутск
Пользователь №: 8 125



QUOTE (Forger @ May 22 2018, 21:47) *
Аналогично! wink.gif
Сокращается объем текста кода, его проще читать, да и размер прошивки тоже выходит меньше.

Единственное, в драйверах, которые работают в прерываниях и должны работать максимально быстро, стараюсь использовать эти прелести аккуратно.

QUOTE (Моисей Самуилович @ May 23 2018, 02:19) *
За такую простоту и желание "не плодить лишние сущности" УБИВАТЬ надо maniac.gif

Вы вроде обещали без эмоций, в соседней теме. Хотя, кто вы такой, что решать кого "убивать". Так кто-то может и вас решить кокнуть. Потом не обижайтесь.


--------------------
Выбор.
Go to the top of the page
 
+Quote Post
Forger
сообщение May 23 2018, 06:36
Сообщение #86


Профессионал
*****

Группа: Свой
Сообщений: 1 215
Регистрация: 22-02-05
Пользователь №: 2 831



Цитата(haker_fox @ May 23 2018, 03:33) *
Единственное, в драйверах, которые работают в прерываниях и должны работать максимально быстро, стараюсь использовать эти прелести аккуратно.

Подавляющее большинство нововведений новых стандартов не влияют на производительность, а влияют лишь на удобство применения и упрощение/сокращение кода.
Вопросов тут больше к тому или иному компилятору, насколько он хорош в новом стандарте. И на качество стандартных библиотек std, без которых от новых стандартов толку мало.
Да и более свежий компилятор, даже если не использовать фишки новых стандартов, все равно лучше топчет старый код. Хоть немного, но лучше.


--------------------
Кругозор некоторых людей - круг с нулевым радиусом. Они называют его "точкой зрения".
Go to the top of the page
 
+Quote Post
haker_fox
сообщение May 23 2018, 07:00
Сообщение #87


Познающий...
******

Группа: Свой
Сообщений: 2 963
Регистрация: 1-09-05
Из: г. Иркутск
Пользователь №: 8 125



QUOTE (Forger @ May 23 2018, 14:36) *
Подавляющее большинство нововведений новых стандартов не влияют на производительность, а влияют лишь на удобство применения и

Я имел в виду друго. Например контейнеры не использую в прерываниях. Они же могут к malloc (new) обрщаться. А делать выделение памяти не комильфо, например в векторе прерывания. Но здесь есть, конечно, нюансы.
QUOTE (Forger @ May 23 2018, 14:36) *
Да и более свежий компилятор, даже если не использовать фишки новых стандартов, все равно лучше топчет старый код. Хоть немного, но лучше.

Надеюсь на это, но нужно проверять, если есть заинтересованность.


--------------------
Выбор.
Go to the top of the page
 
+Quote Post
Forger
сообщение May 23 2018, 07:57
Сообщение #88


Профессионал
*****

Группа: Свой
Сообщений: 1 215
Регистрация: 22-02-05
Пользователь №: 2 831



Цитата(haker_fox @ May 23 2018, 10:00) *
Я Например контейнеры не использую в прерываниях.

Ну, само собой в прерываниях вообще нельзя ничего подобного использовать.
Минимум действий: сброс аппаратного флажка (если нужно), семафор/флаг/сообщение "наверх" для соотв. задачи и на выход.



--------------------
Кругозор некоторых людей - круг с нулевым радиусом. Они называют его "точкой зрения".
Go to the top of the page
 
+Quote Post
_pv
сообщение May 23 2018, 08:18
Сообщение #89


Гуру
******

Группа: Свой
Сообщений: 2 563
Регистрация: 8-04-05
Из: Nsk
Пользователь №: 3 954



Цитата(jcxz @ May 22 2018, 22:35) *
Но лучше чтобы такую работы делал компилятор, если вдруг отвлекусь на что-то и не скорректирую количество элементов в одном из массивов - чтобы он пнул меня.


костыли конечно, но вроде работают

Код
#define ASSERT_CONCAT_(a, b) a##b
#define ASSERT_CONCAT(a, b) ASSERT_CONCAT_(a, b)
#define STATIC_ASSERT(e) enum { ASSERT_CONCAT(assert_line_, __LINE__) = 1/(int)(!!(e)) }

enum {OSCSRC_ADC_IU, OSCSRC_ADC_IV, OSCSRC_ADC_IW, OSCSRC_ADC_POWER, OSCSRC_RATE, OSCSRC_n};
static uint8_t const oscsrcSize[] = {2, 2, 2, 2};     //error: enumerator value for 'assert_line_15' is not an integer constant|
static uint8_t const oscsrcSize[] = {2, 2, 2, 2, 10}; //ok

STATIC_ASSERT(sizeof(oscsrcSize) / sizeof(oscsrcSize[0]) == OSCSRC_n);

можно ещё дополнить имя енума более осмысленным выводом об ошибке.
ну а если у кого идиосинкразия на макросы, тоже самое можно и шаблонами сделать.
Go to the top of the page
 
+Quote Post
XVR
сообщение May 23 2018, 12:04
Сообщение #90


Гуру
******

Группа: Свой
Сообщений: 3 123
Регистрация: 7-04-07
Из: Химки
Пользователь №: 26 847



Цитата(jcxz @ May 22 2018, 18:11) *
например имеем некий список:
enum {
OSCSRC_ADC_IU, OSCSRC_ADC_IV, OSCSRC_ADC_IW, OSCSRC_ADC_POWER, OSCSRC_RATE,
OSCSRC_n};
последнее значение - кол-во элементов списка значений OSCSRC_...
Для каждого из элемента есть свойство 1:
static u8 const oscsrcSize[OSCSRC_n] = {2, 2, 2, 2, 10};
А также есть свойство 2:
static char const oscsrcName[OSCSRC_n * 5 + 1] = "Iu\0\0\0" "Iv\0\0\0" "Iw\0\0\0" "Uz\0\0\0" "Rate\0";
А также есть свойство 3:
struct {
u8 typ;
u8 index;
} static u32 const oscsrcFormat[OSCSRC_n] = {{1, 0}, {1, 0}, {1, 0}, {2, 0}, {3, 2}};
Эти свойства раскиданы по разным файлам, а enum - в хидере. И очень хочется, чтобы при добавлении элемента в enum и забывании внесения изменения в один из массивов свойств, он бы не скомпилился, а вылетел по ошибке при компиляции.
Это как бы делается по другому:
Код
// Header file
#define ADC_IU OSC_ITEM(ADC_IU, 2, "Iu\0\0\0", 1, 0)
#define ADC_IV OSC_ITEM(ADC_IV, 2, "Iv\0\0\0", 1, 0)
#define ADC_IW OSC_ITEM(ADC_IW, 2, "Iw\0\0\0", 1, 0)
...
#define RATE OSC_ITEM(RATE, 10, "Rate\0", 3, 2)

#define OSC_ALL \
    ADC_IU OSC_DLM \
    ADC_IV OSC_DLM \
    ADC_IW OSC_DLM \
...
    RATE

// In code

#define OSC_ITEM(id, _1, _2, _3, _4) OSCSRC_##id
#define OSC_DLM ,
enum {
    OSC_ALL ,
    OSCSRC_n
};
#undef OSC_ITEM

...

#define OSC_ITEM(_1, val, _2, _3, _4) val
static u8 const oscsrcSize[OSCSRC_n] = { OSC_ALL };
#undef OSC_ITEM

...

// etc
Go to the top of the page
 
+Quote Post
jcxz
сообщение May 23 2018, 18:49
Сообщение #91


Гуру
******

Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713



Цитата(XVR @ May 23 2018, 15:04) *
Это как бы делается по другому:

Да, так можно и во многих местах я делаю похожим образом (только задаю в #define список всех опций для пункта, а потом для каждого места, где нужно выделить одну из опций, делаю свой специальный макрос).
Но получается слишком кучеряво. И теряется читаемость и теряется си-подобный вид. Так что делать так во всех местах, где используются перечисления - не хочется.

Кстати, разве в:
Цитата(XVR @ May 23 2018, 15:04) *
#define RATE OSC_ITEM(RATE, 10, "Rate\0", 3, 2)
не будет бесконечной макроподстановки RATE? Сомнительно как-то....
Go to the top of the page
 
+Quote Post

7 страниц V   1 2 3 > » 
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 18th July 2025 - 11:14
Рейтинг@Mail.ru


Страница сгенерированна за 0.0267 секунд с 7
ELECTRONIX ©2004-2016