summaryrefslogtreecommitdiffhomepage
path: root/ru-ru
diff options
context:
space:
mode:
Diffstat (limited to 'ru-ru')
-rw-r--r--ru-ru/c-ru.html.markdown87
1 files changed, 37 insertions, 50 deletions
diff --git a/ru-ru/c-ru.html.markdown b/ru-ru/c-ru.html.markdown
index 80f79ffd..0b39586a 100644
--- a/ru-ru/c-ru.html.markdown
+++ b/ru-ru/c-ru.html.markdown
@@ -50,10 +50,10 @@ int main() {
// int обычно имеет длину 4 байта
int x_int = 0;
- // shorts обычно имеет длину 2 байта
+ // short обычно имеет длину 2 байта
short x_short = 0;
- // chars гарантированно имеет длину 1 байта
+ // char гарантированно имеет длину 1 байта
char x_char = 0;
char y_char = 'y'; // Символьные литералы заключаются в кавычки ''
@@ -82,7 +82,7 @@ int main() {
int a = 1;
// size_t это беззнаковый целый тип который использует как минимум 2 байта
// для записи размера объекта
- size_t size = sizeof(a++); // a++ считается во время компиляции
+ size_t size = sizeof(a++); // a++ не выполнится
printf("sizeof(a++) = %zu, где a = %d\n", size, a);
// выведет строку "sizeof(a++) = 4, где a = 1" (на 32-битной архитектуре)
@@ -134,7 +134,7 @@ int main() {
// Операторы
///////////////////////////////////////
- // Можно использовать множественное объявление
+ // Можно использовать множественное объявление.
int i1 = 1, i2 = 2;
float f1 = 1.0, f2 = 2.0;
@@ -184,10 +184,9 @@ int main() {
0x02 >> 1; // => 0x01 (побитовый сдвиг вправо (на 1))
// Будьте осторожны при сдвиге беззнакового int, эти операции не определены:
- // - shifting into the sign bit of a signed integer (int a = 1 << 32)
+ // - сдвиг в знаковый бит у целого числа (int a = 1 << 32)
// - сдвиг влево отрицательных чисел (int a = -1 << 2)
- // - shifting by an offset which is >= the width of the type of the LHS:
- // int a = 1 << 32; // UB if int is 32 bits wide
+
///////////////////////////////////////
// Структуры ветвления
@@ -231,7 +230,7 @@ int main() {
// Ветвление с множественным выбором
switch (some_integral_expression) {
- case 0: // значения должны быть целыми константами (могут быть выражениями)
+ case 0: // значения должны быть целыми константами (и могут быть выражениями)
do_stuff();
break; // если не написать break; то управление будет передено следующему блоку
case 1:
@@ -249,23 +248,23 @@ int main() {
// Форматирование вывода
///////////////////////////////////////
- // Каждое выражение в Си имеет тип, но вы можете привести один тип к другому
- // если хотите (с некоторыми константами).
+ // Каждое выражение в Си имеет тип, но вы можете привести один тип к другому,
+ // если хотите (с некоторыми искажениями).
- int x_hex = 0x01; // Вы можете назначать переменные с помощью шеснадцатеричного кода
+ int x_hex = 0x01; // Вы можете назначать переменные с помощью шеснадцатеричного кода.
- // Приведение типов будет пытаться сохранять цифровые значения
+ // Приведение типов будет пытаться сохранять цифровые значения.
printf("%d\n", x_hex); // => Prints 1
printf("%d\n", (short) x_hex); // => Prints 1
printf("%d\n", (char) x_hex); // => Prints 1
- // Типы могут переполняться без предупреждения
+ // Типы могут переполняться без вызова предупреждения.
printf("%d\n", (unsigned char) 257); // => 1 (Max char = 255 if char is 8 bits long)
// Для определения максимального значения типов `char`, `signed char` и `unisigned char`,
// соответственно используйте CHAR_MAX, SCHAR_MAX и UCHAR_MAX макросы из <limits.h>
- // Целые типы могут быть приведены к вещественным и наоборот
+ // Целые типы могут быть приведены к вещественным и наоборот.
printf("%f\n", (float)100); // %f formats a float
printf("%lf\n", (double)100); // %lf formats a double
printf("%d\n", (char)100.0);
@@ -274,14 +273,11 @@ int main() {
// Указатели
///////////////////////////////////////
- // A pointer is a variable declared to store a memory address. Its declaration will
- // also tell you the type of data it points to. You can retrieve the memory address
- // of your variables, then mess with them.
-
-
- // Указатель – это переменная которая хранит адрес в памяти. При объявлении указателя указывается тип данных переменной на которую он будет ссылаться. Вы можете получить адрес любой переменной, а потом работать с ним.
+ // Указатель – это переменная которая хранит адрес в памяти.
+ // При объявлении указателя указывается тип данных переменной на которую он будет ссылаться.
+ // Вы можете получить адрес любой переменной, а потом работать с ним.
- // Используйте & для получения адреса переменной
+ // Используйте & для получения адреса переменной.
int x = 0;
printf("%p\n", (void *)&x); // => Напечатает адрес в памяти, где лежит переменная x
// (%p выводит указатель на void *)
@@ -295,37 +291,37 @@ int main() {
// => Напечатает "8, 4" в 64 битной системе
// Для того, чтобы получить знаечние по адресу, напечатайте * перед именем.
- // Да, использование * при объявлении указателя и получении значения по адресу,
+ // Да, использование * при объявлении указателя и получении значения по адресу
// немного запутано, но вы привыкнете.
printf("%d\n", *px); // => Напечаатет 0, значение перемененной x
// Вы также можете изменять значение, на которое указывает указатель.
- (*px)++; // Инкрементирует значение на которое указывает px на еденицу
+ (*px)++; // Инкрементирует значение на которое указывает px на единицу
printf("%d\n", *px); // => Напечатает 1
printf("%d\n", x); // => Напечатает 1
- // массивы хорошо использовать для болшого количества однотипных данных
+ // Массивы удобно использовать для болшого количества однотипных данных.
int x_array[20];
int xx;
for (xx = 0; xx < 20; xx++) {
x_array[xx] = 20 - xx;
} // Объявление x_array с значениями 20, 19, 18,... 2, 1
- // Инициализация указателя на int с адресом массива.
+ // Объявление указателя на int с адресом массива.
int* x_ptr = x_array;
- // x_ptr сейчас x_ptr указывает на первый элемент массива (со значением 20).
+ // x_ptr сейчас указывает на первый элемент массива (со значением 20).
// Это рабоатет, потому что имя массива возвращает указатель на первый элемент.
// Например, когда массив передаётся в функцию или назначается указателю, он
// невявно преобразуется в указатель.
// Исключения: когда массив является аргументом для оператор '&':
int arr[10];
int (*ptr_to_arr)[10] = &arr; // &arr не является 'int *'!
- // он является "указатель на массив" (из десяти 'int'ов).
- // или когда массив это строчный литерал или при объявлении массива символов:
+ // он является "указателем на массив" (из десяти 'int'ов).
+ // или когда массив это строчный литерал, используемый при объявлении массива символов:
char arr[] = "foobarbazquirk";
// или когда массив является аргументом `sizeof` или `alignof` операторов:
int arr[10];
- int *ptr = arr; // то же самое что и int *ptr = &arr[0];"
+ int *ptr = arr; // то же самое что и "int *ptr = &arr[0];"
printf("%zu %zu\n", sizeof arr, sizeof ptr); // напечатает "40, 4" или "40, 8"
// Декрементация и инкрементация указателей зависит от их типа
@@ -333,7 +329,7 @@ int main() {
printf("%d\n", *(x_ptr + 1)); // => Напечатает 19
printf("%d\n", x_array[1]); // => Напечатает 19
- // Вы также можете динамически выделять несколько боков памяти с помощью
+ // Вы также можете динамически выделять несколько блоков памяти с помощью
// функции malloc из стандартной библиотеки, которая принимает один
// аргумент типа size_t – количество байт необходимых для выделения.
int *my_ptr = malloc(sizeof(*my_ptr) * 20);
@@ -347,13 +343,13 @@ int main() {
// Скорей всего программа вылетит.
// Когда вы закончили работать с памятью, которую ранее выделили, вам необходимо
- // освободить её, иначе это может вызвать утечку памяти.
+ // освободить её, иначе это может вызвать утечку памяти или ошибки.
free(my_ptr);
// Строки это массивы символов, но обычно они представляются как
// указатели на символ (как указатели на первый элемент массива).
// Хорошей практикой считается использование `const char *' при объявлении
- // строчоного литерала. При таком подходе литерал не может быть изменён.
+ // строчного литерала. При таком подходе литерал не может быть изменён.
// (например "foo"[0] = 'a' вызовет ошибку!)
const char *my_str = "This is my very own string literal";
@@ -382,13 +378,13 @@ int add_two_ints(int x1, int x2)
}
/*
-Данные в функицию передаются "по значению", но никто не мешает
+Данные в функцию передаются "по значению", но никто не мешает
вам передавать в функцию указатели и менять данные по указателям.
Например: инвертировать строку прямо в функции
*/
-// void орзначает, что функция ничего не возвражщает
+// void означает, что функция ничего не возвращает
void str_reverse(char *str_in)
{
char tmp;
@@ -409,11 +405,11 @@ printf("%s\n", c); // => Выведет ".tset a si sihT"
// Типы и структуры определяемые пользователем
///////////////////////////////////////
-// typedef исапользуется для задания стандартным типам своих названий
+// typedef используется для задания стандартным типам своих названий
typedef int my_type;
my_type my_type_var = 0;
-// Структыры это просто коллекция данных, память выделяется последовательно,
+// Структуры это просто коллекция данных, память выделяется последовательно,
// в том порядке в котором записаны данные.
struct rectangle {
int width;
@@ -421,7 +417,7 @@ struct rectangle {
};
// sizeof(struct rectangle) == sizeof(int) + sizeof(int) – не всегда верно
-// из-за особенностей компиляции (проблема в отступах)[1].
+// из-за особенностей компиляции (необычное поведение при отступах)[1].
void function_1()
{
@@ -441,7 +437,7 @@ void function_1()
my_rec_ptr->height = 10; // то же что и "(*my_rec_ptr).height = 10;"
}
-// Вы можете применить typedef к структуре, для удобства
+// Вы можете применить typedef к структуре, для удобства.
typedef struct rectangle rect;
int area(rect r)
@@ -461,22 +457,13 @@ int area(const rect *r)
///////////////////////////////////////
/*
-At runtime, functions are located at known memory addresses. Function pointers are
-much like any other pointer (they just store a memory address), but can be used
-to invoke functions directly, and to pass handlers (or callback functions) around.
-However, definition syntax may be initially confusing.
-
-Example: use str_reverse from a pointer
-*/
-
-
-/*
Во время исполнения функции находятся по известным адресам в памяти.
Указатель на функцию может быть использован для непосредственного вызова функции.
Однако синтаксис может сбивать с толку.
Пример: использование str_reverse по указателю
*/
+
void str_reverse_through_pointer(char *str_in) {
// Определение функции через указатель.
void (*f)(char *); // Сигнатура должна полность совпадать с целевой функцией.
@@ -491,7 +478,7 @@ void str_reverse_through_pointer(char *str_in) {
## На почитать
Лучше всего найдите копию [K&R, aka "The C Programming Language"](https://en.wikipedia.org/wiki/The_C_Programming_Language)
-Это *книга* написанная создателями Си. Но будьте осторожны, она содержит которые больше не считаются хорошими.
+Это **книга** написанная создателями Си. Но будьте осторожны, она содержит идеи которые больше не считаются хорошими.
Другой хороший ресурс: [Learn C the hard way](http://c.learncodethehardway.org/book/).
@@ -503,4 +490,4 @@ void str_reverse_through_pointer(char *str_in) {
Также не забывайте, что [Google](http://google.com) и [Яндекс](http://yandex.ru) – ваши хорошие друзья.
-[1] http://stackoverflow.com/questions/119123/why-isnt-sizeof-for-a-struct-equal-to-the-sum-of-sizeof-of-each-member
+[1] http://stackoverflow.com/questions/119123/why-isnt-sizeof-for-a-struct-equal-to-the-sum-of-sizeof-of-each-member \ No newline at end of file