Брайан Керниган - Язык программирования Си. Издание 3-е, исправленное

Тут можно читать онлайн Брайан Керниган - Язык программирования Си. Издание 3-е, исправленное - бесплатно полную версию книги (целиком) без сокращений. Жанр: comp-programming, издательство Невский Диалект, год 2001. Здесь Вы можете читать полную версию (весь текст) онлайн без регистрации и SMS на сайте лучшей интернет библиотеки ЛибКинг или прочесть краткое содержание (суть), предисловие и аннотацию. Так же сможете купить и скачать торрент в электронном формате fb2, найти и слушать аудиокнигу на русском языке или узнать сколько частей в серии и всего страниц в публикации. Читателям доступно смотреть обложку, картинки, описание и отзывы (комментарии) о произведении.
  • Название:
    Язык программирования Си. Издание 3-е, исправленное
  • Автор:
  • Жанр:
  • Издательство:
    Невский Диалект
  • Год:
    2001
  • Город:
    Санкт-Петербург
  • ISBN:
    0-13-110362-8
  • Рейтинг:
    4.11/5. Голосов: 91
  • Избранное:
    Добавить в избранное
  • Отзывы:
  • Ваша оценка:
    • 80
    • 1
    • 2
    • 3
    • 4
    • 5

Брайан Керниган - Язык программирования Си. Издание 3-е, исправленное краткое содержание

Язык программирования Си. Издание 3-е, исправленное - описание и краткое содержание, автор Брайан Керниган, читайте бесплатно онлайн на сайте электронной библиотеки LibKing.Ru

Книга широко известных авторов, разработчиков языка Си, переработанная и дополненная с учетом стандарта ANSI для языка Си, 2-е английское издание которой вышло в 1988 году, давно стала классикой для всех изучающих и/или использующих как Си, так и Си++. Русский перевод этой книги впервые был выпущен изд- вом "Финансы и статистика" в 1992 г. и с тех пор пользуется неизменным спросом читателей.

Для настоящего третьего русского издания перевод заново сверен с оригиналом, в него внесены некоторые поправки, учитывающие устоявшиеся за прошедшие годы изменения в терминологии, а так же учтены замечания, размещенные автором на странице http://cm.bell-labs.com/cm/cs/cbook/2ediffs.html.

Для программистов, преподавателей и студентов.

Издание подготовлено при участии издательства "Финансы и статистика"

Язык программирования Си. Издание 3-е, исправленное - читать онлайн бесплатно полную версию (весь текст целиком)

Язык программирования Си. Издание 3-е, исправленное - читать книгу онлайн бесплатно, автор Брайан Керниган
Тёмная тема
Сбросить

Интервал:

Закладка:

Сделать

Теперь присваивание

x = *pa;

будет копировать содержимое a[0] в x .

Если pa указывает на некоторый элемент массива, то pa+1 по определению указывает на следующий элемент, pa+i - на i -й элемент после pa , a pa-i - на i -й элемент перед pa . Таким образом, если pa указывает на a[0] , то

*(pa+1)

есть содержимое a[1] , a+i - адрес a[i] , a *(pa+i) - содержимое a[i] .

Сделанные замечания верны безотносительно к типу и размеру элементов массива a - фото 4

Сделанные замечания верны безотносительно к типу и размеру элементов массива a . Смысл слов "добавить 1 к указателю", как и смысл любой арифметики с указателями, состоит в том, чтобы pa+1 указывал на следующий объект, a pa+i - на i -й после pa .

Между индексированием и арифметикой с указателями существует очень тесная связь. По определению значение переменной или выражения типа массив есть адрес нулевого элемента массива. После присваивания

pa =&a[0];

ра и a имеют одно и то же значение. Поскольку имя массива является синонимом расположения его начального элемента, присваивание pa=&a[0] можно также записать в следующем виде:

pa = a;

Еще более удивительно (по крайней мере на первый взгляд) то, что a[i] можно записать как *(a+i) . Вычисляя a[i] , Си сразу преобразует его в *(a+i) ; указанные две формы записи эквивалентны. Из этого следует, что полученные в результате применения оператора & записи &a[i] и a+i также будут эквивалентными, т. е. и в том и в другом случае это адрес i -го элемента после a . С другой стороны, если pa - указатель, то его можно использовать с индексом, т. е. запись pa[i] эквивалентна записи *(pa+i) . Короче говоря, элемент массива можно изображать как в виде указателя со смещением, так и в виде имени массива с индексом.

Между именем массива и указателем, выступающим в роли имени массива, существует одно различие. Указатель - это переменная , поэтому можно написать pa=a или pa++ . Но имя массива не является переменной , и записи вроде a=pa или a++ не допускаются.

Если имя массива передается функции, то последняя получает в качестве аргумента адрес его начального элемента. Внутри вызываемой функции этот аргумент является локальной переменной, содержащей адрес. Мы можем воспользоваться отмеченным фактом и написать еще одну версию функции strlen , вычисляющей длину строки.

