Отговори на тема  [ 25 мнения ]  Отиди на страница Предишна  1, 2
Еквивален на "this" в plain C 
Автор Съобщение
Ранг: Форумен бог
Ранг: Форумен бог

Регистриран на: Нед Фев 26, 2006 5:52 pm
Мнения: 10356
Местоположение: Добрич
Мнение Re: Еквивален на "this" в plain C
gicho написа:
Оттам насетне какво да го плюя повече?


Може да плюеш колкото си искаш, но фактите са:
1. Ц/Ц++ са Turing complete. Демек няма и НЕ може да има език или компютър на който ти да реализаш някакво изчисление, което да не може да бъде реализирано на Ц/Ц++.
2. Това дето цитирах за нулевия овърхед - в Ц/Ц++ няма абсракции или каквото и да е било в езика, което да създава овърхед. Демек няма нещо, което Ц/Ц++ прави, а ти да можеш да го направиш по принцип но по-ефективен начин. Примерно пишейки на асемблер.

От горните две следва, че няма нещо, което да не може да бъде написано на С. Както и това, че ако нещо е написано не Ц/Ц++ не означава, че трябва да работи по-зле само защото е писано на Ц/Ц++.

Изобщо ако имате идеи как нещата да се подобрят, авторът на езика е все още жив и все още работи, така че винаги можете да му пишете. А освен това има организация, която прави стандартите и всеки може да членува в нея. Верно има такса, но не е убийствена и съм готов, ако някой има смислени идея да му покрия таксата.

bateAz написа:
Поради това "this" така и не разбрах как се прави поинтър към member function.


По дефиниция всяка функция без значение дали е мембър или друга си е указател. Така че няма какво да се прави. Просто Цецо явно има структури и в тези структури има указатели към функции и търси как на тези функции да подаде указател към структурата. При Ц++ това си е клас и мембър функции и те си получават this, стига да не са статични естествено.


Сря Мар 11, 2020 11:07 pm
Профил
Ранг: Форумен бог
Ранг: Форумен бог
Аватар

Регистриран на: Пон Сеп 27, 2004 8:22 am
Мнения: 15501
Местоположение: София
Мнение Re: Еквивален на "this" в plain C
gicho написа:
Скритото подаване на инстанция е безсмислено - по-доброто е да се вижда чисто и ясно с коя интанция се вика нещото някъде.


Да, ама това създава възможност за грешки. Например в моя случаи имам множество такива структури и от съвсем тривиални copy/paste грешки е възможно да извикаш функция от една структура с параметър указател към друга структура. Под може, разбирай правил съм го, затова се почесох по главата за някаква автоматизация.

В крайна сметка един опаковащ макрос може да реши проблема, както казах не се имам за кой знае какъв програмист и затова питах, да не би да има някаква добра практика, която не знам.

Хора които бичат код по цял ден, вероятно нямат такива проблеми, но при мен писането е само една част от работата и често бъркам, та ако може нещо да ме спира да си стрелям в краката е добре. Па макар и на цената на някакви други ограничения.

_________________
"Да еба и шибаната държава" мислеше си Гошо, докато се опитваше да улучи кофата за боклук от балкона на осмия етаж.


Последна промяна Цецо на Чет Мар 12, 2020 9:31 am, променена общо 1 път



Чет Мар 12, 2020 9:28 am
Профил ICQ
Ранг: Форумен бог
Ранг: Форумен бог

Регистриран на: Пон Мар 13, 2006 12:59 pm
Мнения: 3855
Местоположение: Габрово
Мнение Re: Еквивален на "this" в plain C
Цитат:
в Ц/Ц++ няма абсракции или каквото и да е било в езика, което да създава овърхед.

Не разбирам какво ми казваш - ако ползвам RTTI има сериозен овърхед. Ако ползвам ексепшъни имам сериозен овърхед. Ако ползвам обект, който е инстанция от сложен (съставен от няколко наследявания) клас имам няколко (не една) вуртуални таблици (по спомен, може и някъде да го оптимизират това). Ако сложа темплейт дори рънтайм кода да не е влошен остава "екстрата" кода да се билдва няколко пъти по-бавно...
Откъм синтаксис - ако искам да итерирам някаква колекция трябва да подавам начало, край, .... Примерно за да направя функционално мап-ване на функция върху всеки елемент от списък:
Цитат:
std::string s("hello");
std::transform(s.begin(), s.end(), s.begin(),
[](unsigned char c) -> unsigned char { return std::toupper(c); });

