LINUX.ORG.RU

По-настоящему важный вопрос

 ,


1

3

Куда вы ставите звёздочки и амперсанды при объявлении/инициализации указателей и ссылок, и почему?

  1. T* name, T& name
  2. T * name, T & name
  3. T *name, T &name
  4. Я талиб, я везде использую передачу по значению

P.S. Это не тупой наброс, мне правда интересно кто как делает, может есть весомые причины делать так или иначе, которые открываются с опытом.

Ответ на: комментарий от Forum0888

Из реального впопенсорца, который я рефакторю. Экономия на скобочках:

static void on_copy(GtkAction* act, FmFolderView* fv)
{
    _init_quarks();

    GtkMenu *popup = g_object_get_qdata(G_OBJECT(fv), popup_quark);
    GtkWidget *win = gtk_menu_get_attach_widget(popup);
    GtkWidget *focus = gtk_window_get_focus(GTK_WINDOW(win));

    /* check if we copy inside the view; for desktop focus will be NULL */
    if(focus == NULL || gtk_widget_is_ancestor(focus, GTK_WIDGET(fv)))
    {
        FmPathList* files = fm_folder_view_dup_selected_file_paths(fv);
        if(files)
        {
            fm_clipboard_copy_files(win, files);
            fm_path_list_unref(files);
        }
    }
    else if(GTK_IS_EDITABLE(focus) && /* fallback for editables */
            gtk_editable_get_selection_bounds((GtkEditable*)focus, NULL, NULL))
        gtk_editable_copy_clipboard((GtkEditable*)focus);
}

И такое там везде.

wandrien ★★
()
Ответ на: комментарий от Ivan_qrt

М.б. там имеет смысл объявлять те переменные, в которые могут выделяться какие-то ресурсы, которые нужно будет освободить, чтобы было удобнее следить за этим.

Да, есть такой кейс. Обычно там еще и выходы в конечную часть функции через goto применяются, чтобы ничего не потерять. Чтобы видно было: «вот в начале все ресурсы, которые могут утечь, а вот в конце все эти ресурсы освобождены».

wandrien ★★
()
Ответ на: комментарий от wandrien
static void on_copy(GtkAction* act, FmFolderView* fv)
{
    _init_quarks();

    GtkMenu   *popup = g_object_get_qdata(G_OBJECT(fv), popup_quark);
    GtkWidget *win   = gtk_menu_get_attach_widget(popup);
    GtkWidget *focus = gtk_window_get_focus(GTK_WINDOW(win));

// check if we copy inside the view; for desktop focus will be NULL
//
    if ( focus == NULL ||
         gtk_widget_is_ancestor(focus, GTK_WIDGET( fv ) )
       ) {

     FmPathList  *files = 
      fm_folder_view_dup_selected_file_paths( fv );

      if (files) {

       fm_clipboard_copy_files(win, files);
       fm_path_list_unref(files);

      }

      return;

    }

    if ( GTK_IS_EDITABLE(focus) && /* fallback for editables */
         gtk_editable_get_selection_bounds((GtkEditable *) focus, NULL, NULL)
       )
     gtk_editable_copy_clipboard((GtkEditable*)focus);

Forum0888
()

Вправо, ибо это логичнее, т.к. что звёздочка, что амперсанд относятся именно к переменной стоящей правее, нежели типу слева, в противном случае можно протормаживать видя код уровня int* a = &s, b = k, т.е. * не будет вызывать помутнений, что это и к b относится

AKonia ★★
()
Последнее исправление: AKonia (всего исправлений: 2)
Ответ на: комментарий от wandrien

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

firkax ★★★★★
()
Ответ на: комментарий от Ivan_qrt

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

firkax ★★★★★
()
Последнее исправление: firkax (всего исправлений: 1)
Ответ на: комментарий от firkax

У меня вон там в скинутом примере первым идёт вызов инициализатора _init_quarks();, который и должен быть сразу в начале тела функции, до любого другого кода.

Ты мне предлагаешь как, всю остальную функцию в блок завернуть?

wandrien ★★
()
Последнее исправление: wandrien (всего исправлений: 1)
Ответ на: комментарий от firkax

Тот что записан слева - это базовый тип. К переменной применяется производный от него, который нигде в явном виде не указан.

Как это не указан?

int a, *b;

Сишным по серому написано: указатель на int.

wandrien ★★
()
Ответ на: комментарий от Forum0888

Твой вариант с одной стороны не такой мусорный как «плохой» из двух моих, но с другой (это уже наверно личное предпочтение у меня) фигурные скобки при теле цикла/ифа на отдельной строчке всё-таки нужны, иначе нет наглядного понимания где он кончается.

firkax ★★★★★
()
Ответ на: комментарий от firkax

Квалификаторы не относятся к базовому типу непосредственно, они с ним комбинируются

А комбинируются - это не относятся? Квалификаторы буквально меняют тип, но никакого отношения к нему не имеют, понятно.

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

Ivan_qrt ★★★★★
()
Ответ на: комментарий от wandrien

Нет, тут сразу несколько плохих вещей разной степени плохости:

1) функция _init_quarks() вызывается до объявления переменных