/* strlen: возвращает длину строки */

int strlen(char *s)

{

int n;

for (n = 0; *s!= '\0'; s++)

n++;

return n;

}

Так как переменная s - указатель, к ней применима операция ++; s++ не оказывает никакого влияния на строку символов функции, которая обратилась к strlen . Просто увеличивается на 1 некоторая копия указателя, находящаяся в личном пользовании функции strlen . Это значит, что все вызовы, такие как:

strlen("3дравствуй, мир"); /* строковая константа */

strlen(array); /* char array[100]; */

strlen(ptr); /* char *ptr; */

правомерны.

Формальные параметры

char s[];

и

char *s;

в определении функции эквивалентны. Мы отдаем предпочтение последнему варианту, поскольку он более явно сообщает, что s есть указатель. Если функции в качестве аргумента передается имя массива, то она может рассматривать его так, как ей удобно - либо как имя массива, либо как указатель, и поступать с ним соответственно. Она может даже использовать оба вида записи, если это покажется уместным и понятным.

Функции можно передать часть массива, для этого аргумент должен указывать на начало подмассива. Например, если a - массив, то в записях

f(&a[2])

или

f(a+2)

функции f передается адрес подмассива, начинающегося с элемента a[2] . Внутри функции f описание параметров может выглядеть как

f(int arr[]) {…}

или

f(int *arr) {…}

Следовательно, для f тот факт, что параметр указывает на часть массива, а не на весь массив, не имеет значения.

Если есть уверенность, что элементы массива существуют, то возможно индексирование и в "обратную" сторону по отношению к нулевому элементу; выражения p[-1] , p[-2] и т.д. не противоречат синтаксису языка и обращаются к элементам, стоящим непосредственно перед p[0] . Разумеется, нельзя "выходить" за границы массива и тем самым обращаться к несуществующим объектам.

5.4 Адресная арифметика

Если p есть указатель на некоторый элемент массива, то p++ увеличивает p так, чтобы он указывал на следующий элемент, а p+=i увеличивает его, чтобы он указывал на i -й элемент после того, на который указывал ранее. Эти и подобные конструкции - самые простые примеры арифметики над указателями, называемой также адресной арифметикой.

Си последователен и единообразен в своем подходе к адресной арифметике. Это соединение в одном языке указателей, массивов и адресной арифметики - одна из сильных его сторон. Проиллюстрируем сказанное построением простого распределителя памяти, состоящего из двух программ. Первая, alloc(n) , возвращает указатель p на n последовательно расположенных ячеек типа char ; программой, обращающейся к alloc , эти ячейки могут быть использованы для запоминания символов. Вторая, afree(p) , освобождает память для, возможно, повторной ее утилизации. Простота алгоритма обусловлена предположением, что обращения к afree делаются в обратном порядке по отношению к соответствующим обращениям к alloc . Таким образом, память, с которой работают alloc и afree , является стеком (списком, в основе которого лежит принцип "последним вошел, первым ушел"). В стандартной библиотеке имеются функции mallocи free, которые делают то же самое, только без упомянутых ограничений: в параграфе 8.7 мы покажем, как они выглядят.

Функцию alloc легче всего реализовать, если условиться, что она будет выдавать куски некоторого большого массива типа char , который мы назовем allocbuf . Этот массив отдадим в личное пользование функциям alloc и afree . Так как они имеют дело с указателями, а не с индексами массива, то другим программам знать его имя не нужно. Кроме того, этот массив можно определить в том же исходном файле, что и alloc и afree , объявив его static , благодаря чему он станет невидимым вне этого файла. На практике такой массив может и вовсе не иметь имени, поскольку его можно запросить с помощью malloc у операционной системы и получить указатель на некоторый безымянный блок памяти.

Естественно, нам нужно знать, сколько элементов массива allocbuf уже занято. Мы введем указатель allocp , который будет указывать на первый свободный элемент. Если запрашивается память для n символов, то alloc возвращает текущее значение allocp (т. е. адрес начала свободного блока) и затем увеличивает его на n , чтобы указатель allocp указывал на следующую свободную область. Если же пространства нет, то alloc выдает нуль. Функция afree(p) просто устанавливает allocp в значение p , если оно не выходит за пределы массива allocbuf .

Читать дальше
Тёмная тема
Сбросить

Интервал:

Закладка:

Сделать


Брайан Керниган читать все книги автора по порядку

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




Язык программирования Си. Издание 3-е, исправленное отзывы


Отзывы читателей о книге Язык программирования Си. Издание 3-е, исправленное, автор: Брайан Керниган. Читайте комментарии и мнения людей о произведении.


Понравилась книга? Поделитесь впечатлениями - оставьте Ваш отзыв или расскажите друзьям

Напишите свой комментарий
x