От тук е примера: https://en.cppreference.com/w/cpp/algorithm/transform
Забелязваш ли как три пъти се подава string-а за да може да се направи toupper() на всеки? А тая простотия с каст-ването наскоро я показвах на колегите че бяха я пропуснали - в един наш проект правеха точно това (toupper на текстове от XML) и това се е билдвало без warning дори на mscv2014. На ГЦЦ стреля грешка и не минава - докато не им показах че по стандарт трябва да се кастне. Интересното е че тръгваш от std::string,ползваш std::toupper и пак трябва да кастваш? Кой прецака типа в горния ред? Да не говорим как щеше да изглежда реда ако нямаше ламбдата с closure-а, която преди 11 я няма. А след като има closure цялата концепция за класове става излишна...
Това, което повече ме дразни е че кода трябваше да е:
Цитат:
std::transfrom( s, toupper);

Или още по-добре:
Код:
s.toupper();

Само че заради избрания подход за memory management това в c++ не може да се опише така.

Както и да е - аз c++ за ембедед не харесвам - не че е лош езика след 11, но за да става за ембедед трябва да са решени няколко неща:
- стандартизиран език - това го има
- компилатор - това също
- рънтайм библиотеки - тука е сложно - няма много ефективни решения; има примерно https://www.etlcpp.com/
- дебъгери, среди и анализатори последните години взеха да покриват специфичните дивотии и конструкции, и още се дънят накъде

Наскоро се борих с std::threading. При първия сблъсък видях че по дефиниция няма стандартизиран начин да дефинираш приоритет на треда. Много хора питат, много им отговарят - създаваш си треда и после търсиш платформено специфичен начин да сетнеш приоритета (примерно с викане на posix функция). Това е специфика на стандарта и доклкото четох имат аргументи от комитета и няма да го променят.

Въпросът е че за да се решиш да минеш на c++ за проект ще трябва да имаш пълно доверие на всичките тия компоненти, за да остане само човешкия фактор.
При мен кодът винаги може да се наложи да се ползва на по-малък таргет, така че дори когато правя нещо за ПЦ трябва да мисля дали след време една функция няма да се наложи да се ползва на микроконтролер. Това значи най-тежките ограничения да ги прилагам при дизайна на почти всеки код. Огромна част от смисления код, който мога да ползвам от други проекти из нет-а не е писан да работи така - иска си я boost, я stl, я нещо друго.

Общо взето това, което работи на ардуиното е максимума от c++, който може да се ползва при ембедед фокус - и не случайно е така. Маса хора се опитват да го ползват и се е видяло което минава. С есп-тата взеха да стават по-разтегливи понятията - там има доста повече ресурс и вървят доста повече екстри - примерно async библиотеката е не-boost варианта си.

Ц++ е по-добър език от C по принцип - няма как да е иначе, в самия език има повече екстри. За мен въпросът е дали миграцията да е от Ц на Ц++ или да е от Ц на по-добър език.
Като потребител нито имам силата, нито нервите да им дават акъл как да си правят езика - моят избор е кой език да ползвам. Може да не харесвам БМВ но няма да им пиша какво да оправят, избирам нещо друго и ползвам.


Чет Мар 12, 2020 9:30 am
Профил
Ранг: Форумен бог
Ранг: Форумен бог

Регистриран на: Пон Мар 13, 2006 12:59 pm
Мнения: 3855
Местоположение: Габрово
Мнение Re: Еквивален на "this" в plain C
Цецо написа:
Да, ама това създава възможност за грешки. Например в моя случаи имам множество такива структури и от съвсем тривиални copy/paste грешки е възможно да извикаш функция от една структура с параметър указател към друга структура. Под може, разбирай правил съм го, затова се почесох по главата за някаква автоматизация.

В крайна сметка един опаковащ макрос може да реши проблема, както казах не се имам за кой знае какъв програмист и затова питах, да не би да има някаква добра практика, която не знам.


Нищо няма да те спре (или твой колега) да повика метод на друг обект (ако беше c++), примерно:
Цитат:
uart0.send("Bla");
uart0.send("-Bla");
uart10.send("\r\n");