2) инициализация переменных в объявлении (это не строго плохо, но стараюсь такого избегать)

2а) (сразу не заметил) мешаниниа из объявлений и инициализаций в начале - а вот в таком виде это точно плохо

3) фигурная скобка после if (и после заголовка функции) на отдельной строке

4) фигурные скобки до и после else на отдельных двух строках

5) тела нескольких if-ов на отдельных строках без фигурных скобок

6) всякая мелочь типа return; на отдельных строках

Правильно так:

static void on_create_new(GtkAction *act, FmFolderView *fv) {
    const char* name;
    GtkMenu *popup;
    GtkWidget *win;
    GtkUIManager *ui;
    GList *templates;
    FmTemplate *templ;
    FmMimeType *mime_type;
    const char *prompt, *template_name, *label;
    char *_prompt, *header, *basename;
    FmPath *dest;
    GFile *gf;
    GError *error;
    GtkWidget *run_button, *sub_button;
    gboolean new_folder, run_app;
    gint n;

    _init_quarks();
    name = gtk_action_get_name(act);
    popup = g_object_get_qdata(G_OBJECT(fv), popup_quark);
    win = gtk_menu_get_attach_widget(popup);
    ui = g_object_get_qdata(G_OBJECT(fv), ui_quark);
    templates = g_object_get_qdata(G_OBJECT(ui), templates_quark);
    _prompt = NULL;
    error = NULL;
    new_folder = FALSE;

    if(!strncmp(name,"NewFolder",9)) {
        templ = NULL;
        prompt = _("Enter a name for the newly created folder:");
        header = _("Creating new folder");
        new_folder = TRUE;
    } else if(G_LIKELY(!strncmp(name,"NewFile",7))) {
        n = atoi(name+7);
        if(n<0 || !(templ=g_list_nth_data(templates,n))) return; /* invalid action name, is it possible? */
    } else if(G_LIKELY(!strcmp(name,"NewBlank"))) {
        templ = NULL;
        prompt = _("Enter a name for empty file:");
        header = _("Creating ...");
    } else { /* invalid action name, is it possible? */
        return;
    }
    if(!templ) { /* new folder */
        template_name = _("New");
        n = -1;
        run_app = FALSE;
        run_button = NULL;
    } else {
        mime_type = fm_template_get_mime_type(templ);
        prompt = fm_template_get_prompt(templ);
        if(!prompt) prompt = _prompt = g_strdup_printf(_("Enter a name for the new %s:"), fm_mime_type_get_desc(mime_type));
        label = fm_template_get_label(templ);
        header = g_strdup_printf(_("Creating %s"), label ? label : fm_mime_type_get_desc(mime_type));
        template_name = fm_template_get_name(templ, &n);
        run_app = fm_config->template_run_app;
        sub_button = gtk_check_button_new_with_mnemonic(_("_Run default application on file after creation"));
        gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(sub_button), run_app);
        g_signal_connect(sub_button, "toggled", G_CALLBACK(on_run_app_toggled), &run_app);
        run_button = gtk_alignment_new(0, 0, 1, 1);
        gtk_alignment_set_padding(GTK_ALIGNMENT(run_button), 0, 0, 16, 0);
        gtk_container_add(GTK_CONTAINER(run_button), sub_button);
    }
    basename = fm_get_user_input_n(GTK_WINDOW(win), header, prompt, template_name, n, run_button);
    if(templ) { g_free(_prompt); g_free(header); }
    if(!basename) return;
    dest = fm_path_new_child(fm_folder_view_get_cwd(fv), basename);
    g_free(basename);
    gf = fm_path_to_gfile(dest);
    fm_path_unref(dest);
    if(templ) fm_template_create_file(templ, gf, &error, run_app);
    else if(new_folder) g_file_make_directory(gf, NULL, &error);
    else { /* 'NewBlank' */
        GFileOutputStream *f;
        if(f=g_file_create(gf,G_FILE_CREATE_NONE,NULL,&error)) g_object_unref(f);
    }
    if(error) {
        fm_show_error(GTK_WINDOW(win), NULL, error->message);
        g_error_free(error);
    }
    g_object_unref(gf);
}

