Купить
 
 
Жанр: Учеба

Руководство полного идиота по программированию на C

страница №2

ОБЪЯВЛЕНИЕ ПЕРЕМЕННЫХ */
int LINES = 25; /* всего строк. */
int nline; /* номер строки */

/* Для человека естественно считать с 1.
Для машины же первое число - это НУЛЬ.
Поэтому цикл
for(nline=1; nline <= LINES; nline++)
Следует записать в виде
for(nline=0; nline < LINES; nline++)

Он тоже выполнится 25 раз, но значение переменной-счетчика
nline будет на каждой итерации на 1 меньше. Поэтому надо
поменять расчет параметров для функции рисования.

n (номер строки)
...* 0
..*** 1
.***** 2
******* 3

Всего строк: LINES
Число звездочек в n-ой строке: n*2 + 1
Число пробелов спереди (обозначены точкой): LINES - n - 1

*/

/* ВЫПОЛНЯЕМЫЕ ОПЕРАТОРЫ (ДЕЙСТВИЯ) */
for(nline=0; nline < LINES; nline++)
drawOneLine(LINES - nline - 1, nline*2 + 1);
}
07.c

/*
Тип переменных для хранения БУКВ называется

char

(от слова character).

Буквы изображаются в одиночных кавычках 'a' 'b' '+'.

Пример:
char letter;

letter = 'a';
putchar(letter);
letter = 'b';
putchar(letter);
letter = '\n';
putchar(letter);

Символ '\n' обозначает "невидимую букву" -
переход на новую строку, new line.
Есть несколько таких специальных букв, о них - позже.

Зато сразу сделаем оговорку.
Чтобы изобразить саму букву \
следует использовать '\\'

putchar('\'); или
printf ("\"); ошибочны.

Надо: putchar('\\'); printf("\\");

Дело в том, что символ \ начинает последовательность из ДВУХ букв,
изображающих ОДНУ букву, иногда вызывающую специальные
действия на экране или на принтере.
*/

/*
Число делится на n, если ОСТАТОК от деления его на n равен 0,
то есть если

(x % n) == 0

В частности, так можно проверять числа на четность/нечетность,
беря x%2.

Остатки от деления числа x на n
это 0 1 2 ... n-1.
В случае деления на 2 остаток
0 соответствует четному x
1 соответствует нечетному x

*/

/* Задача:
Нарисовать треугольник
из звездочек в нечетных строках
из плюсиков в четных строках
*--------------------------------------------------------*

Решение: используем прежнюю программу,
добавив в функцию drawOneLine еще один аргумент - symbol -
каким символом рисовать строку.

Далее в основном цикле используем условный оператор и
проверку номера строки на четность.

*/

#include

void drawOneLine(int nspaces, int nsymbols, char symbol){
int i; /* счетчик */

for(i=0; i < nspaces; i++)
putchar(' ');
for(i=0; i < nsymbols; i++)
putchar(symbol);
putchar('\n');
}

/* Мы вынесем объявление этой переменной из функции,
сделав ее "глобальной", то есть видимой во ВСЕХ функциях.
*/
int LINES = 25; /* всего строк. */

void main(){
/* ОБЪЯВЛЕНИЕ ПЕРЕМЕННЫХ */
int nline; /* номер строки */

/* ВЫПОЛНЯЕМЫЕ ОПЕРАТОРЫ (ДЕЙСТВИЯ) */
for(nline=0; nline < LINES; nline++){

if((nline % 2) == 0) /* четное ? */
drawOneLine(LINES - nline - 1, nline*2 + 1, '+');
else drawOneLine(LINES - nline - 1, nline*2 + 1, '*');
}
}
08.c

/* То же самое, но теперь нужно еще и печатать номер строки.
*/

#include

/* Вообще-то глобальные переменные
принято объявлять в самом начале файла с программой.
*/

int LINES = 25; /* всего строк. */

