Шрифт:
ему будет присвоен указатель на символьную строку "Это правильно". Снова об операторах приращения (++) и уменьшения (--)
До настоящего момента оператор приращения или уменьшения был единствен-ным оператором в выражении. Если мы пишем выражение ++х, это означает, что значение х увеличивается на I. И, как вы уже видели, если х — указатель на массив, эта операция делает х указателем на следующий элемент массива.
Операторы приращения и уменьшения можно использовать в выражениях, где присутствуют другие операторы. В таких случаях важно знать, как они действуют.
Операторы приращения (increment) и уменьшения (decrement) всегда по-мещаются перед соответствующими наращиваемыми и уменьшаемыми пере-менными. Например, для приращения переменной i достаточно написать: ++i;
Оператор приращения можно также поместить после переменной: i++;
Оба выражения допустимы, и оба дают одинаковый результат: увеличение на I значения i. В первом случае, когда ++ помещается перед операндом, операция увеличения называется преувеличением (pre-increment). Во втором случае, когда ++ помещается после операнда, операция увеличения называется посту-величением.
То же самое относится к оператору уменьшения. Поэтому оператор --i;
выполняет предуменыиение i, а оператор i--;
выполняет постуменьшение i. Оба дают одинаковый результат: вычитание 1 из значения i.
Если операторы приращения и уменьшения используются в более сложных выражениях, то отличия между пред- и пост-операторами могут быть существен-ными.
Предположим, что у нас есть две целые переменные: i и j. Если присвоить i значение 0 и затем написать оператор j = ++i;
то переменной j будет присвоено значение 1, а не 0. В случае оператора преду-величения переменная наращивается до того, как ее значение используется в выражении. В приведенном выше выражении значение i сначала увеличивается с 0 до 1, а затем ее значение присваивается переменной j, как в следующих двух операторах. ++i; i = i;
Если использовать оператор постувеличения j = i++;
значение i будут увеличено после того, как она будет присвоена переменной j. Если i было присвоено значение 0 перед выполнением оператора постувеличс- ния, то переменной j будет присвоено значение 0, и затем значение i будет уве-личено на 1, как в следующих операторах. j = i; ++i;
Еше один пример. Если i равна 1, то в результате оператора X = a[--i];
переменной х будет присвоено значение а[0], так как переменная i уменьшается до того, как ее значение используется для индексации а. Оператор x = a[i--];
присваивает х значение а[1], поскольку i уменьшается после того, как ее значение используется для индексации а.
Третий пример отличий между пред- и пост-операторами приращения и уменьшения. При вызове функции NSLog (@"%i", ++i);
происходит увеличение i, после чего ее значение передается функции NSLog, а при вызове NSLog (@"%i", i++);
увеличение i происходит после того, как ее значение передано этой функции. Таким образом, если значение i было равно 100, при первом вызове NSLog на терминал будет выведено 101, а при втором вызове NSLog — 100. В обоих случаях значение i будет равно 101 после выполнения оператора.
И последний пример. Если textPtr — указатель на тип char, то в выражении *(++textPtr)
textPtr сначала увеличивается на 1, а затем извлекается символ, на который ука-зывает textPtr. Однако в выражении *(textPtr++)
сначала извлекается символ, на который указывает textPtr, а затем увеличивается его значение. В обоих случаях круглые скобки не обязательны, поскольку опера-торы * и ++ имеют одинаковый приоритет, но применяются справа налево.
Вернемся к функции copyString из программы 13.13 и перепишем ее для включения операций прирашения непосредственно в оператор присваивания.
Поскольку указатели to и from наращиваются каждый раз после выполнения оператора присваивания внутри цикла for, их следует включить в оператор при-сваивания как операции пост-увеличения. Модифицированный цикл for из про-граммы 13.13 принимает вид for (; *from != '\0';) *to++ = *from++;
Выполнение оператора присваивания внутри никла происходит следующим образом. Считывается символ, на который указывает from, затем происходит наращивание from, чтобы он указывал следующий символ в исходной строке. Соответствующий символ будет сохранен в позиции, на которую указывает 1о; затем происходит наращивание to так, чтобы он указывал следующую позицию в конечной строке.
Приведенный цикл не слишком пригоден, поскольку не имеет начального выражения и не содержит выражения цикла. Для этой логики больше подходит цикл while. Он показан в программе 13.14, где представлена новая версия функции copyStriog. В этом цикле while учитывается, что нуль-символ равен значению 0. // Функция для копирования одной строки в другую // с помощью указателей, версия 2 #import <Foundation/Foundation.h> void copyString (char *to, char *from) { while (*from) *to++ = *from++; *to = “\0"; } int main (int arge, char *argv[]) { NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; void copyString (char *to, char *from); char string 1[] = "Копируемая строка"; char string2[50]; copyString (string2, string 1); NSLog (@"%s", string2); copyString (string2, "Строка-константа"); NSLog (@"%s", string2); [pool drain]; return 0; }