All streams
Search
Write a publication
Pull to refresh

Comments 46

Мне очень зашла книга "Программирование на C в примерах и задачах", Васильева. В былу работы программистом микроконтроллеров очень помогла войти в курс дела. До этого толком языки вообще не знал.

Видел ее не раз , но че то как то руки не доходили изучить

Как почти всегда, нет введения с объяснением, почему полный новичок решил изучить С. А было бы интересно.

Автор, а почему a[5] и 5[a] это одно и то же? Или не одно? )

а[5] == *(а + 5) == *(5 + а)

Переводим нотацию обращения к элементу массива в арифметику указателей и наблюдаем коммутативность

Вот-вот, что там с арифметикой указателей? Поподробнее. Но хотелось, конечно, это от автора статьи услышать. Но не судьба, ушёл в сад.

Все советуют её первой книгой, и казалось бы, куда ещё?

Кто эти «все» и «кому» они советуют? В аннотации от издательства и в авторском предисловии к K&R чёрным по русскому написано:

Книга не рекомендуется для чтения новичкам; для своего изучения она требует знания основ программирования и вычислительной техники.

мой опыт: я читал k&r подростком, немного зная ассемблер и бейсик. Всё казалось простым и очень логичным.

Ваш комментарий и еще один ниже внезапно (!) никак не противоречат приведенной мной цитате. Зато она видимо обидела кого-то.

Зная ассемблер, так то и мне K&R простой показалась бы в свое время. И если что, новичок — это не про возраст. Не противоречит это и утверждению Константина Владимирова, что K&R должна быть первой (не важно в каком смысле «первой») книгой студента — сферический студент кафедры информатики в МФТИ сдецл отличается от сферического новичка в вакууме, ничего о программировании доселе не слышавшем.

отличается от сферического новичка в вакууме

А нужен ли вообще C сферическому новичку в вакууме? Всё таки это в первую очередь язык для тех, кому интересно, как реально код бежит на процессоре, и кто может конвертировать этот интерес в разработку софта (embedded, OS, компиляторы, прочие инструменты) - и обычно у таких людей какой то бэкграунд в программировании накапливается в школьные годы до знакомства с C.

не надо путать тогдашних новичков , способных набрать программу биткартой и сегодняшних

Недурная книга для начинающих, НО только следует иметь в виду, что в ней описывается старая-престарая версия С (по первому изданию K&R). Кроме того, раздел по указателям и структурам (а это, в сущности, то, что составляет самый смак в языке) изложен конспективно. Я, все-таки, не рекомендовал бы ее.

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

P.S. И по-любому, K&R обязан прочесть любой сишник :) Пусть не самой первой, но обязательно

Так человек, вроде, как раз с нуля и начинает. Она, а затем и K&R можно )

K&R для начинающего тяжело, мне хорошо зашёл Стивен Прата, очень подробно объясняет.

Мне известны три перевода второго издания: "Финансы и статистика", "Невский диалект" и "Вильямс". Первые два перевода - отличные (особенно, от "Невского диалекта"), третий - мягко говоря, какой-то странный, imho. Но как раз третий распространен повсеместно и Вы, подозреваю, читали именно его?

Тоже начинал с него, но перевод не помню уже. Это был 1989-90гг.

Дальше уже, конечно были более серьезные книги, но легко вникнуть в основные понятия и концепции языка помогла именно книга Прата.

Если честно, не помню издателя) это более старая книга, и на обложке были рисунки будто русичи с летописи (может странно звучит, но факт). По ней и учился.

Кстати, мне очень понравилась книга Роберта Сикорда "Эффективный C. Профессиональное программирование". Учить С по ней, пожалуй, не стоит - книга не для новичков. Но книга полезная, с упором на безопасное программирование

Практика программирования (Керниган/Пайк) - не только про C, но большая часть кода на нём.

Начинать программировать с С - навсегда угробить в себе программиста (заработать сишность головного мозга).

Считаю категорически наоборот , как по мне С самый лучший вход в программирование

заработать сишность головного мозга

объясните что вы имеете в виду

Сишники не отличают процедуры от функций, не понимают побочных эффектов (поскольку практически все сишные выражения - один сплошной побочный эффект).

И вообще, С в силу своей ограниченности (отсутствие массивов, вложенных функций, процедур и пр., а также нелогичного синтаксиса (указателей) формирует неправильные представления о концепциях/парадигмах программирования. И эти представления очень трудно (если вообще) преодолимы). Очень похоже на подобных программистов, начинавших с Бейсика, о которых Дейкстра говорил, что их мозг безвозвратно искалечен.

зато си формирует правильные представления о том как код исполняется. никакой магии, всё максимально близко к железу.

Сишники не отличают процедуры от функций

а в чём это отличие? чем плохо использование функции, не возвращающей значение?

Даже? Ну, разумеется, в С нет разделения на процедуры и функции, но аналогом процедуры может служить функция, возвращающая void. Подскажите, насколько это критично - отсутствие понятия процедур в С? В java нет ни функций, ни процедур, только методы, но это, простите те же яйца, только сбоку и никому не мешает.

