Стандард који користим приликом програмирања у програмском језику 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 не подржава уравнање узастопних додела по оператору доделе.