Questions tagged [c]

C — это классический компилируемый стандартизированный слабо статически типизированный императивный язык программирования с ручным управлением памятью, созданный в 1970-х годах Брайаном Керниганом и Деннисом Ритчи. Широко распространен, используется как для написания операционных систем, драйверов и программирования микроконтроллеров, так и для высокоуровневых проектов. Основные идеи: препроцессор, структуры, функции, указатели, указатели на функции.

Компоновка программы

Написанные на С программы традиционно состоят из .h и .c файлов, объединенных между собой с помощью директивы препроцессора #include и так называемых стражей включения (include guard).

Файлы .h содержат интерфейс, а .c — его реализацию.

Граф компоновки больших программ может быть достаточно сложен, и поэтому связанные с неправильным включением ошибки — не редкость.

Стандартная библиотека:

Существует множество стандартизированных функций для ввода/вывода, взаимодействием с ОС, памятью, строками, датой, типами данных, отладки. Подробнее смотрите заголовочные файлы:

assert.h
complex.h
ctype.h
errno.h
fenv.h
float.h
inttypes.h
iso646.h
limits.h
locale.h
math.h
setjmp.h
signal.h
stdarg.h
stdbool.h
stddef.h
stdint.h
stdio.h
stdlib.h
string.h
tgmath.h
time.h
wchar.h
wctype.h

Основные средства абстракции:

  • функции
  • структуры
  • указатели
  • typedef
  • препроцессор
  • указатели на функции

Базовые типы данных:

int
float
double
char

Операторы:

  • Арифметические
  • Логические
  • Побитовые
  • Сравнения
  • Составного присваивания
  • Указатели и члены
  • Остальные

Ключевые слова:

auto
break
case
char
const
continue
default
do
double
else
enum
extern
float
for
goto
if
int
long
register
return
short
signed
sizeof
static
struct
switch
typedef
union
unsigned
void
volatile
while 

Стандарты:

  • K&R C
  • ANSI C
  • C99
  • C11

Самые популярные компиляторы:

  • gcc
  • clang
  • Visual Studio

Известные проекты, эксплуатирующие С:

  • Apache
  • Nginx
  • Linux
  • FreeBSD
  • Windows
  • Quake 3
  • Vim
  • Многие известные базы данных (MySQL, PostgreSQL, Redis и др.)

Влияние на другие языки.

Множество других языков так или иначе имеют заимствования из C, первоначально написаны на C, а также предоставляют интерфейсы для вызова С библиотек, количество которых на сегодняшний день не поддается исчислению. Хорошие примеры — Python и Java.

Примеры:

Приближенное вычисление обратного квадратного корня в движке Quake 3:

float Q_rsqrt( float number )
{
    long i;
    float x2, y;
    const float threehalfs = 1.5F;
x2 = number * 0.5F;
y  = number;
i  = * ( long * ) &y;                       
i  = 0x5f3759df - ( i >> 1 );              
y  = * ( float * ) &i;
y  = y * ( threehalfs - ( x2 * y * y ) );   
y  = y * ( threehalfs - ( x2 * y * y ) );  

return y;

}

Линейный генератор случайных чисел:

#include <stdint.h>
uint64_t s[2]; //Нужно проинициализировать не нулями.