То, что некоторые сишники не понимают побочных эффектов, так это свойственно не только им. Они могут быть в любом распространенном ЯП. Может и есть ЯП, где эта фишка заколочена наглухо (единственное, что приходит на ум - rust), то это исключение из правил. Да, хорошо бы без них, но что имеем, то имеем. Думать просто надо, когда пишешь код. Это - сложно и скучно и не всем по душе.

Вложенные функции ни разу не понадобились. Их удобства я нисколько не отрицаю, но это точно не критично.

А вот насчет отсутствия массивов в С: если не трудно, подробнее можно?

Касаемо указателей. Да, это камень преткновения. Многие не могут понять, что значение и адрес значения - разные вещи. Можно без них программировать? Ессно: java, c# к примеру. Ну и пользуйте их на здоровье. Но в С (а тем более, в ассемблере, откуда косвенная адресация и пришла) без них плохо получается

Понадобилось - не понадобилось, речь вообще не об этом. Побочные эффекты в других ЯП тоже не аргумент (вообще избавиться от побочных эффектов невозможно). Сам стиль программы на С, состоящей практически полностью из побочных эффектов (и по-другому не написать), травмирует мышление начинающего.

Насчет отсутствия массивов. Я плохо умею объяснять. Вот, скажем, массив

int p[20];

А теперь мы пишем *(p + 5) = 12; Так правильно?

Или всё-таки p[5] = 12; ?

Я тут вижу имитацию массива указателями.

А вообще, рекомендую почитать А.В. Столяров, "Язык С и начальное обучение программированию".

То Вы против С, то рекомендуете книгу Столярова (хорошая, кстати).

Я тоже не считаю, что С - это то, с чего следует начинать учиться. Этот язык для уже что-то понимающих

int p[20];

А теперь мы пишем *(p + 5) = 12; Так правильно?

Или всё-таки p[5] = 12; 

И так, и так - даст один результат:

#include <stdio.h>

int main(void) {
    int p[20];
    p[5] = 10;    // Инициализируем
    printf("%d\n", p[5]);
    p[5] = 12;    // Меняем "в лоб"
    printf("%d\n", p[5]);
    *(p+5) = 12;  // Меняем через указатель
    printf("%d\n", p[5]);
    return 0;
}

Компилятор gcc 11.4.0 (Ubuntu)

Можете считать это синтаксическим сахаром ) Но лучше обратиться к первоисточнику (K&R). Но массивы входят в определение ядра языка (как и структуры, перечисления, объединения)

У Столярова хорошо изложено. Я только ухудаю.

Нет в С полноценного типа "массив". Попробуйте передать в функцию хотя бы двумерный массив. (Указатель на массив - страшная вещь!)

Знаете, нет предела извращениям. Вот, например, функция, которая находит минимальное из двух целых (для общности пишу на псевдокоде):

min(a, b) = (a + b - abs(a-b)) >> 2

Ни одного if-а, заметьте. Но за такой код надо руки отрывать начиная от колен :) И тройные указатели встречались. Но это не значит, что так надо делать. Можно? Да. Нужно? Нет

Ну, во-первых, а покажите abs без if-а. Если if-а не видно, то это не значит, что его нет.

Во-вторых, вы уверены, что >> 2 ? Деление на 2 - это >> 1.
А вообще красивый if. Я такого раньше не встречал. Только с переполнением у него плохо...

а покажите abs без if-а.

Навскидку (x ^ (x >> (sizeof(x)*8-1))) - (x >> (sizeof(x)*8-1))

Офигенно! Я в блаженстве.

Да, конечно :))) Сдвиг на 1 должен быть. ОписАлся

Попробуйте передать в функцию хотя бы двумерный массив

В чём проблема?

#include <stdio.h>
#include <stddef.h>

void myfunc(const int arr[3][2])
{
    for (size_t i = 0; i < 3; ++i) {
        for (size_t j = 0; j < 2; ++j) {
            printf("%d\n", arr[i][j]);
        }
    }
}

int main(void)
{
    const int arr[3][2] = {1, 2, 3, 4, 5, 6, };
    myfunc(arr);
    return 0;
}

Компилируем:

[newpson@archlinux tmp]$ gcc -o bin -fsanitize=address -Wall -Wextra -Wpedantic -O2 demo.c
demo.c: In function ‘main’:
demo.c:14:27: warning: missing braces around initializer [-Wmissing-braces]
   14 |     const int arr[3][2] = {1, 2, 3, 4, 5, 6, };
      |                           ^
      |                            {   } {   } {     }

Запускаем:

[newpson@archlinux tmp]$ ./bin
1
2
3
4
5
6

В чём проблема?

Не считая того, что в void myfunc(const int arr[3][2]) компилятор игнорирует 3 и превращает параметр функции в const int arr[][2] (т.е. в обычный указатель на константный массив из 2 интов), ни в чем https://godbolt.org/z/T6q1WdT3G :)