/* Добавим к функции еще один аргумент, указатель - печатать ли
номер строки. Назовем его drawLineNumber.
Не впадите в заблуждение по аналогии с именем ФУНКЦИИ drawOneLine() !
В данном случае - это имя ПЕРЕМЕННОЙ - АРГУМЕНТА ФУНКЦИИ.

Оператор if(x) .....;
РАБОТАЕТ ТАКИМ ОБРАЗОМ (так он устроен):
в качестве условия он принимает целое число (типа int).

Условие истинно, если x != 0,
и ложно, если x == 0.

Второй добавленный аргумент - собственно номер строки.
*/
void drawOneLine(int nspaces,
int nsymbols,
char symbol,
/* а это мы добавили */
int drawLineNumber,
int linenum
){
int i; /* счетчик */

if(drawLineNumber)
printf("%d\t", linenum); /* без перевода строки */

/* На самом деле это условие более полно надо записывать как

if(drawLineNumber != 0)

но в языке Си это то же самое.
*/

/* Тут мы снова видим новый специальный символ \t - ТАБУЛЯЦИЯ.
Весь экран (или лист бумаги) условно поделен
на колонки шириной по 8 позиций.
Примерно так:
| | | | | | | | | ...
Символ табуляции вызывает переход из текущей позиции в начало следующей
колонки. Например
| | | | | | | | | ...
^ отсюда

| | | | | | | | | ...
^ в это место

*/
for(i=0; i < nspaces; i++)
putchar(' ');
for(i=0; i < nsymbols; i++)
putchar(symbol);
putchar('\n');
}

void main(){
/* ОБЪЯВЛЕНИЕ ПЕРЕМЕННЫХ */
int nline; /* номер строки */

/* ВЫПОЛНЯЕМЫЕ ОПЕРАТОРЫ (ДЕЙСТВИЯ) */
for(nline=0; nline < LINES; nline++){

if((nline % 2) == 0) /* четное ? */
drawOneLine(LINES - nline - 1, nline*2 + 1, '+', 1, nline);
else drawOneLine(LINES - nline - 1, nline*2 + 1, '*', 9, nline);
}

/* А почему именно 1 или именно 9 ?
* А все что попало, лишь бы не 0.
* Можно 3, 333, 666, -13445, итп
*
* Вопрос: что будет, если тут написать 0 ?
*/
}
09.c

/* Следующая задача будет касаться того,
чтобы каждая строка треугольника печаталась
в виде:
*+*+*+*.....*+*

Тут нам уже придется модифицировать функцию рисования строки.
*/

#include

int LINES = 25; /* всего строк. */

void drawOneLine(int nspaces, int nsymbols){
int i;

for(i=0; i < nspaces; i++)
putchar(' ');

/* в цикле мы будем проверять на четность НОМЕР
печатаемого символа.
*/
for(i=0; i < nsymbols; i++){
if((i % 2) == 0)
putchar('*');
else putchar('+');
}
putchar('\n');
}

void main(){
int nline; /* номер строки */

for(nline=0; nline < LINES; nline++) {
drawOneLine(LINES - nline - 1, nline*2 + 1);
}
}
10.c

/* Задача нарисовать РОМБ:
*


*****


*
*/

#include

int LINES = 10; /* всего строк в половине ромба. */

void drawOneLine(int nspaces, int nsymbols){
int i;

for(i=0; i < nspaces; i++)
putchar(' ');

for(i=0; i < nsymbols; i++)
putchar('+');
putchar('\n');
}

void main(){
int nline; /* номер строки */

for(nline=0; nline < LINES; nline++)
drawOneLine(LINES - nline - 1, nline*2 + 1);

/* Мы нарисовали треугольник.
Теперь нам нужен перевернутый треугольник.
Пишем цикл по убыванию индекса.
С данного места номера строк отсчитываются в обратном порядке:
от LINES-2 до 0
*/

for(nline=LINES-2; nline >= 0; nline--)
drawOneLine(LINES - nline - 1, nline*2 + 1);
}
11.c

