Перейти к содержанию
    

Почему для GCC следующий код в полном порядке?

8 часов назад, jcxz сказал:

Я могу привести множество примеров, когда ваш подход приведёт не то, что к потере нескольких тактов, а к очень существенному перерасходу ресурсов.

ну приводите. че от этого изменится? Вы хотите убедить тут народ что передача одного адреса структуры даст какоето пенальти по сравнению по рассовыванию данных по аргументам? 

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

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

2 часа назад, AlexRayne сказал:

ну приводите. че от этого изменится? Вы хотите убедить тут народ что передача одного адреса структуры даст какоето пенальти по сравнению по рассовыванию данных по аргументам? 

Может не будет передёргивать? Ok? Что именно я писал, можно прочитать выше.

2 часа назад, AlexRayne сказал:

И чего Вы доказываете мне, что такие же монстры не получаются с Вашим подходом? да запросто

Ещё раз - не надо передёргивать! Что и кто писал - всё можно прочитать:

11 часов назад, AlexRayne сказал:

И даже если надо мало аргументо передавать - все равно рулят. Маленькие структуры тож в регистрах неплохо передаются.

Здесь вы топите не за использование структур в "монстрах", а за использование их во всём подряд. В том числе и в функциях с 2-3 аргументами.

И приведите пожалуйста пример передачи "в регистрах" структуры с тремя членами? Код и листинг в студию просим!

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

11 hours ago, jcxz said:

Как правило = ~95% моих функций не используют стек для локальных переменных (кроме как для сохранения в случае вложенных вызовов других функций).

Ну так для большинства функций при передаче аргументов через стэк упакованными в структуру ничего не поменяется, так как если функция делает что-то сложнее чем return a+b, то они там всё равно окажутся при вызове вложенной функции.

Что заворачивание пары агрументов в структуру для передачи в функцию, что функция с десятком однотипных аргументов выглядит одинаково коряво.

А инициализация стуктуры прям в вызове функции позволяет делать именованные аргументы, а не только по порядку, и без простыней кода, но ценой аж пары лишних push при вызове функции. Если это вдруг настолько критично для быстродействия "оптимизировать" надо явно где-то не в этом месте.

59 minutes ago, jcxz said:

И приведите пожалуйста пример передачи "в регистрах" структуры с тремя членами? Код и листинг в студию просим!

у х86_64 соглашение о вызовах виндовса обязывает всё что в 8 байт влазит передавать как есть, а не по указателю, в том числе и через регистры, так что структура с 4мя uint16_t будет целиком засунута в регистр.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

23 часа назад, _pv сказал:

У верилога с разнообразием типов изначально было довольно бедно и перепутать местами clk и rst у модуля с парой десятков аргументов несколько проще. В том же С компилятор не даст поменять местами double и указатель на строку.

C компилятор без проблем даст поменять местами double и int. Или int и int. Или double и double... От этого не легче -- вкрадывается подлая ошибка, замыленный глаз не видит, проявляется это где-то в другом месте, отладка весьма муторна и сильно портит продуктивность. Проблема общая: если параметров больше 3, запоминать это уже тяжело. Просто в HDL в отличие от конвециональных ЯП в силу своей природы в норме могут иметь десятки параметров (портов модуля), поэтому там сразу озаботились именованными аргументами.

 

23 часа назад, _pv сказал:

С (в отличии от плюсов) вроде умеет в человеческую инициализацию структур

С++20 тож могёт (и тип явно приводить не надо):

struct lparams_t { int pos_x; int pos_y; int len; int color; int win; };

void draw_line(lparams_t params) { ... }

int main()
{    
    draw_line( {.pos_x = 10, .pos_y = 20, .len = 100, .color = 0, .win = 1}  );
    
    return 0;    
}

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

#include <iostream>

struct Point { int x; int y; };

struct Line
{ 
    Line(int o) : owner(o) { }

    Line &start(Point p) { p1 = p;     return *this; }
    Line &end(Point p)   { p2 = p;     return *this; }
    Line &col(int c)     { color  = c; return *this; }

    void draw() { std::cout << "owner: " << owner << " | "
                            << " p1.x: " << p1.x << ", p1.y: " << p1.y << " | "
                            << " p2.x: " << p2.x << ", p2.y: " << p2.y << " | "
                            << " color: " << color <<  std::endl; }

    int   owner; 
    Point p1;
    Point p2; 
    int   color; 
};

int main()
{    
    int win_handler = 1;
    Line(win_handler).start({10, 20}).end({30, 40}).col(0).draw();
    Line(win_handler).start({11, 22}).end({33, 44}).col(5).draw();
    Line(win_handler).start({55, 66}).end({77, 88}).col(9).draw();
    
    return 0;    
}

Выхлоп:

owner: 1 |  p1.x: 10, p1.y: 20 |  p2.x: 30, p2.y: 40 |  color: 0
owner: 1 |  p1.x: 11, p1.y: 22 |  p2.x: 33, p2.y: 44 |  color: 5
owner: 1 |  p1.x: 55, p1.y: 66 |  p2.x: 77, p2.y: 88 |  color: 9

Разумеется, графика на С++ так не пишется, там в полный рост ООП с иерархиями классов, наследованием и виртуальными функциями, здесь просто принцип показан. Писанины при вызове не больше, читабельность на уровне -- сразу понятно без изучения формальных параметров, что тут к чему.

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

При написании кода я пользуюсь средствами подсветки синтаксиса в IDE/редакторах, иначе на кой хрен они нужны, давайте дальше на скалах рисовать))