Кажется тут можно ещё и логику работы почистить, но я исправил только синтаксис - стало выглядеть намного приятнее.

firkax ★★★★★
()
Последнее исправление: firkax (всего исправлений: 2)
Ответ на: комментарий от firkax

але! инициализировать локальные переменные надо в месте обьявления. для этого и ввели обьявление с инициализацией.

переделывайте методическое пособие.

за такое с работы выгоняют, и кидают вслед александерску!

alysnix ★★★
()
Последнее исправление: alysnix (всего исправлений: 1)
Ответ на: комментарий от wandrien

У меня вон там в скинутом примере первым идёт вызов инициализатора _init_quarks();, который и должен быть сразу в начале тела функции, до любого другого кода.
Ты мне предлагаешь как, всю остальную функцию в блок завернуть?

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

firkax ★★★★★
()
Ответ на: комментарий от firkax

Или вот пример:

gchar * su_path_resolve_agent_id_by_path(const char * path, const char * default_id)
{
    if (!path)
        return g_strdup(default_id);

    if (!(_get_res_flags() & RES_AUTODETECTED_DIR))
        return g_strdup(default_id);

    const char * pattern = "/" AGENT_SPECIFIC_RESOURCE "/";

    const char * s = g_strstr_len(path, -1, pattern);
    if (s)
    {
        s = s + strlen(pattern);
        const char * end = g_strstr_len(s, -1, "/");
        if (end)
        {
            size_t agent_id_size = end - s;
            size_t prefix_size = end - path;

            gchar * agent_id = g_strndup(s, agent_id_size);
            gchar * prefix = g_strndup(path, prefix_size);

            if (!autodetected_agent_prefix_table)
            {
                autodetected_agent_prefix_table = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
            }

            g_hash_table_insert(autodetected_agent_prefix_table, agent_id, prefix);

            su_log_debug("path %s autodetected as agent %s with prefix %s\n", path, agent_id, prefix);

            return g_strdup(agent_id);
        }
    }

    return g_strdup(default_id);
}

Здесь если писать по правилам C89, то переменные pattern, s и end (да-да), должны быть объявлены в начале функции. Ну или другой вариант - заворачивать всё в многоэтажные блоки, но так никто в здравом уме не делает, понятно.

А если перед объявлением agent_id_size мне потребуется дописать хоть строчку кода, то и тут тоже придётся переколбашивать всё.

А вот пример, где действительно полезно деление функции на блоки:

    /* overall history */
    {
        overall_nav_history_initialize();
        GtkWidget* mi = gtk_ui_manager_get_widget(ui, "/menubar/GoMenu/RecentlyVisitedMenu");
        win->overall_nav_history_menu = GTK_WIDGET(gtk_menu_item_get_submenu(GTK_MENU_ITEM(mi)));
    }

    /* load bookmarks menu */
    load_bookmarks(win, ui);

    /* file menu  */
    {
        GtkWidget * mi = gtk_ui_manager_get_widget(ui, "/menubar/EditMenu/FileMenu");
        win->file_menu_item = GTK_MENU_ITEM(mi);
        GtkWidget * ancestor_menu_item = gtk_ui_manager_get_widget(ui, "/menubar/EditMenu");
        g_signal_connect(ancestor_menu_item, "select", G_CALLBACK(on_file_menu_item_ancestor_select), win);
    }
