Pull to refresh
40
0
Павлов Николай Александрович @ZyXI

Инженер

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

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


Если мы про Python, Java и т.п. языки, отказавшиеся от поддержки беззнаковых целых, то сравнения с нулём всё равно не избежать.

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

У Python есть отдельная семантика для отрицательных индексов. Конкретно для него был бы другой вопрос, если бы он начинал индексы с единицы: почему в нуле дырка (или что‐то ещё более неожиданное).
У Java: нет, сравнение с нулём все ещё не нужно на большинстве машин, если вспомнить, как представляются знаковые целые в памяти.


Для компьютера разница была пока улучшения в процессоре и оптимизирующих компиляторах её не убрали.

Не во всех. К примеру, в lua первый элемент имеет индекс 1. Насколько я понимаю, причина в том, что большинство массивов — это некоторая область памяти, в которой по порядку располагаются элементы. Если первый элемент имеет индекс 0, то он расположен по адресу (начало массива + 0 ∙ размер элемента). Если 1 — то по адресу (начало массива + (1 − 1) ∙ размер элемента). Т.е. на вычисление адреса элемента нужно потратить на одну инструкцию больше.


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


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

Я не знаю, что не так с ht_clear, что она бы не скомпилировалась, но вызов memset(NULL, 0, 0) — это как минимум unspecified behaviour, которое в некоторых реализациях UB. Или UB уже по стандарту: на SO есть разбор ситуации.


Т.е. её нельзя использовать на пустых таблицах.

Для того, чтобы обобщённый C нормально работал с отладчиком можно заменить макросы на параметризованные макросами #include. Пример: typval_encode.c.h, использование.


Плюсы такой техники:


  • лучше работает с отладчиком и анализаторами кода;
  • можно иметь намного больше параметров, не сходя с ума;
  • можно иметь параметры по‐умолчанию.

Минусы:


  • инстанцирование всегда растягивается на несколько строчек;
  • с помощью этой техники можно определить функции, переменные, типы, числовые константы (через enum), но нельзя макросы;
  • параметры для такого файла загрязняют пространство имён макросов, и при повторном инстанцировании в рамках одной единицы трансляции их приходится очищать;
  • продемонстрированный пример не определяет символов, которые бы использовались в иных единицах трансляции, если это требуется, то работать с .c.h файлами становится ещё менее удобно (но всё ещё не невозможно).

Я учился три курса в МГУ на химфаке, и там были философия, история России, история кафедры, ещё, кажется, экономика. Предпоследняя особенно запомнилась тем, что я пришёл на зачёт заранее (что я обычно делаю, а не с целью совершить следующее действие) и т.к. никого не было мне пришла в голову идея написать шпаргалку мелом на стене (стена была весьма светлая, но не белая). И это как‐то прокатило.
А вот собственно содержание лекций по этим предметам не запомнилось совсем.