/* А теперь рисуем ромб, используя математические формулы. */

#include

void draw(int nspaces, int nstars, char symbol){
int i;

for(i=0; i < nspaces; i++)
putchar(' ');
for(i=0; i < nstars; i++)
putchar(symbol);
putchar('\n');
}

void main(){
int LINES = 21;
int MIDDLELINE = LINES/2 + 1; /* середина ромба */
int nline;

for(nline=0; nline < MIDDLELINE; nline++)
draw(MIDDLELINE - nline -1, nline*2+1, 'A');

/* У следующего цикла for() нет инициализации
начального значения индекса.
Начальное nline наследуется из предыдущего цикла,
таким, каким оно осталось после его окончания, то есть
равным MIDDLELINE.
*/

for( ; nline < LINES; nline++)
draw(nline - MIDDLELINE + 1, (LINES - 1 - nline) * 2 + 1, 'V');
}
* 12_ARRAYS.txt *

МАССИВЫ

Массив - это несколько пронумерованных переменных,
объединенных общим именем.
Все переменные имеют ОДИН И ТОТ ЖЕ ТИП.

Рассмотрим ПОЛКУ с N ящиками,
пусть имя полки - var.
Тогда кажждый ящик-ячейка имеет имя
var[0]
var[1]
var[N-1]

Нумерация идет с НУЛЯ.

--------
/ var /
/ /
------------------------------------------- ------------------
| | | | | |
| | | | .... ... | |
| | | | | |
------------------------------------------- ------------------
/ var[0] / / var[1] / / var[2] / / var[N-1] /
--------- --------- --------- -----------

Массив объявляется так:

int var[N];

здесь N - его размер, число ячеек.

Это описание как бы объявляет N переменных типа int с именами
var[0] ... var[N-1];

В операторах для обращения к n-ому ящичку (где 0 <= n < N)
используется имя ящика

var[n]

где n - целое значение (или значение целой переменной,
или целочисленного выражения), "индекс в массиве".
Эта операция [] называется "индексация массива".
Индексация - есть ВЫБОР одного из N ящиков при помощи указания целого номера.
var - массив (N ячеек)
n - выражение (формула), выдающая целое значение в интервале 0..N-1
var[n] - взят один из элементов массива. Один из всех.
n - номер ящика - называется еще и "индексом" этой переменной в массиве.


Пример:

int var[5]; /* 1 */

var[0] = 2; /* 2 */
var[1] = 3 + var[0]; /* 3 */
var[2] = var[0] * var[1]; /* 4 */
var[3] = (var[0] + 4) * var[1]; /* 5 */

printf("var третье есть %d\n", var[3]);

В ходе этой программы элементы массива меняются таким образом:

var[0] var[1] var[2] var[3] var[4]
------------------------------------------------
/* 1 */ мусор мусор мусор мусор мусор
/* 2 */ 2 мусор мусор мусор мусор
/* 3 */ 2 5 мусор мусор мусор
/* 4 */ 2 5 10 мусор мусор
/* 5 */ 2 5 10 30 мусор

Как видим, каждый оператор изменяет лишь ОДНУ ячейку массива за раз.

Массив - набор переменных, которые не ИМЕНОВАНЫ разными именами,
вроде var0, var1, var2, ...
а ПРОНУМЕРОВАНЫ под одним именем:
var[0], var[1], var[2], ...

Индекс - часть ИМЕНИ ПЕРЕМЕННОЙ.

На самом деле индексация - это
1) выбор элемента в массиве
2) справа от присваиваний и в выражениях - еще и разыменование,
то есть взятие вместо имени переменной - значения, в ней хранящегося.
---------------------------------------------------------------------------

Если в переменную не было занесено значение,
а мы используем эту переменную,
то в ней лежит МУСОР (любое, непредсказуемое значение).