Понял. Как насчёт такого? Теперь разве что вручную прострелить себе колено и преобразовать один указатель в другой.

#include <stdio.h>
#include <stddef.h>

void myfunc(const int (*arr)[3][2])
{
    for (size_t i = 0; i < 3; ++i) {
        for (size_t j = 0; j < 2; ++j) {
            printf("%d\n", (*arr)[i][j]);
        }
    }
}

int main(void)
{
    const int arr[3][2] = {1, 2, 3, 4, 5, 6, };
    myfunc(&arr);

    const int little_evil_arr[][2] = {{1, 2}};
    myfunc(&little_evil_arr);
    return 0;
}
[newpson@archlinux tmp]$ gcc -o bin -g -fsanitize=address -Wall -Wextra -Wpedantic -O2 demo.c
demo.c: In function ‘main’:
demo.c:15:27: warning: missing braces around initializer [-Wmissing-braces]
   15 |     const int arr[3][2] = {1, 2, 3, 4, 5, 6, };
      |                           ^
      |                            {   } {   } {     }
demo.c:19:12: error: passing argument 1 of ‘myfunc’ from incompatible pointer type [-Wincompatible-pointer-types]
   19 |     myfunc(&little_evil_arr);
      |            ^~~~~~~~~~~~~~~~
      |            |
      |            const int (*)[1][2]
demo.c:4:25: note: expected ‘const int (*)[3][2]’ but argument is of type ‘const int (*)[1][2]’
    4 | void myfunc(const int (*arr)[3][2])
      |             ~~~~~~~~~~~~^~~~~~~~~~

Отстреливание колена:

// ...
myfunc((const int (*)[3][2]) &little_evil_arr);
// ...

не отличают процедуры от функций

И чем отличается процедура от функции, возвращающей void?

не понимают побочных эффектов (поскольку практически все сишные выражения - один сплошной побочный эффект)

Это можно сказать про любой императивный язык. Пока не пощупаешь какой-нибудь хаскель

С в силу своей ограниченности (отсутствие массивов, ... и пр.

А ещё там отсутствуют строки и utf, длинная арифметика, работа с изображениями, встроенная БД, интерфейс к чатгпт и автоматическое управление кофеваркой. И что? Кто сказал, что это всё нужно тащить в язык, а не в библиотеки?

а также нелогичного синтаксиса (указателей)

Что может быть логичнее, чем указатели?!

вообще не понял )) с каких пор у Си отсутствуют массивы и функции ? ))) Да, C не учит высоким абстракциям напрямую, зато отлично учит понимать, как работает компьютер. И после этого уже можно спокойно осваивать любые парадигмы.

Спасибо за подборку. Как раз думал освоить си, и первым делом пришла в голову Кериниган и Ричи, которую читали в универе

K&R для начала действительно тяжеловато (скучновато) будет ( хотя уже была ученая степень).

А вот М.Уэйт, С. Прата, Д.Мартин, Язык Си. Руководство для начинающих. плюс дискетка с Turbo C зашло как по маслу.  И картинки симпатичные, с юмором :) До сих пор при словах "переносимый язык" вспоминается большая буква С с ручкой для переноски.

Судя по тому, что за 30 лет наворотили в Windows, сейчас эта книжка наверное уже бесполезна...

смотрел такую книжку Expert C Programming: Deep Secrets, Peter van der Linden, последнее время если по азам то я бы посмотрел книжку Искусство программирования С, её оглавление частично есть в вики

есть еще книга по FreeBSD там тоже интересно, само устройство Линукс или Юникс, пока ставишь уже учишься как щас помню )

ну и еще 1 смотрел по С++ там книга про то что просто изучаем С++ через консольные игры, и там рассматриваются все аспекты языка, которых достаточно на момент изучения

компиляция программ на генту даст буст тоже, но это на любителя

можно попробовать еще сделать свой Wm это оказывается вполне реально после практики на Swing например, тоже даёт чуть знаний

по памяти и работой с памятью поможет освещение математики отрезков, это целый раздел оказывается есть книги где это рассматривается

Вот еще книга просто космос , но единственное что нашел только на Английском и это все таки тормозит чуть процесс чтения

Пытался как-то пройти бесллатный курс на Степике по питону, но бросил. Потом курс по Си от уважаемого С. Балакирева и тоже бросил. Каждый раз становится как-то скучно что ли и не интересно. Так вот вопрос. Есть ли смысл попробовать изучать по Си по одной из этих книг или программирование это вообще не моё? До конца не могу понять. Вроде в этом что-то привлекает, а вроде бы это навязанная рекламой потребность. Посоветуйте метод самопроделения. Мне сложно судить о какой-то деятельности, как следует её не попробовав

Удивлён, что никто не упомянул Head First C. Знаю, что многим она не заходит, т.к. в ней используется интересный и нестандартный подход к обучению. Но для меня именно эта книга стала переломной.

Sign up to leave a comment.

Articles