Меня удивило, что при включении оптимизаций он не сократил весь main до одного ret — тут ни о каком lorem речи не идёт, main же ничего не возвращает, и не имеет никаких побочных эффектов, кроме выделения памяти. Именно так компилятор делает, если заменить vec! на &. Но почему‐то не если убрать vec! полностью (т.е. заменить тип xs с Vec<&'static str> на [&'static str; 3], или на &[&'static str; 3] в первом случае).

В wikipedia всё есть. И это, оказывается, конверты для серии A. Правда, в английском варианте написано немного не так: Cx это геометрическое среднее между Bx и Ax, в основном используемое для конвертов.

Это принято писать в личку — создатели хабра даже сделали так, что при использовании <C-Enter> сообщение отправится именно туда. А то заголовок поправлен, а ваше теперь бесполезное сообщение осталось.

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

В rust есть trait’ы. В C мне вместо них не раз приходилось использовать либо функции, генерируемые макросами, либо .c.h файлы. Не знаю, как называется последняя техника, но уверен, что не я первый её придумал: идея в том, что у нас есть файл frob.c.h вида


// FROB_ACTION has default value.
#ifndef FROB_ACTION
# define _FROB_ACTION_DEFINED
# define FROB_ACTION(a, b) (a) += (b)
#endif

#define _FROB_FUNCNAME(suffix) FROB_PREFIX##suffix

static FROB_RETURN_TYPE _FROB_FUNCNAME(_frobnicate)(int arg1)
{
    FROB_RETURN_TYPE ret = 1;
    FROB_ACTION(ret, 1);
    return ret;
}

#undef _FROB_FUNCNAME

#ifdef _FROB_ACTION_DEFINED
# undef _FROB_ACTION_DEFINED
# undef FROB_ACTION
#endif

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


#define FROB_PREFIX froba
#define FROB_RETURN_TYPE int
#include "frob.c.h"
#undef FROB_RETURN_TYPE
#undef FROB_PREFIX

#define FROB_PREFIX frobs
#define FROB_RETURN_TYPE int
#define FROB_ACTION(a, b) (a) <<= (b)
#include "frob.c.h"
#undef FROB_ACTION
#undef FROB_RETURN_TYPE
#undef FROB_PREFIX

int main(const int argc, const char *const *const argv)
{
    if (froba_frobnicate(argc) > 0) {
        return frobs_frobnicate(argc);
    } else {
        return 0;
    }
}

(#undef тут везде только чтобы не засорять пространство имён).


Такая вариация на тему generic’ов не слишком удобна, но она имеет несколько важных преимуществ перед определением функций в макросах:


  1. В отладчике функции теперь не в одну строку и вы можете нормально ставить точки останова.
  2. Подсветка синтаксиса работает лучше.
  3. Не нужно помнить про \ в конце строки.
  4. Можно сделать аргументы по‐умолчанию.

Из недостатков в первую очередь только бо́льший размер кода. Техника для случаев, когда вы хотите что‐то вроде HashMap<K, V> со всеми его функциями, но в C — т.е. когда кода достаточно много, чтобы вас волновало удобство работы с ним.

C позволяет опускать int во многих случаях. Например, если вы напишете


typedef T;
const A = 1;
main(argc, argv)
    char **argv;
{
    return A;
}

, то компилятор (gcc и clang) поругается на те места, где опущен int, но скомпилирует (на argc clang ругается только с -pedantic). Не знаю, правда, что из этого есть в стандарте, но, учитывая что при указании -std=c89 и gcc, и clang перестают ругаться (у clang надо ещё убрать -pedantic), я полагаю, что такой код был вполне допустим C89.


Также, из имеющихся у меня компиляторов есть ещё tcc, который глотает код без каких‐либо предупреждений, bcc, который отказывается компилировать и pcc, который компилирует данный код без предупреждений, только результат компиляции откуда‐то ловит SEGV.

Эм, так я написал, что у меня восстанавливается при перезапуске несколько окон. И почта/ленты оба оказываются в «первом», и отправить в другое их нельзя. Замечание не про восстановление нескольких окон при перезапуске — эта часть всегда отлично работала, — а про отсутствие контроля за тем, в каком окне функциональность почты доступна и про то, что я не могу иметь почту и ленты в разных окнах.


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

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


Во время беты я как‐то ухитрился получить ленты новостей в новом окне вместо «первого» и был неприятно удивлён тем, что после перезапуска они оказались в другом. Сейчас что‐то не могу повторить.


Мне, собственно, не нужно иметь доступ к почте в нескольких окнах, равно как и к лентам новостей, но хотелось бы, во‐первых, иметь почту и ленты в разных окнах — одна из причин, почему я сейчас использую только RSS. Во‐вторых, иметь возможность указать, в каком именно. В‐третьих, чтобы эти данные сохранялись в сессии.

Ещё можно просто использовать


while True:
    start_time = time.monotonic()
    {code}
    time.sleep(max(interval - (time.monotonic() - start_time), 0))

. Штатный инструмент автозапуска, это, конечно, хорошо, но, во‐первых, с ним вы каждый раз будете платить за запуск процесса Python, чтение всех модулей, …, во‐вторых, останавливать скрипт выше гораздо удобнее. В варианте выше период должен плавать не так сильно.

Если ставят фильтры, то это значит, что вода часто воспринимается как плохая. Скорее всего, это либо означает просто, что она невкусная, что не является синонимом вредности. Равно как и (без)вкусная вода не означает полезности, а для длительного проживания безвредность как‐то важнее. Я бы воду с ледников всё равно бы на всякий случай прогнал через обратный осмос.

У меня есть подозрение, что дело не столько в яйцах, сколько в том, что вода выкипает вся. Соответственно, всё, что пропустил фильтр, окажется в яйцеварке. Если он «простенький», но спасает от накипи, то там, вероятно, уголь (от накипи не помогает никак, но он не для этого) и что‐то с использованием ионного обмена. Последнее оставит на месте то же количество солей, что и до фильтра, просто одни ионы (Ca, Mg) заменяться на другие (скорее всего, Na) — не разлагающиеся от нагрева. При выпаривании эти соли всё равно выпадут.


Хотя, мне кажется, результат должен неплохо растворяться. Может, действительно дело в яйцах: насчёт именно грязи я совсем не уверен, но быстрый поиск показывает, что сама скорлупа состоит в основном из накипи (точнее, карбоната кальция). Вопрос только в том, как при его крайне слабой растворимости он оказывается внизу.

Автор уже написал выше:


В ней яйца не погружены в воду, а вода просто на донышке налита и они варятся в пару.

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

Во‐первых, там есть минерализатор. Конкретно у меня в стандартный комплект поставки даже входит кран, который позволяет забрать воду как до, так и после минерализатора (обычно если минерализатор и есть, то в комплект входит кран только с одним краником). Правда, вода после минерализатора невкусная, поэтому краник «после» там есть, а реально его никто не использует. Плюс, бытовые минерализаторы, насколько я знаю, эффективны только если вода в них постояла.
Во‐вторых, тема в отношении людей весьма спорная и, насколько я знаю, консенсуса сейчас нет: нужные вещества можно и из еды получить. Вот растения такой водой поливать точно не стоит.

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

В Rust нет стандартного выражения для целочисленных перечислений. Для определения типа перечисления используем псевдоним на существующий базовый тип с помощью ключевого слова type. Перечислители объявляем константами.

Вообще‐то есть. У пакета num-traits также есть FromPrimitive, упрощающий каст в такой enum (derive для него поддерживается в отдельном пакете).

Information

Rating
5,689-th
Location
Москва, Москва и Московская обл., Россия
Date of birth
Registered
Activity