wandrien ★★
()
Последнее исправление: wandrien (всего исправлений: 1)
Ответ на: комментарий от firkax

А я надеялся на троллинг, потому что уже на втором пункте стало жирновато.

Штош, теперь остаётся надеяться, что в будущем мне не придётся работать с твоим кодом вообще никогда)))

alex1101
() автор топика
Ответ на: комментарий от firkax

Не заметил там проблем с неймингом.

Вот в том и дело. Потому что в такой каше не заметишь.

И даже cppcheck или gcc -fanalyzer тут не помогут.

Переменная n используется в разных частях функции под два разных назначения. При любых правках этой функции - как говорится, «Удачной отладки!».

wandrien ★★
()
Ответ на: комментарий от firkax

Sorry

static void on_create_new(
 GtkAction     *act,
 FmFolderView  *fv
) {

  const char    *name;
  GtkMenu       *popup;
  GtkWidget     *win;
  GtkUIManager  *ui;
  GList         *templates;
  FmTemplate    *templ;
  FmMimeType    *mime_type;

  const char    *prompt,
                *template_name,
                *label;

  char          *_prompt,
                *header,
                *basename;

  FmPath        *dest;
  GFile         *gf;
  GError        *error;

  GtkWidget     *run_button,
                *sub_button;

  gboolean      new_folder,
                run_app;

  gint          n;

  _init_quarks();

  name       = gtk_action_get_name(
   act
  );

  popup      = g_object_get_qdata(
   G_OBJECT( fv ),
   popup_quark
  );

  win        = gtk_menu_get_attach_widget(
   popup
  );

  ui         = g_object_get_qdata(
   G_OBJECT( fv ),
   ui_quark
  );

...

Гм, поленился в примере инициализировать переменные (в коде у меня всегда инициализация имеется).

Forum0888
()
Последнее исправление: Forum0888 (всего исправлений: 1)
Ответ на: комментарий от firkax

неинициализированная переменная это почти UB. даже по общим соображениям она содержат некий мусор на стеке от предыдущих вызовов.

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

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

по сути это наихудший способ изложения требуемого.

alysnix ★★★
()
Последнее исправление: alysnix (всего исправлений: 1)
Ответ на: комментарий от firkax
static void on_create_new(GtkAction *act, FmFolderView *fv) {
    ...
    gint n;  

    ...

    } else if(G_LIKELY(!strncmp(name,"NewFile",7))) {
        n = atoi(name+7);
        if(n<0 || !(templ=g_list_nth_data(templates,n))) return; /* invalid action name, is it possible? */
    }
    ...
}

А в чём смысл объявления вверху gint n? Я не то что не согласен с этим, я вообще ни одного аргумента «за» в данном случае придумать не могу. Вот вообще не понятно, в чём смысл этого действия и чем это лучше такого:

static void on_create_new(GtkAction *act, FmFolderView *fv) {
    ...

    } else if(G_LIKELY(!strncmp(name,"NewFile",7))) {
        gint n = atoi(name+7);
        if(n<0 || !(templ=g_list_nth_data(templates,n))) return; /* invalid action name, is it possible? */
    }
    ...
}

Можешь объяснить, в чём смысл объявлять эту переменную в начале?

Ivan_qrt ★★★★★
()
Ответ на: комментарий от alex1101

Он шарашит по методичкам середины 90-х. Когда в действующем на то время ANSI C / C89 не было возможности объявлять переменные в любом месте блока.

Поэтому хотя технически Си позволял делать объявления вида, int bla = foo();, руководства по стилю требовали отрывать инициализацию от объявления и класть на отдельную строку.

Потому что наличие исполняемого кода на строке объявления где-то примерно за пару часов работы над кодом неизбежно приводило к необходимости вставить какую-нибудь промежуточную строку кода куда-то между объявлениями. А компилятор этого не позволял.

Поэтому и придумали такой костыль, наученные горьким опытом.

То есть весь вот этот устаревший стайл - это тупо хау-тушка по мотивам набитых шишек «мы так делали и пришли в жопу, поэтому пишем для всех предупреждение - ходите сразу обходной дорогой, она хотя бы в жопу не идёт».

