Printf:
http://www.cplusplus.com/reference/cstdio/printf/
https://linux.die.net/man/3/ snprintf
http://man7.org/linux/man-pages/man3/printf.3.html
https://www.cypress.com/file/54441/download

man 3 printf
int printf(const char * limited format, …);
Эта функция записывает данные в стандартный поток вывода. Вывод использует определенный формат в соответствии с strdarg(3).

Ключевое слово limited с указателем указывает на то, что ptr — единственный способ получить доступ к указанному на него объекту, поэтому компилятору не нужно выполнять какие-либо дополнительные проверки (оптимизацию).
https://www.geeksforgeeks. org/restrict-keyword-c/

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

int main(void)
{ printf("Привет %2$d %d %d %3$s %s", 25, 32, "Привет", 27);

Привет 32 25 32 Привет Привет

В этом случае первый указатель обращается ко второму элементу, который имеет десятичный тип, поэтому выводится 32. Когда мы делаем %d и %d дважды, второй указатель снова начинается с первого аргумента, потому что это новый указатель, поэтому вы получаете 25 42. Когда мы делаем %3s, первый указатель затем обращается к третьему элементу, который строка. Когда мы делаем %s, второй указатель продолжает увеличиваться, и теперь мы находимся на «Hello».

int main(void)
{ printf("Привет, %1$f %f %d", 2.54, 32); }

Привет 2,540000 2,540000 32

В этом случае первый указатель указывает на первый аргумент, который является числом с плавающей запятой. Второй указатель предназначен для %f %d, а затем указывает на 2,54 и приращение и указывает на 32.

Общее объяснение: причина, по которой это работает, заключается в том, что $ и без $ имеют отдельные указатели. Если вы попытаетесь получить доступ к строке, когда в качестве следующего аргумента нет строки, вы можете получить ошибку сегментации или ошибку, как показано ниже:
int main(void) { printf("Hello %1$f %f %s”, 2.54, 32); }
Это не сработает, потому что 32 — это цифра/целое число, а не строка.

— — — — — — — — — — — — — — — — — — — — — — — — — — — —
%[флаги][минимальная ширина поля][точность][ длина]спецификатор преобразования
Терминология может быть немного запутанной во всем документе, но следите за правильным использованием приведенных выше слов на этом веб-сайте: http://www.cplusplus.com/reference/cstdio /printf/

  • Спецификаторы преобразования:символ, указывающий тип применяемого преобразования. (d, i, o, u, x, X, f, c, s, p)
  • Модификаторы длины:форматирование целых чисел (diouxX)
    * hh, h, l, ll
    * L
    (f)
  • Символы флажков: за символом % следует ноль или более следующих флажков: #, 0, -, ‘ ‘, +

Преобразования: csp (иначе "идентификаторы формата")
c: символ
s: строка
p: указатель

Преобразования с флагами: diouxX & hh, h, l, ll
d & i: десятичное целое со знаком
o: восьмеричное целое
u: целое без знака
x: шестнадцатеричное целое {0123456789abcdef}
X: шестнадцатеричное целое (заглавная версия), {0123456789ABCDEF}

Длина:
hh: знаковый char или беззнаковый char (1 байт)
h: short int или unsigned short int (2 байта)
l: long int или unsigned lont int (8 байт) → не менее 4 байтов → например. 65000L
ll: long long int или unsigned long long int (8 байт) → например. 65000ЛЛ

Это читает байты справа налево. Давным-давно мы говорили о прямом и прямом порядке байтов и о том, как компьютеры MAC с номером 42 используют прямой порядок байтов, т. е. в данном случае он начинает считать байты справа налево (но смотрите ниже, что происходит на самом деле). Итак, в случае hh…
Если у нас есть десятичное число 578, указанное
0b0000 0010 0100 0010
0100 0010 читается, потому что читается только 1 байт. (правая сторона)

Напомним, порядок следования байтов используется для описания порядка, в котором последовательность байтов хранится в памяти компьютера. Big vs little endian описывает, какое значение сохраняется первым. Big endian означает, что самое большое или самое значимое значение сохраняется первым по самому низкому адресу хранения. В системе с прямым порядком байтов сначала сохраняется наименее значимое значение. Маки используют прямой порядок следования байтов. Таким образом, номер 4F52 технически читается как 524F, что означает, что 42 хранится по адресу 1000, а 4F хранится по адресу 1001.

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

Конверсии: f с флагами l и L
f: float (3.14159)

printf ("Decimals: %d %ld\n", 1977, 650000L);

"%f" - это (или по крайней мере один) правильный формат для двойного числа. Формата для float не существует, потому что если вы попытаетесь передать float в printf, оно будет повышено до double до того, как printf получит его1. "%lf" также допустимо в соответствии с текущим стандартом — l указано как не имеющее никакого эффекта, если за ним следует спецификатор преобразования f (среди прочего). ("Источник")

printf("\n%lf", (двойной)32.3);

Флаги:
l: long или unsigned long

l (ell) Указывает, что (…) не влияет на следующий за ним спецификатор преобразования a, A, e, E, f, F, g или G. Модификатор l требуется в scanf с double, но не в printf . потому что он автоматически продвигается va_args (Источник). Следовательно, %lf и %f эквивалентны.

L: длинный двойной (f)

Управление: %%, #0-+ и пробел

  • %%: % указывает управляющую последовательность формата, используемую для форматирования переменных. Другими словами, вот как написать 20%:

int main(void) {
printf(20%%);
return 0; }

  • #: различное использование
    - #o: добавлен префикс 0
    - #x: префикс 0x добавлен к ненулевым значениям
    - #X: префикс 0X добавлен к ненулевым значениям
    - #f: всегда показывать десятичную точку

printf("%#x", 10); → 0xa

float f = 12;
printf("%#.0f", f); → 12. (.0f дает 12, а # добавляет .)

  • 0: дополняется слева нулями вместо пробелов

printf("Тест: %05d", 10); → 00010

  • - : выравнивание по левому краю

printf("%-10s", "Привет");

  • +: знак числа. По умолчанию для отрицательных чисел отображается знак «-».

printf("%+d", 10);

Минимальная ширина поля:
необязательная строка цифр с ненулевой первой цифрой.

printf(|%5d|, 5); → |’’’’5| ’ указывает на пробелы. 5 символов в поле

Если символов меньше, чем в поле, оно будет дополнено слева (или справа, если используется с флагом выравнивания по левому краю).

printf("|%-5d|", 5); → |5'’’’| ’ указывает на пробелы. 5 символов в поле

Вы также можете использовать * или *m$ (для некоторого десятичного целого числа m), чтобы указать ширину поля в следующем (*) или (m) аргументе. Это должно быть целое число.

printf("|%*d|", 5, 1); → |’’’’1| Следующий аргумент 5 указывает интервал. 1 указывает, что будет напечатано

printf("%d %d |%*3$d|", 5, 1, 10); → 5 1 |’’’’’’’’10|. 8 мест в поле.

Точность:
в виде точки (.), за которой следует десятичная дробь. Это позволяет нам ограничить размер/длину числа. Вы можете использовать * или *m$, аналогично минимальной ширине поля.

Если точность равна «.», тогда точность будет равна 0.

printf(“%.5d”, 20); → 00020
printf(“%.d”, 20); → 20

printf(“%.3f”, 20.0); → 20.000
printf(“%.f”, 20.0); → 20

— — — — — — — — — — — — — — — — — — — — — — — — — — — — — —

man 3 stdarg
https://www.youtube.com/watch?v=-dZpDPFp6YU

Переменный список аргументов, иначе функция может принимать несколько аргументов
#include ‹stdarg.h›

создается объект va_list. Используется макросами ниже

  • void va_start(va_list ap, last);
    Должен вызываться первым.
    Инициализирует ap.
    last — это переменная, переданная в функцию перед многоточием
  • type va_arg(va_list ap, type);
    Отслеживает последнее возвращенное значение аргумента. (Вероятно, указатель. Увеличивайте его, чтобы он возвращал следующее подходящее значение аргумента в списке ap).
  • void va_copy(va_list dest, va_list src);
    Копирует src в dstand, сохраняет состояние в dest (аналогично вызову va_start и va_arg для src).
  • void va_end(va_list ap);
    Вызов указывает на отсутствие дополнительных аргументов. Завершает файл va_start.

целая функция (целое число, …) {

int count = 0;
va_list argptr;

va_start (аргумент, число);

while(count ‹ num)
{ sum+= va_arg(argptr, int);
count++;}
va_end(argptr);
return sum;
}

— — — — — — — — — — — — — — — — — — — — — — — — — — — —
Союзы:
https: //www.youtube.com/watch?v=T976YpsV62w&t=334s
Это определяемая пользователем структура данных, в которой несколько переменных используют одну и ту же ячейку памяти. Это способ сохранить память.

Struct vs Union:
https://www.geeksforgeeks.org/difference-structure-union-c/
Для структуры все элементы получают независимые ячейки памяти. Для объединения все элементы получают одну и ту же ячейку памяти.

Enums:
Enum — это набор констант, которые можно использовать для более читаемого кода. Первый член перечисления по умолчанию равен «0», если вы его не назначите.

typedef enum День недели
{
Вс=1,Пн,Вт,Ср,Чт, Пт, Сб
} WEEKDAY;

ДЕНЬ НЕДЕЛИ wd;
wd = вс;

printf("%d", wd);

Возможная дополнительная функция:
https://blog.alicegoldfuss.com/function-dispatch-tables/
https://github.com/MrColour/ft_printf/ blob/4171d6143cd4fb7d54598c46b1cdde7fee7de708/minimain.c
https://github.com/MrColour/ft_printf/blob/4171d6143cd4fb7d54598c46b1cdde7fee7de708/includes/color.h

Быстрый способ проверить код:
int mine_result;
int syst_result;
#define VERIFY(msg, …) mine_result = ft_printf("[MINE]: |"msg"|\n", ## __VA_ARGS__); \
syst_result = printf("[SYST]: |"msg"|\n", ## __VA_ARGS__); \
if (mine_result == syst_result) \
printf("[РЕЗУЛЬТАТ]: [МОИ]: %d [SYST]: %d\n""\n", mine_result, syst_result); \
else \
printf("[РЕЗУЛЬТАТ]: [МАЙН]: %d [СИСТЕМА]: %d\n""\n", mine_result, syst_result);

— — — — — — — — — — — — — — — — — — — — — — — — — — — — — —

Стандартные целочисленные типы
‹stdint.h› Стандартные целочисленные типы
https://www.nongnu.org/avr-libc/user-manual/group__avr__stdint.html

Рекомендуется использовать стандартные целочисленные типы, а не слова «long long» и «long int», потому что «long long» и «long int» могут различаться в зависимости от компилятора. Длинный int гарантированно будет не менее 32 бит. Длинный длинный int гарантированно будет не менее 64 бит.

Когда мы делаем «int32_t» и int64_t, более прозрачно видеть, сколько битов мы выделяем/просматриваем.

Тип VA_ARG
va_arg преобразует все, что меньше целого числа, в целое число. В результате короткий int и char становятся int.

va_arg преобразует число с плавающей запятой в число с двойной точностью.
https://en.wikipedia.org/wiki/Stdarg.h

Вы можете увидеть ошибку в repl при попытке использовать va_arg(argptr, char). Вы получите следующее сообщение об ошибке:
предупреждение: второй аргумент «va_arg» имеет продвигаемый тип «char»; этот va_arg имеет неопределенное поведение, потому что аргументы будут повышены до «int» [-Wvarargs]

Чтобы избавиться от этой ошибки, вы можете привести ее обратно к char, например
printf("%c", (char)va_arg(argptr, int));

Группы для va_arg (d, i, o, u, x, X, f, c, s, p)
d, i, o, u, x, X, c
ф
с
р

Печать адреса с использованием int64_t
Указатели хранятся как целые числа со знаком. Вы можете преобразовать это целое число в шестнадцатеричное значение, чтобы показать местоположение или адрес, чтобы распечатать его.

Как выполнить отправку в два репозитория
https://stackoverflow.com/questions/14290113/git-pushing-code-to-two-remotes