Стандард који користим приликом програмирања у програмском језику C
[верзија 1.1, 12. јануар 2022.]
Страхиња РадићОвде ћу описати кодни стандард који користим у програмима које пишем у програмском језику C. До њега сам дошао поступно, током година, и он је инспирисан ГНУ-овим кодним стандардом и suckless стандардом, али се ипак разликује од њих.
У основним цртама се начин на који форматирам код у C-у може описати следећим параметрима програма indent:
-nbad -bap -bbb -bbo -nbc -bl -blf -bli0 -brs -cbi8 -cd40 -ncdw -nce -nlp -ci8 -cli0 -ncs -nbfda -nbfde -di0 -nfc1 -nfca -hnl -i8 -il0 -ip8 -l80 -lc80 -pal -npcs -pi8 -nprs -psl -saf -sai -sar -saw -ts8 -ut
Програм clang-format је понегде бољи, а понегде гори од програма
indent у изражавању моје идеје форматирања кода1. Мој кодни стандард се у том
програму може описати датотеком .clang-format
.
Ипак, овде ћу дати и нешто детаљнији опис.
Увлачење редова и уравнање (-cd40
, -ncs
, -i8
, -il0
, -ts8
, -ut
, -pal
, -psl
)
За увлачење редова првенствено користим знак Tab (ASCII 0x09). Размаке
користим једино када је потребно да се неки делови изворног кода уравнају по
вертикали, на пример (-i8
, -ts8
, -ut
):
int some_var = 10; char a = 'b'; |
⇥int some_var = 10; ⇥char a␣␣␣␣␣␣␣= 'b'; |
Иницијализаторске доделе уравнавам код знака једнакости, што се нажалост не може задати у програму indent. Код уношења изворног кода програма, користим додатак tabular.
/* * */ |
⇥/* ⇥␣* ⇥␣*/ |
Коментаре у истом реду као и код (рецимо, код описивања променљивих у блоку
декларација или код дефиниције struct-а) уравнавам по истој колони. За потребе
задавања параметра програму indent, одлучио сам се да одаберем половину
екрана, -cd40
.
После cast-овања, не користим размак (-ncs
):
char c = (char)v;
Ознаке почињу од почетка реда (-il0
):
void bad_func() { beginning: if (misbehave) goto beginning; }
Показивачке типове у декларацијама уравнавам „слева“ (-pal
):
char* message = "Hello"; FileRecord* fr = NULL;
Да би ово функционисало у програму indent и за кориснички дефинисане типове
(преко typedef), они се морају проследити преко параметра -T
.
Називи функција се налазе у посебном реду (-psl
), што омогућава правилно
функционисање програма за издвајање тагова из изворног кода:
int fact(int n) { if (n <= 1) return 1; else return n * fact(n-1); }
Прелом редова (-bbo
, -l80
, -lc80
)
Редове форматирам тако да се могу комотно читати на стандардном текстуалном
екрану, који је ширине 80 знакова (-l80
). Ово се односи и на коментаре
(-lc80
).
Уколико се ред састоји од дугачког логичког израза, преламам га тако да је нови
ред увучен и почиње логичким оператором (-bbo
):
if ((statement == ST_MOV && *token) || (statement == ST_NOP && !*token))
Блокови (-bl
, -blf
, -bli0
, -brs
, -cbi8
, -ncdw
)
Витичасте заграде после наредби контроле тока почињу у новом реду, и уравнате су
вертикално са кључном речју if (-bl
, -bli0
):
if (!running) { save_files(); clean_up(); }
Витичасте заграде у дефиницијама функција се такође налазе у новом реду, и
уравнате су са називом функције (-blf
):
int main() { printf("Hello, world!\n"); return 0; }
Код struct-ова, витичаста заграда остаје у првом реду (-brs
):
struct Point { int x; int y; };
У switch блоковима, case блокови (које углавном не користим) почињу
витичастом заградом која је увучена у односу на кључну реч case (-cbi8
).
Такође, case ознаке су уравнате са кључном речју switch (-cli0
):
switch (day_of_week) { case MONDAY: { mondays++; log_monday(); } break; case TUESDAY: tuesdays++; break; default: others++; }
Код do-while петље, завршна витичаста заграда је у посебном реду (-ncdw
):
do { on_tick(); } while (running);
слично код if-else конструкције (-nce
):
if (success) { save_file(); print_ok(); } else { print_error(); clean_up(); }
Напомене
У зависности од времена настанка, програми које сам писао могу у мањој или већој мери одступити од овог стандарда.
Фусноте
1. На пример, clang-format тренутно не дозвољава да се код do-while петље завршна витичаста заграда смести у посебан ред. Заузврат, програм indent не подржава уравнање узастопних додела по оператору доделе.