И как только C99 разрешил смешивать объявления с любым кодом - этот костыль стал неактуальным как неактуальны лайфхаки по запуску Жигулей качением с горки.

wandrien ★★
()
Ответ на: комментарий от wandrien

Что-то я не нашёл где.

В начале она заполняется либо в неотрицательный индекс (по которому ищется templ) после NewFile либо в -1 если название не NewFile (и заодно ставится templ=NULL).

Затем она используется тут:

template_name = fm_template_get_name(templ, &n);
я не знаю что делает эта функция, но она либо потребляет исходное значение n из кода выше, либо генерирует новое для кода ниже, и таким образом не может быть «другим назначением».

Ну и в конце n используется для

basename = fm_get_user_input_n(GTK_WINDOW(win), header, prompt, template_name, n, run_button);

Которое, очевидно, возьмёт либо -1 если не NewFile либо какое-то другое число если NewFile. Я что-то пропустил?

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

firkax ★★★★★
()
Ответ на: комментарий от wandrien

Он шарашит по методичкам середины 90-х. Когда в действующем на то время ANSI C / C89 не было возможности объявлять переменные в любом месте блока.

этот человек тащит нас в кговавое пгошлое!

alysnix ★★★
()
Ответ на: комментарий от firkax

А вообще, использование одной и той же переменной для разных целей в разном коде - я тоже так делаю, зачем плодить три временные переменные если можно обойтись одной?

Мы расстаёмся. Не пиши мне больше.

wandrien ★★
()
Ответ на: комментарий от firkax

А вообще, использование одной и той же переменной для разных целей в разном коде - я тоже так делаю, зачем плодить три временные переменные если можно обойтись одной?

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

alysnix ★★★
()
Последнее исправление: alysnix (всего исправлений: 1)
Ответ на: комментарий от wandrien
gchar * su_path_resolve_agent_id_by_path(const char *path, const char *default_id) {
    char const *pattern, *s, *end;
    gchar *agent_id, *prefix;
    if(!path) return g_strdup(default_id);
    if(!(_get_res_flags() & RES_AUTODETECTED_DIR)) return g_strdup(default_id);
    pattern = "/" AGENT_SPECIFIC_RESOURCE "/";
    if(s = g_strstr_len(path, -1, pattern)) {
        s += strlen(pattern);
        if(end = g_strstr_len(s, -1, "/")) {
            agent_id = g_strndup(s, end-s);
            prefix = g_strndup(path, end-path);
            if(!autodetected_agent_prefix_table) {
                autodetected_agent_prefix_table = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
            }
            g_hash_table_insert(autodetected_agent_prefix_table, agent_id, prefix);
            su_log_debug("path %s autodetected as agent %s with prefix %s\n", path, agent_id, prefix);
            return g_strdup(agent_id);
        }
    }
    return g_strdup(default_id);
}

Чего плохого переставить pattern, s, end в начало? Я и agent_id_size и prefix_size собирался, но при ближайшем рассмотрении оказалось что они тавтологические и ненужные, вообще от них избавился. а вот agent_id и prefix перенёс, хотя их и можно было оставить в блоке, но незачем - этот блок по сути основное содержание функции, и его переменные = переменные функции.

А если перед объявлением agent_id_size мне потребуется дописать хоть строчку кода, то и тут тоже придётся переколбашивать всё.

Ну и эта проблема тоже исчезла сама собой.