компилаторът ще те спре ако на уарт функция подадеш SPI структура - само че за да сработи това се връщаме на една тема отпреди няколко месеца да се възползваме от типовете и да не ги крием в безсмислени абстракции (от типа на хендъл или воид*).
Срещу copy-paste грешки има лесен, но официално скъп начин за борба - pvs-studio се казва продукта на viva64. Има го при руснаците, ползва се лесно и не иска никакви настройки - пускаш "мониторът" му да виси като процес и то дебне за повиквания на gcc. Като ги види ги прихваща и си изважда цялата необходима информация за какво се билдва, къде е сорса, хедъри, символи. Т.е. ти си пускаш нормалния билд от конзола или Еклипс или каквото и да е и то си хваща информацията. Само трябва да му кажеш кога е приключил билда и то ти вади анализа си.
Правен е точно за такива цели - типични грешки от механично копиране и подобни, но това допълнително към много проверки, които има заради стандарти - наскоро вкараха и MISRA, има разните CVE-та.
Другото е code review да се прави, но аз винаги имам недоверие към не-автоматизираните проверки - две ракии предната вечер горница и ревюто е за боклука.


Чет Мар 12, 2020 9:40 am
Профил
Ранг: Форумен бог
Ранг: Форумен бог

Регистриран на: Пон Мар 13, 2006 12:59 pm
Мнения: 3855
Местоположение: Габрово
Мнение Re: Еквивален на "this" в plain C
bateAz написа:
Поради това "this" така и не разбрах как се прави поинтър към member function.

Примерно как да дадеш мембър функция като callback някъде на друг? Това не работи - известен проблем е на c++. Решения има, но директното взимане на адреса на мембър фунцията не може да се ползва.
В новите c++ има std::bind и std::function, които са базата за решаване на този проблем - има го описано и дискутирано.
https://stackoverflow.com/questions/400257/how-can-i-pass-a-class-member-function-as-a-callback


Чет Мар 12, 2020 9:46 am
Профил
Ранг: Форумен бог
Ранг: Форумен бог

Регистриран на: Нед Фев 26, 2006 5:52 pm
Мнения: 10356
Местоположение: Добрич
Мнение Re: Еквивален на "this" в plain C
gicho написа:
Цитат:
в Ц/Ц++ няма абсракции или каквото и да е било в езика, което да създава овърхед.

Не разбирам какво ми казваш - ако ползвам RTTI има сериозен овърхед. Ако ползвам ексепшъни имам сериозен овърхед. Ако ползвам обект, който е инстанция от сложен (съставен от няколко наследявания) клас имам няколко (не една) вуртуални таблици (по спомен, може и някъде да го оптимизират това). Ако сложа темплейт дори рънтайм кода да не е влошен остава "екстрата" кода да се билдва няколко пъти по-бавно...


Примерите, които си дал са някакви решения на проблеми, които не са свързани с езика. Демек RTTI, ексепшъни, обекти и т.н. се слагат когато ТИ искаш да решиш даден проблем по такъв начин, а не защото езика го изисква. Не е казано, че това са най-добрите или най-удобните или най-красивите инструменти. Целта на Ц/Ц++ не е да ти даде всички възможни инструменти, даже напротив - дава ти само инструменти, които ти не може да заместиш с нещо по-ефективно.

Кодът, който се генерира от тези инструменти (или паметта която ядат) е гарантирано без овърхед. Демек, не може да направиш същото, което прави инструмента с по-малко код или с по-малко памет. Още веднъж - никой не те задължава да ползваш един или друг инструмент. Примерно ако можеш да работиш без ексепшъни - никой не те задължава и няма да имаш код, заради ексепшъни. Но ако решиш че трябва да ползваш тая техника, то няма как да виниш С/С++ за какъвто и да било овърхед. За "овърхед" може да говориш само, ако можеш да предложиш алтернатива с по-малко код. Доколкото на мен ми известно а и на повечето програмисти, по-добра алтернатива няма. И точно защото няма по-добра алтернатива ексепшъните се поддържат от езика. Ако имаше по-добра алтернатива ексепшъните нямаше да ги има в С++.

Що се отнася до STL... това не е част от езика. Има много алтернативни библиотеки. За съжаление и STL и всички останали са оптимизирано като за РС и не са толкова подходящи за ембедед. Тук две мнения няма. И аз не съм щастлив от тоя факт, но това е положението...


Чет Мар 12, 2020 10:38 am
Профил
Ранг: Форумен бог
Ранг: Форумен бог

