пʼятницю, 2 січня 2015 р.

Мова С і відповідь на прості запитання - частина 1

На початкових етапах вивчення програмування виникають такі питання:
1. #include <stdio.h> писати в кожній програмі ?
2. int main() чи void main() ?
3. return 0 чи return 1, а іноді return -1 ?

Саме зараз хочеться і поговорити на цю тему, чому ? Краще один раз зрозуміти і робити далі як потрібно, чим забити голову “я пишу так і код працює”. В першій частині ми зробимо огляд, а в другій вже буде погляд з сторони, ОС і асемблера

1. Часто написання коду починається з заголовних файлів #include, в них містяться допоміжні функції для роботи. Наприклад в stdio.h є такі допоміжні функції http://uk.wikipedia.org/wiki/Stdio.h , написати програму простеньку hello world, чи якусь дію можна і без #include <stdio.h>, от докази:

Далі використаємо компілятор Pelles C:


без stdio.h не компілюється, як бачимо все залежить від компілятора. GCC викинув попередження, але зібрав код, а Pelles C ні. Так що все залежить від компілятора і як там влаштовано, також які стандарти ISO ANSI C він підтримує, наприклад Pelles C підтримує С99 і С11 ( це дати прийняття стандартів 1999 і 2011 ). В цьому є деякі зміни в кодові, наприклад в книзі Кернігана і Річі 1988 року, код hello world виглядає так:

// приклад 1
#include <stdio.h>
main()
{
 printf("hello, world \n");

} 
Якщо ви написали код без return 0; , то нічого страшного, компілятор все сам за вас зробить, але писати повернення з програми є правилами хорошого тону, не забуваємо про це.
Друге питання тісно звязана з третім запитанням.

3. return має дві особливих задачі в коді:
1. Вихід з функції, та передати код далі
2. Повернути значення, типу return a+b;
В коді return 0; означає що функція завершилась успішно і без помилки, тому можна її закривати. Якщо ви написали return 1; то це для окремих ситуацій, таких як не відкрився файл, сталась помилка. ВUnix Операційних Системах є таке розуміння, як -1, завершення функції чи програми через сигнал. Це є дуже важливо для ОС, для вас мабуть ні, але в ОС потрібен порядок, що б не зберігати сміття впам'яті, також дані можуть далі оброблятись, а ОС повинна знати чи потрібно це робити далі чи ні ( Якщо помилка, то навіщо робити щось далі ). Розглянемо непоказовий легкий навчальний код:


А по стандарту ANSI C:


// приклад 2
#include <stdio.h>
 
int main (void)
{
    printf ("Hello, World! \n");
    return 0;
}

Як бачимо що в першому випадку немає int перед main(), немає return. Це є одна із проблем інтернету, програмування, та книжок старих. Загрузили новий компілятор, завантажили книжку ще 1988 року і вчимось програмувати. Через це в інтернетах можливо зустріти навіть такі вираження “А я пишу так, бо це швидко працює”, хоча ці дані застаріли, компілятор все збирає по новому і по різному. Автор навіть не заглядає в код асемблера і не розуміє що швидко і чому, лиш того що прочитав це в книжці. Я вважаю що правильно писати як в другому прикладі. Сам автор мови програмування С велів.
Важливо також запам'ятати, якщо програма працює не правильно, то можливо потрібно дописати інші бібліотеки, наприклад, коли ви написали програму по розрахунку будь якої задачі, а рахування проходить не правильно, то швидше за все потрібно дописати:
#include <math.h>
там є функції для роботи по математичній темі.
Ознайомитись з stdio.hйого короткими функціями, та іншими стандартними заголовними файлами можна на сторінці Вікіпедії https://uk.wikipedia.org/wiki/Stdio.h

2. По стандарту ANSI C, правильно int main()а не void main(), void означає, що функція не верне ніякого значення, всі функції void не мають повернень (return), а у нас в коді return 0;. Нуль це десяткове ціле значення, тому правильніше int main().
Якщо ви написали код без return 0; то це не проблема, компілятор все зробить за вас сам , добавить вихід з функції :

#include <stdio.h>
int main (void)
{
FILE *fil;
if((fil=fopen("file.txt", "r"))==0)
{
printf("error open file \n");
return 1;
}
else
{
printf("File open good \n");
}
fclose(fil);
return 0;
}

Як бачимо з коду ми сповістили ОС, якщо файла немає, то це помилка і не варто робити дальше виконання, виходимо, на будь-який випадок закриваємо структуру файла fclose(fil);
Варто і згадати про exit();
exit(0); означає що програма ( не функція) завершилась нормально і можна закривати програму. А еxit(1);сталась помилка.

Сама найголовніша проблема, це те що майбутній програміст не читає як все на справді працює, дивиться на приклади, чи копіює код. Друга справа, це дивитися на свій код і в дизасемблері бачити то що згенерував компілятор, та ще й розуміти шо там. Так що, читаємо, думаємо, експериментуємо, за це ніхто по фейсові не дасть, а лиш покритикує.


Немає коментарів:

Дописати коментар