А теперь сравни исходную простыню, которая у меня даже к экран (15" 768) не влезла и таким образом затруднительно всю её логику оценить одним взглядом (хотя признаюсь не влезло всего несколько строк), и компактный красивый код всего на полстраницы после переделки.

Кстати if(!autodetected_agent_prefix_table) просится сократиться в однострочник но уж слишком длинно получается - перестаёт влезать по горизонтали (да и имя переменной слишком длинное, сократить бы его), не совсем комфортно. Хотя может это потому что я не знаю что он делает. Всякие «залогировать ошибку и вернуть NULL» я спокойно за правую границу экрана отправляю чтобы не засоряли вертикальное пространство экрана с полезной логикой.

Кстати ещё, strstr()+strlen() хорошо бы объединить в единую функцию и тогда нужда в переменной pattern отпадёт. Хотя на самом деле нужды и так нет, это же статическая константа.

firkax ★★★★★
()
Последнее исправление: firkax (всего исправлений: 2)
Ответ на: комментарий от alysnix

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

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

firkax ★★★★★
()
Ответ на: комментарий от firkax

Чего плохого переставить pattern, s, end в начало?

В целом – ничего. Объявлять переменные непосредственно перед их использованием не стоит воспринимать как догму.

Код должен быть ясным.

Поэтому если есть переменные, ради которых код и написан, то их вполне логично объявить в начале функции, и откомментировать.

Касательно стиля этого твоего примера кода, замечаний можно сделать много…

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

Если писать так, то смысл будет понятней, и основной код оборачивать в условный оператор не придется:

s = g_strstr_len(path, -1, pattern));
if(s == 0) return g_strdup(default_id);

...
soomrack ★★★★★
()
Последнее исправление: soomrack (всего исправлений: 2)
Ответ на: комментарий от Ivan_qrt

Можешь объяснить, в чём смысл объявлять эту переменную в начале?

Оно потом ниже используется, вот тут:

template_name = fm_template_get_name(templ, &n);
Если ты её объявишь в блоке то там ниже она видна не будет. Хотя wandrien намекал, что то пересечение тут случайно, но я так и не уверен что он хотел сказать. В любом случае, глобальное n нужно - для вот этой строчки и того что после неё, и дублировать его ещё раз в немешающем блоке незачем.

firkax ★★★★★
()
Ответ на: комментарий от wandrien

Он шарашит по методичкам середины 90-х. Когда в действующем на то время ANSI C / C89 не было возможности объявлять переменные в любом месте блока.

Я не читал никаких «методичек» ни из 90-х ни из других годов. Всё что я тут пишу про стиль - это результат опыта.

Я и сам когда-то раньше вовсю пользовался объявлениями переменных в середине, инициализацией их вызовом функций из объявления и прочими некрасивостями (а ещё вроде какими-то ms-специфичными синтаксисами, т.к. с Си начал знакомиться в качестве msvc5, кстати он позволяет объявления в середине несмотря на то что вышел в 97 году). А ещё я не различал C и C++, и хоть и писал на Си, но файлы у меня были .cpp и я пользовался перегрузкой функций и дефолтными аргументами. Со временем понял что от всех этих якобы удобств вреда больше чем пользы и перестал. Это не было каким-то конкретным моментом, просто плавно сошло на нет. А сейчас при столкновении со своим старым кодом его приходится рефакторить для избавления от всех этих «фич».

Если писать на С++ то это всё в порядке вещей, но не надо путать языки.

firkax ★★★★★
()
Ответ на: комментарий от wandrien

Это все старый стиль, который, к сожалению, все еще очень популярен, т.к. новые книги малодоступны, а учителя учат по старым… в массе.

Стиль формировался под кучей факторов.

  1. Сейчас большую часть кода пишет IDE, в виде автодополнения, ты начинаешь писать имя, а оно уже само его дополняет. Представь, как это делать без IDE. Поэтому короткие имена, сокращения и пр. было просто необходимостью.

  2. Язык развивался. Ты в каком-то комменте правильно отметил, что раньше нужно было объявлять переменные в начале функции… И таких изменений куча – выразительность языка очень изменилась за последние 30 лет.

  3. Размер программ сильно вырос. Теперь большинство работает с объемным кодом, очень объемным, те же фреймворки и пр. Это резко повысило требования к стилю кода… которых раньше не было.

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

soomrack ★★★★★
()
Ответ на: комментарий от alysnix

неинициализированная переменная это почти UB. даже по общим соображениям она содержат некий мусор на стеке от предыдущих вызовов.

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

Есть конкретный кейс, когда переменную желательно оставлять неинициализированной. Вот такой:

int *p;
if (bla)
    p = foobar();
else
    p = barbaz();

В этом случаем мы рассчитываем на то, что умный компилятор (или же тулза типа cppcheck) поможет нам поймать случай, если мы в какой-то ветке забыли присвоить значение p.

wandrien ★★
()