Регистриран на: Нед Фев 26, 2006 5:52 pm
Мнения: 10356
Местоположение: Добрич
Мнение Re: Еквивален на "this" в plain C
gicho написа:
Нищо няма да те спре (или твой колега) да повика метод на друг обект (ако беше c++), примерно:
Цитат:
uart0.send("Bla");
uart0.send("-Bla");
uart10.send("\r\n");

компилаторът ще те спре ако на уарт функция подадеш SPI структура - само че за да сработи това се връщаме на една тема отпреди няколко месеца да се възползваме от типовете и да не ги крием в безсмислени абстракции (от типа на хендъл или воид*).


При "безсмилените" абстракции няма как да объркаш само пращането. Не може да пишеш или четеш от хендъл, без преди това да си го отворил. Абстрактни са операциите като четене/писане, но отварянето не е абстрактно.
Опитите по този начин да ловиш грешки са меко казано наивни. Компилаторът няма как да знае дали искаш да работиш с файл "A.jpg" или "B.jpg". Ако отвориш единия вместо другия файл, проблемът си е изцяло твой и Господ не може да те предпази от подобна грешка. От друга страна ако пишеш различни JPEG библиотеки за всеки файл който ползваш, само за да може компилатора да ти дава грешка то това е много далеч от разбирането ми за програмиране ;-)


Чет Мар 12, 2020 8:07 pm
Профил
Ранг: Минаващ
Ранг: Минаващ

Регистриран на: Чет Юни 04, 2020 5:57 pm
Мнения: 1
Мнение Re: Еквивален на "this" в plain C
Ние тук сме се събрали една тайфа циганета. Още не можем да четем и пишем, но отлепваме малко от Це. Така става покрай електронния скрап, но това е друга история. Ето една програмка за имитация на указател this на чисто Це. Програмката вероятно не решава въпроса, но поне е нещо за отскок.

Код:
#include <stdio.h>
#include <stdlib.h>

typedef struct _struct {
//    struct _struct *that; // redundant
    int a;
    int (*funcPtr)();
} myStruct;

// The second formal argument bears the name "a" on purpose
int func(myStruct *this, int a) {

    (*this).a = a;

    return (*this).a;
}//func

int main() {
// Create an instance
myStruct *foo = (myStruct*)malloc(1 * sizeof(myStruct));

    // Initialise the instance
//    (*foo).that = foo;
    (*foo).a = 0;
    (*foo).funcPtr = func;

    // Test the instance
    printf("%d\n", (*foo).funcPtr(foo, 5)); // should be 5

    // Get rid of the instance
    free(foo);

    printf("All done!\n");
    return 0;
}//main


Чет Юни 04, 2020 6:06 pm
Профил
Ранг: Форумен бог
Ранг: Форумен бог
Аватар

Регистриран на: Пон Юни 05, 2006 12:48 pm
Мнения: 4393
Местоположение: където небето среща земята, ракията е Jameson, а бирата Guinness
Мнение Re: Еквивален на "this" в plain C
samolet4e написа:
Ние тук сме се събрали една тайфа циганета. Още не можем да четем и пишем, но отлепваме малко от Це. Така става покрай електронния скрап, но това е друга история.
..

и за чий е това упражнение :?:
само хабите клавиатурата

_________________
... ако трети ден не ти се работи... това означава, че е сряда !


Чет Юни 04, 2020 6:36 pm
Профил
Ранг: Форумен бог
Ранг: Форумен бог

Регистриран на: Пон Дек 19, 2005 11:21 am
Мнения: 1025
Мнение Re: Еквивален на "this" в plain C
gicho написа:
Забелязваш ли как три пъти се подава string-а за да може да се направи toupper() на всеки?


Да, това е доста досадно повторение, но ще има решение с Ranges & Views -

https://github.com/ericniebler/range-v3


Пет Юни 05, 2020 8:22 am
Профил
Покажи мненията от миналия:  Сортирай по  
Отговори на тема   [ 25 мнения ]  Отиди на страница Предишна  1, 2

Кой е на линия

Потребители разглеждащи този форум: 0 регистрирани и 2 госта


Вие не можете да пускате нови теми
Вие не можете да отговаряте на теми
Вие не можете да променяте собственото си мнение
Вие не можете да изтривате собствените си мнения
Вие не можете да прикачвате файл

Търсене:
Иди на:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group.
Designed by ST Software for PTF.
Хостинг и Домейни