uint64_t xorshift128plus(void) { uint64_t x = s[0]; uint64_t const y = s[1]; s[0] = y; x ^= x << 23; // a x ^= x >> 17; // b x ^= y ^ (y >> 26); // c s[1] = x; return x + y; }

Так называемый void walker. Выполнение приводит к перезагрузке некоторых моделей микроконтроллеров.

((void(*)(void))0)();

Классический пример от 1998 года. Вычисление числа Пи с помощью подсчета площади самой программы.

#define _ -F<00||--F-OO--;
int F=00,OO=00;main(){F_OO();printf("%1.3f\n",4.*-F/OO/OO);}F_OO()
{
            _-_-_-_
       _-_-_-_-_-_-_-_-_
    _-_-_-_-_-_-_-_-_-_-_-_
  _-_-_-_-_-_-_-_-_-_-_-_-_-_
 _-_-_-_-_-_-_-_-_-_-_-_-_-_-_
 _-_-_-_-_-_-_-_-_-_-_-_-_-_-_
_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
 _-_-_-_-_-_-_-_-_-_-_-_-_-_-_
 _-_-_-_-_-_-_-_-_-_-_-_-_-_-_
  _-_-_-_-_-_-_-_-_-_-_-_-_-_
    _-_-_-_-_-_-_-_-_-_-_-_
        _-_-_-_-_-_-_-_
            _-_-_-_
}

См. также:

  1. Существует международный конкурс самых запутанных программ на C.
  2. Перевод нечитаемых заголовков и объявлений функций на английский.
9297 questions
12
votes
4 answers

Зачем использовать uint32_t?

Гарантируется ли, что типы с явным указанием размера (такие, как uint32_t, uint64_t, uint16_t) занимают одинаковое количество памяти на всех платформах (на десктопах, на мобилах, на микроконтроллерах)? Собственно, независимо от ответа, как эти типы…
m9_psy
  • 6,449
12
votes
3 answers

Как сделать работоспособным присваивание main?

Хочу скомпилировать такой код: void function () { puts("Hello world"); } main = function; Местами он компилируется, но при выполнении падает с ошибкой, местами не компилируется: prog.c:5:1: error: initializer element is not computable at load…
Qwertiy
  • 123,725
12
votes
4 answers

Почему языки C-семейства заняли свое "особое" место среди прочих языков программирования

А как вы считаете почему языки C-семейства заняли свое "особое" место среди прочих языков программирования?
fedor-sg
  • 515
12
votes
10 answers

Почему популярность Си увеличивается?

TIOBE Programming Community Index for August 2012 Может мне кто-нибудь пояснить, почему популярность Си увеличивается!? Что на нём вообще пишут, кроме прог для микроконтроллеров, низкоуровневых системных утилит и драйверов?
d9k
  • 295
10
votes
1 answer

Зачем ставить (void) перед printf и другими функциями?

Изучаю С на примере репозитория: https://github.com/ankushagarwal/nweb/blob/master/nweb23.c И собственно вопрос - зачем ставить (void) перед printf и другими функциями? (void)sprintf(...);
Ljil
  • 575
10
votes
3 answers

Как сравнить вещественные числа в Си на больше-меньше?

Как в Си выяснить, какое из вещественных чисел больше? Везде пишут, что нельзя использовать обычные операторы сравнения, но внятного объяснения, как корректно это сделать, я так и не нашел.
pentagon1000
  • 101
  • 1
  • 1
  • 5
10
votes
9 answers

Как правильно склеить две строки в Си?

При исполнении кода #include #include int main() { char *first = "first"; char *second = "second"; char *third = strcat(first, second); } происходит ошибка сегментирования.
stanislav
  • 34,518
  • 27
  • 98
  • 214
9
votes
3 answers

Может ли `free` отработать с ошибкой

Допустим есть кусок кода: char *ptr = (char*)malloc(needed_size); if (!ptr) { error_handling(); } else { do_something_without_freeing_ptr(); free(ptr); ptr = 0; } Может ли вызов free не отработать/отработать неправильно и к каким…
andy.37
  • 7,461
9
votes
1 answer

Как получить аргументы функции?

Здравствуйте. Есть исходник void some_func() { SOME_CODE_HERE; } int main(int argc, char *argv[]) { some_func(1,2,3); return 0; } Вопросы: Как из функции some_func получить аргументы без ассемблерных вставок? Зачем вообще в Си было…
gg4me
  • 538
8
votes
2 answers

Как оформить код в Word для курсача?

Как можно красиво оформить исходный код на языке си для курсовой работы в ворде, которую потом буду печатать?
7
votes
2 answers

Защита от некорректного использования extern в C

Есть ли какая-то - на уровне стандарта - защита от некорректного использования объявлений extern в C? Например, пусть в одном файле есть extern int global; в другом - double global = 3.1416; Ведь mangling имен - это только в C++, который,…
Harry
  • 221,325
7
votes
3 answers

Семантика объявлений 2D-массивов в Си

Не могу понять семантику следующего выражение на Си: char (*daytab)[13] Оно эквивалентно такому выражению: char daytab[2][13] В первом выражении сообщается, что так объявленный параметр функции - указатель на массив из 13 элементов. Наличие…
typemoon
  • 2,517
7
votes
1 answer

Какой тип данных правильно использовать как логический в C?

Какой тип данных правильно использовать как логический в C?
Nicolas Chabanovsky
  • 51,426
  • 87
  • 267
  • 507
7
votes
1 answer

Правильность популярного выражения для функции копирования строк в языке Си { while (*dest++ = *src++) }

Начал читать учебник "Программирование: Введение в профессию" Том №2 "Системы и сети" автора А.В. Столярова, в котором рассматривается язык программирования Си. В теме про указатели и строковые массивы (стр.96) есть небольшой пример реализации…
Artem
  • 497
7
votes
5 answers

Странный код с двойным long

Увидел в коде вот такое выражение: long long value = ...; Почему здесь long 2 раза? Это опечатка или такое корректно и действительно что-то значит? Если так, то что изменится, если один long стереть или если, наоборот, дописать еще один?
angry
  • 8,677
  • 18
  • 74
  • 182
1
2 3
99 100