Що повинен знати програміст C? [зачинено]


12

Назвіть деякі поняття / методи / мовні особливості, які повинен знати / знати кожен гідний програміст C (виключайте загальну інженерію програмного забезпечення та подібне та зосереджуйтесь лише на конкретних матеріалах C). Я хотів би знати, щоб я міг заповнити деякі можливі прогалини в моїх знаннях C.


9
Почніть з питань C Stack Overflow і подивіться, чи є щось, чого ви не знаєте.
chrisaycock

3
Програміст змінного струму, мабуть, повинен це знати2 + 2 = 4
Едвард Странд

21
Вони повинні знати про магазин, який продає непробивне взуття.
Адам Кросленд

1
На цю тему написано сотні книг. Ваше запитання дійсно досить розпливчасте. Вам доведеться бути більш конкретними, щоб отримати гідні відповіді, які не є лише списком речей. І бачачи відповіді, згенеровані так далеко від цього питання, я думаю, що його потрібно переробити чи закрити.
Вальтер

2
Ще одна мова програмування?
Мухаммед Алкарурі

Відповіді:


19

Характерно для C? Окрім стандартних конструкцій, загальних для більшості процедурних мов, я б сказав:

  • (ab) з використанням препроцесора
  • Linker vs компілятор
  • Покажчики Покажчики Покажчики!
  • Як масиви - покажчики, - це масиви
  • Як працюють рядки C, і як вони також є вказівниками та масивами
  • Наскільки погане використання рядків C може призвести до переповнення буфера
  • Як кинути що-небудь на що-небудь (це все просто 1 і 0 зрештою :))
  • Управління пам'яттю вручну / мало
  • Стек проти Хіпа
  • Псевдонім вказівника (чому його незаконне в C99)
  • Думаючи про розробку з точки зору модулів (.h / .c файлів) із набором загальнодоступних функцій замість строго класів
  • Союзи
  • Чому спринт може збити вашу ногу
  • Функціональні покажчики

Я додав би "переповнення буфера" до списку.
Айдан Каллі

@ Айдан, хороший улов. Додано.
Дуг Т.

2
Як масиви та вказівники C не однакові: books.google.ca/…
Матьє

покажчики мали бути повторені як мінімум у 3 рази більше
Гаурав

8

Зрозумійте вказівники, і ви зрозумієте комп’ютери.


12
Ні, у вас просто з’явиться ілюзія, що ви розумієте комп’ютери.
Робота

5

Окрім відмінної відповіді пітаграса,

як писати (або принаймні читати) складні декларації, такі як char (*(*funcs[4])())[10]

funcs - це масив [4] покажчиків на функцію, що повертає вказівник на масив [10] char


1
Якщо він стає таким складним, можливо, це належить у коментарі?
Робота

7
може, він повинен навчитися уникати написання?
FabianB

3
  1. Правила просування цілого числа
  2. Ініціалізуйте все до відомого значення
  3. GOTO не є злом, особливо коли використовується для обробки винятків / збоїв
  4. malloc та / або calloc можуть повернути NULL ... переконайтеся, що ваші контрольні значення повернення
  5. Часті невеликі виділення пам'яті можуть викликати фрагментацію на купі.
  6. Арифметика вказівника
  7. Бітові маски - твій друг
  8. x >> 1 еквівалентно x / 2 для непідписаних цілих чисел

+1 для GOTO не будучи злом :)
zvrba

2

Програміст змінного струму повинен знати ... інші мови! ;-) Завжди корисно знати поняття з інших мов різних парадигм, таких як OOP, функціональне програмування тощо.

Більш серйозно, погляд на змагання із затуманеного програмування - це весело і, що цікаво, теж хороший досвід.


2

Я згадав про «переповнення буфера» в коментарі до відповіді Пітаграса, я, мабуть, повинен уточнити, що я мав на увазі трохи. У С недостатньо знати, що робота безпосередньо з пам’яттю небезпечна - ви також повинні розуміти точні шляхи небезпеки. Мені не дуже подобається метафора "стріляй собі в ногу" для всіх цих випадків - багато часу, це не ти запускаєш курок, але часто це актор, який має інтереси, що суперечать твоїм та / або вашим користувачам " .

Наприклад, в архітектурі з низхідним стеком (найпопулярніші архітектури відповідають цьому рахунку - x86 і ARM, як правило, включені), коли ви викликаєте функцію, зворотна адреса функції буде розміщена на стеці після локальних змінних, визначених у тіло функції. Отже, якщо ви оголошуєте буфер як локальну змінну і піддаєте цю змінну зовнішньому світу, не перевіряючи переповнення буфера, наприклад:

void myFn(void) {
    char buf[256];
    gets(buf);
}

зовнішній користувач може надіслати вам рядок, який перезаписує зворотну адресу зі стека - в основному він може змінити уявлення про виконання програми вашої програми про графік викликів, що призводить до поточної функції. Таким чином, користувач надає вам рядок, що є двійковим поданням якогось виконуваного коду для вашої архітектури, достатньо прокладки для переповнення стека myFn, а також додаткових даних, щоб замінити зворотну адресу, myFnщоб вказати на код, який він вам дав. Якщо це трапиться, тоді, коли myFnзазвичай повертається контроль своєму абонентові, він замість цього відгалужується до коду, який надав зловмисний користувач. Якщо ви пишете код C (або C ++), який може піддаватися впливу недовірених користувачів, вам потрібно зрозуміти цей вектор атаки. Ви повинні зрозуміти, чому переповнення буфера до стека часто (але не завжди) легше експлуатувати, ніж один проти купи, і ви повинні розуміти, як пам'ять у купі розкладається (не надто багато деталей, обов'язково, але Ідея про те, що в malloc()регіоні "ЕД" є контрольні структури, може оточувати її, може допомогти зрозуміти, чому ваша програма виходить з ладу в іншому malloc()або в free()).

C піддає вам детальну інформацію про те, як працює ваша машина, і вона надає вам більш безпосередній контроль над вашою машиною, ніж будь-яка інша мова, що редагується користувачем, і широко використовується сьогодні. З великою силою виникає велика відповідальність - вам потрібно зрозуміти ці деталі низького рівня, щоб безпечно та ефективно працювати з C.


0

Окрім інших хороших відповідей, я хотів би додати до списку методи оборонного програмування .

Наприклад, використовуючи ствердження на початку / в кінці функцій для перевірки контракту.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.