printf("var4 есть %d\n", var[4]);

напечатает все что угодно.

Поэтому переменные надо всегда инициализировать
(давать им начальное значение).

Глобальные переменные автоматически инициализируются нулем,
если мы не задали иначе.

Локальные переменные не инициализируются автоматически, и содержат МУСОР.
---------------------------------------------------------------------------

Массивы НЕЛЬЗЯ присваивать целиком, язык Си этого не умеет.

int a[5];
int b[5];

a = b; /* ошибка */

Также нельзя присвоить значение сразу всем элементам (ячейкам) массива:

a = 0; /* ошибка */

не делает того, что нами ожидалось, а является ошибкой.
Для обнуления всех ячеек следует использовать цикл:

int i;

for(i=0; i < 5; i++) /* для каждого i присвоить a[i] = 0; */
a[i] = 0;

---------------------------------------------------------------------------

СВЯЗЬ МАССИВОВ И ЦИКЛОВ


Вследствие этого массивы приходится копировать (и инициализировать)
поэлементно, в цикле перебирая все (или часть) ячейки массива.

int i;

for(i=0; i < 5; i++)
a[i] = b[i];

В данном случае индекс цикла служит также и индексом в массиве.

Индексы в массиве идут с НУЛЯ.

Пример инициализации:

int index, array[5];

for(index=0; index < 5; index++)
array[index] = index * 2 + 1;

или

int index, array[5];

index = 0;
while(index < 5){
array[index] = index * 2 + 1;
index++;
}

/* В массиве будет: { 1, 3, 5, 7, 9 } */

ИНДЕКС
для массивов -
номер "ящика/ячейки" в массиве.

для циклов -
номер повторения цикла, счетчик.
Мы должны изменять его САМИ.

Обычно массивы и циклы совмещаются так:
индекс цикла есть индекс в массиве;
то есть индекс цикла используется для перебора всех
элементов массива:

int a[N], i;

for(i=0; i < N; i++)
...a[i]...
---------------------------------------------------------------------------

Примеры:

int a[5];

a[0] = 17;
a[0] += 4;
a[0]++;
---------------------------------------------------------------------------

Пример: числа Фибоначчи.
Задаются математическими формулами:

f[1] = 1
f[2] = 1
f[n+2] = f[n+1] + f[n]

Вот программа:
---------------------------------------------------------------------------

#include /* магическая строка */
#define N 20 /* сколько первых чисел посчитать */

void main(){
int fibs[N], index;

fibs[0] = 1; /* индексы отсчитываются с нуля!!! */
fibs[1] = 1;

/* Тут показано, что индекс элемента массива может вычисляться */

for(index=2; index < N; index++)
fibs[index] = fibs[index-1] + fibs[index-2];

/* Распечатка в обратном порядке */
for(index = N-1; index >= 0; index--)
printf("%d-ое число Фибоначчи есть %d\n",
index+1, fibs[index]);
}

Здесь мы видим новый для нас оператор #define
Он задает текстуальную ЗАМЕНУ слова N на слово 20,
в данном случае просто являясь эквивалентом

const int N = 20;

К несчастью размер массива не может быть задан при помощи переменной,
а вот при помощи имени, определенного в #define - может.

СТРОКИ

Строки есть массивы БУКВ - типа char,
оканчивающиеся спецсимволом \0

char string[20];

string[0] = 'П';
string[1] = 'р';
string[2] = 'и';
string[3] = 'в';
string[4] = 'е';
string[5] = 'т';
string[6] = '\0';

printf("%s\n", string);

%s - формат для печати СТРОК.
Никакие другие массивы не могут быть напечатаны
целиком одним оператором.

char string[20];

string[0] = 'П';
string[1] = 'р';
string[2] = 'и';
string[3] = 'в';
string[4] = 'е';
string[5] = 'т';
string[6] = '\n'; /* Перевод строки - тоже буква */
string[7] = '\0';