А при чтении кода я не заостряю внимание на порядке аргументов функций, если только это не бросается в глаза. Главное - логический смысл исходника.

ИМХО, готовые исходники не изучают до букв. Они уже написаны. При отладке, уж извините, ошибки вида "перепутал порядок аргументов функции" обнаруживаются практически сразу. Или настоящие гуру программирования 100500 тыщ строк кода добьют, и только потом запускают компиляцию с отладкой? Не верю.

Написанное тяжело читать, когда между осмысленными строками кода находятся простыни заполнения структур. Для меня это имеет ту же боль, которую несут бессмысленные многострочные комментарии, которые не добавляют понимания происходящего, а очевидное я уже итак понял "пробегом глазами".

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

40 минут назад, dxp сказал:

Разумеется, графика на С++ так не пишется, там в полный рост ООП с иерархиями классов, наследованием и виртуальными функциями, здесь просто принцип показан.

https://github.com/id-Software/DOOM-3/blob/a9c49da5afb18201d31e3f0a429a037e56ce2b9a/neo/renderer/Model.cpp#L247C2-L247C2

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вот именно! 🙂 Это в книжках умный дядька Страус... как иво там.. скажет, дескать, надо так-то и так-то и обязательно вот слева направо делать. А на практике, особенно зная формулу "надо еще вчера, пох на всё" самые быстрые даже .start и .end не будут писать. На кой это им, если они и без того видят, где старт, а где энд, сделали и забыли. Реальность, она иная, чем в учебниках, пусть даже и в правильных. Вы знаете, что по инструкции, прежде чем вставить вилку в розетку электросети, нужно убедиться в соответствии напряжения питания электроприбора и напряжения в электросети? И кто на практике об этом хотябы задумывался? Чуть больше, чем никто вообще. Так то.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

4 hours ago, dxp said:
Line(win_handler).start({10, 20}).end({30, 40}).col(0).draw();

Не понимаю, что хорошего в таком коде. Чтобы разобраться, в том, что это последовательный вызов процедур которые лишь делают присвоения, надо всю реализацию просмотреть. А в друг один из метод вернет не *this, откуда мне знать?

Более того, могут быть переопределены операции . и () где-то в иерархии классов. И это я не придумываю, вспомнил, когда-то давно похожий код попадался.

Изменено пользователем amaora

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

8 минут назад, amaora сказал:

Не понимаю, что хорошего в таком коде. Чтобы разобраться, в том, что это последовательный вызов процедур которые лишь делают присвоения, надо всю реализацию просмотреть. А в друг один из метод вернет не *this, откуда мне знать?

Хорошего то, что читается на раз и запись компактная. Реализация тривиальная -- один раз посмотрел и дальше можно не гадать, всё делается одинаково. В программе, которая рисует графику, таких вызовов (рисования объектов), как правило, достаточно много, читается такой код легко, даже если вызовы пишутся в произвольном порядке. Главное, чтобы draw() была в конце.

А если какая-то из функций не вернёт ссылку на себя, получится ошибка времени компиляции.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Just now, dxp said:

А если какая-то из функций не вернёт ссылку на себя, получится ошибка времени компиляции.

Я про то, что она может возвращать ссылку на другой экземпляр например. Тут много вариантов, чего может быть. В отличии от одного вызова draw в который передаются все параметры. Но я не утверждаю, что запихнуть все параметры в draw это лучшее из всех решение.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

С чего бы ей возвращать ссылку на какой-то левый объект? Это надо специально постараться ещё туда этот объект как-то передать. Ну, а от ошибок ни один способ не защищает, одни помогают их минимизировать, другие нет.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вы смотрите со стороны автора этого кода, там все понятно, да. А я оцениваю со стороны, впервые вижу этот код и надо разобраться.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Когда вы встречаете это:

Line({10, 20}, 50, RED, &win);

вам сразу всё понятно, что тут происходит или таки надо посмотреть код этого самого Line? Подозреваю, что таки надо. Ну, и в случае класса это один раз нужно сделать. А если вы знакомы с этим приёмом, то вам и все остальные элементы, выполненные по аналогии, сразу станут понятны, может даже и смотреть не придётся. Приём этот называется Named Parameter Idiom (https://isocpp.org/wiki/faq/ctors#named-parameter-idiom).

Через пару месяцев, когда снова попадётся этот код Line({10, 20}, 50, RED, &win);, скорее всего опять придётся смотреть код этой функции -- какой аргумент там что означает, а вот 

Line(win_handler).start({10, 20}).end({30, 40}).col(0).draw();

вопросов скорее всего не вызовет, т.к. идиома запоминается намного легче, чем позиционные параметры какой-то функции, а параметры тут читаются с листа.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Я же не идиому критикую а реализацию на ++. Хотите именованные параметры, значит надо сделать именно их без возможности накрутить внутри неочевидное поведение.

Но это, чего-то далеко от темы уже.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Не догоняю, чем вам реализация так не нравится. Эти функции-члены -- суть интерфейс класса. Через них устанавливаются значения объекта -- это тут для простоты написана struct, а в норме это class, где представление сокрыто и защищено. Всё общение только через явный интерфейс. Поведение его простое и прозрачное. Это самый что ни на есть базовый С++, что тут может быть не так с реализацией, не пойму. А в этом примере просто вызовы функций зацеплены в "паровозик", только и всего.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Гость
Эта тема закрыта для публикации ответов.
×
×
  • Создать...