printf("%s", string);

или даже просто

printf(string);

Такие массивы можно записать в виде строки букв в ""

char string[20] = "Привет\n";

Оставшиеся неиспользованными символы массива от string[8] до string[19]
содержат МУСОР.

ПОЧЕМУ ДЛЯ СТРОК ИЗОБРЕЛИ СИМВОЛ "ПРИЗНАК КОНЦА"?


Строка - это ЧАСТЬ массива букв.
В разное время число букв в строке может быть различным,
лишь бы не превышало размер массива (тогда случится сбой программы).
Значит, следует где-то хранить текущую длину строки (число использованных
символов). Есть три решения:
(1) В отдельной переменной. Ее следует передавать во все
функции обработки данной строки (причем она может изменяться).


char str[32]; /* массив для строки */
int slen; /* брать первые slen букв в этом массиве */
func(str, &slen); /* ДВА аргумента для передачи ОДНОЙ строки */
Этот подход работоспособен, но строка разбивается на два
объекта: сам массив и переменную для его длины. Неудобно.

(2) Хранить текущую длину в элементе str[0],
а буквы - в str[1] ... итд.
Плохо тем, что в str[0] можно хранить лишь числа от 0 до 255,
и если строка длиннее - то такой подход неприменим.

(3) Не хранить длину НИГДЕ, а ввести символ-признак конца строки.
Теперь в

func(str); /* ОДИН аргумент - сам массив */

передается только сам массив, а его текущая длина может быть
при нужде вычислена при помощи некоей функции, вроде такой:

int strlen(char s[]){ /* функция от массива букв */
int counter = 0; /* счетчик и одновременно индекс */

while(s[counter] != '\0') /* пока не встретился признак конца текста */
counter++; /* посчитать символ */
return counter; /* сколько символов, отличных от '\0' */
}

Тут никаких ограничений нет. Именно этот подход и был избран
в языке Си, хотя в принципе можно самому пользоваться и другими.
На самом деле в языке есть такая СТАНДАРТНАЯ функция strlen(s)
(вам не надо писать ее самому, ее уже написали за вас).
---------------------------------------------------------------------------

ИНИЦИАЛИЗАЦИЯ ГЛОБАЛЬНОГО МАССИВА


Массив, заданный вне каких-либо функций, можно проинициализировать
константными начальными значениями:

int array[5] = { 12, 23, 34, 45, 56 };

char string[7] = { 'П', 'р', 'и', 'в', 'е', 'т', '\0' };

Если размер массива указан БОЛЬШЕ, чем мы перечислим элементов,
то остальные элементы заполнятся нулями (для int) или '\0' для char.

int array[5] = { 12, 23, 34 };

Если мы перечислим больше элементов, чем позволяет размер массива -
это будет ошибкой.

int a[5] = { 177, 255, 133 };

Операция индексации массива a[] дает:

при n значение выражения a[n] есть
---------------------------------------------------------------------------

-1 не определено (ошибка: "индекс за границей массива")
0 177
1 255
2 133
3 0
4 0
5 не определено (ошибка)
* 13_FUNCS.txt *

КАК ПРОИСХОДИТ ВЫЗОВ ФУНКЦИИ



Пусть у нас описана функция, возвращающая целое значение.

/* ОПРЕДЕЛЕНИЕ ФУНКЦИИ func(). */
/* Где func - ее имя. Назвать мы ее можем как нам угодно. */

int func(int a, int b, int c){
int x, y;
x = a + 7;
b = b + 4;
return(некое_значение);
}

Здесь
a, b, c - аргументы функции (параметры)
x, y - локальные переменные

Точка вызова - находится внутри какой-то другой
функции, например функции main()

main(){

int zz, var;
var = 17;
zz = func(33, 77, var + 3) + 44;
}

Когда выполнение программы доходит до строки

zz = func(33, 77, var + 3) + 44;

1) Происходит ВЫЗОВ ФУНКЦИИ func()

(a) Этот пункт мы увидим ниже.

(b) Создаются переменные с именами a, b, c, x, y;

© Переменным-аргументам присваиваются начальные значения,
которые берутся из точки вызова.
В точке вызова перечислен список (через запятую) выражений (формул):

func(выражение1, выражение2, выражение3)

Вычисленные значения этих выражений соответственно будут присвоены
1-ому, 2-ому и 3-ему аргументам (параметрам) из определения функции:

int func(a, b, c){ /* a = номер 1, b = 2, c = 3 */

Первый параметр:

a = 33;

Второй параметр:

b = 77;

Третий параметр:

c = var + 3;

то есть, вычисляя,

c = 20;

Локальные переменные x и y содержат неопределенные значения,
то есть мусор (мы не можем предсказать их значения,
пока не присвоим им явным образом какое-либо значение сами).

2) Выполняется ТЕЛО функции, то есть вычисления, записанные внутри { ... }
в определении функции. Например:

x = a + 7;

И параметры, и локальные переменные - это ПЕРЕМЕННЫЕ,
то есть их можно изменять.

b = b + 4;

При этом никакие переменные ВНЕ этой функции не изменяются.
(Об этом еще раз позже).

3) Производится ВОЗВРАТ из функции.
return(некое_значение);
}

Например, это может быть
return(a + 2 * x);
}

Рассмотрим, что при этом происходит в точке вызова:

zz = func(33, 77, var + 3) + 44;

(1) Вычеркиваем func(.....)

zz = XXXXXXX + 44;

(2) Вычисляем значение "некое_значение" в операторе return,
и берем КОПИЮ этого значения.
Пусть при вычислении там получилось 128.

(3) Подставляем это значение на место вычеркнутого func(.....)
У нас получается

zz = 128 + 44;

(4) АВТОМАТИЧЕСКИ УНИЧТОЖАЮТСЯ локальные переменные и аргументы функции:

a - убито
b - убито
c - убито
x - убито
y - убито

Таких переменных (и их значений) больше нет в природе.

(5) Пункт, который мы обсудим позже.

(6) Продолжаем вычисление:

zz = 128 + 44;

Вычисляется в

zz = 172; /* оператор присваивания */

---------------------------------------------------------------------------

int func1(int x){
printf("func1: x=%d\n", x); /* 1 */
x = 77;
printf("func1: x=%d\n", x); /* 2 */
return x;
}

void main(){
int var, y;

var = 111;
y = func1(var); /* @ */

printf("main: var=%d\n", var); /* 3 */
}

В данном случае в точке @ мы передаем в функцию func1()
ЗНАЧЕНИЕ переменной var, равное 111.
Это значит, что при вызове функции будет создана переменная x
и ей будет присвоено начальное значение 111

x = 111;

Поэтому первый оператор printf() напечатает 111.

Затем мы изменяем значение переменной x на 77.
Мы меняем переменную x, но не переменную var !!!
Использовав ЗНАЧЕНИЕ (его копию) из переменной var для x,
мы о переменной var забыли - она нас не касается (а мы - ее).


Поэтому второй оператор printf() напечатает 77.
В переменной же var осталось значение 111,
что и подтвердит нам третий оператор printf,
который напечатает 111.

---------------------------------------------------------------------------

ВРЕМЕННОЕ СОКРЫТИЕ ПЕРЕМЕННЫХ



int func1(int x){ /* f.1 */
printf("func1: x=%d\n", x); /* f.2 */
x = 77; /* f.3 */
printf("func1: x=%d\n", x); /* f.4 */
return x; /* f.5 */
}

void main(){
int x, y; /* 1 */

x = 111; /* 2 */
y = func1(x); /* 3 */

printf("main: x=%d y=%d\n", x, y); /* 4 */
}

А теперь мы и переменную внутри main(), и аргумент функции
func1() назвали одним и тем же именем. Что будет?

Будет то же самое, что в предыдущем примере.

В момент вызова функции func1() будет создана НОВАЯ переменная
с именем x, а старая (прежняя) переменная и ее значение будут
ВРЕМЕННО СПРЯТАНЫ (скрыты).

Можно было бы уточнить эти переменные именами функций,
в которых они определены:

main::x

и

func1::x

(но это уже конструкции из языка Си++, а не Си).

Выполним программу по операторам:

|/* 1 */ Отводятся переменные main::x и main::y для целых чисел;
|/* 2 */ main::x = 111;
|/* 3 */ Вызывается func1(111);
|
+-------+
. |/* f.1 */ Отводится переменная func1::x со значением 111;
. |/* f.2 */ Печатается 111 из переменной func1::x;
. |
. |/* f.3 */ func1::x = 77; (это не main::x, а другая переменная,
. | ЛОКАЛЬНАЯ для функции func1.
. | Переменную main::x мы сейчас не видим -
. | она "заслонена" именем нашей локальной
. | переменной.
. | Поэтому мы не можем ее изменить).
. |
. |/* f.4 */ Печатает 77 из func1::x;
. |/* f.5 */ Возвращает значение func1::x , то есть 77.
. | Переменная func1::x уничтожается.
. |
. | Теперь мы снова возвращаемся в функцию main(),
. | где имя x обозначает переменную main::x

+-------+
|
|/* 3 */ y = 77;
|/* 4 */ Печатает значения main::x и main::y, то есть
| 111 и 77.


Этот механизм сокрытия имен позволяет писать функции main() и func1()
разным программистам, позволяя им НЕ ЗАБОТИТЬСЯ о том, чтобы имена
локальных переменных в функциях НЕ СОВПАДАЛИ. Пусть совпадают - хуже не
будет, механизм упрятывания имен разрешит конфликт.
Зато программист может использовать любое понравившееся ему имя
в любой функции - хотя бы и x, или i.

---------------------------------------------------------------------------

То же самое происходит с локальными переменными,
а не с аргументами функции.

int func1(int arg){ /* локальная переменная-параметр func1::arg */
int x; /* локальная переменная func1::x */

x = arg;
printf("func1: x=%d\n", x);
x = 77;
printf("func1: x=%d\n", x);
return x;
}

void main(){
int x, y; /* переменные main::x и main::y */

x = 111;
y = func1(x);

printf("main: x=%d y=%d\n", x, y);
}

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

имя_функции(..., ..., ....)
арг1 арг2 арг3

в месте вызова функции.

То есть

ОПИСАНИЕ ФУНКЦИИ:

int f(int арг1, int арг2, int арг3){
int перем1, перем2;
/* продолжение */
}

ВЫЗОВ:

.... f(выражение1, выражение2, выражение3) ...

ТО В ТЕЛЕ ФУНКЦИИ ВЫПОЛНИТСЯ (в момент ее вызова):

арг1 = выражение1;
арг2 = выражение2;
арг3 = выражение3;

перем1 = МУСОР;
перем2 = МУСОР;
/* продолжение */

---------------------------------------------------------------------------

ГЛОБАЛЬНЫЕ ПЕРЕМЕННЫЕ



Наконец, существуют переменные, которые объявляются ВНЕ ВСЕХ ФУНКЦИЙ,
и существующие все время выполнения программы
(а не только то время, когда активна функция, в которой

Список страниц

Закладка в соц.сетях

Купить

☏ Заказ рекламы: +380504468872

© Ассоциация электронных библиотек Украины

☝ Все материалы сайта (включая статьи, изображения, рекламные объявления и пр.) предназначены только для предварительного ознакомления. Все права на публикации, представленные на сайте принадлежат их законным владельцам. Просим Вас не сохранять копии информации.