» √лавна€
eXcode.ru » —татьи » ƒругие » ќсновы программировани€
» Ќовости
» ќпросы
» ‘айлы
» ∆урнал



ѕользователей: 0
√остей: 9





ќсновы €зыка —и




ќсновы €зыка —и

¬ насто€щее врем€ €зык —и и объектно-ориентированные €зыки его группы (прежде всего C++, а также Java и C#) €вл€ютс€ основными в практическом программировании. ƒостоинство €зыка —и - это, прежде всего, его простота и лаконичность. язык —и легко учитс€. √лавные пон€ти€ €зыка —и, такие, как статические и локальные переменные, массивы, указатели, функции и т.д., максимально приближены к архитектуре реальных компьютеров. “ак, указатель - это просто адрес пам€ти, массив - непрерывна€ область пам€ти, локальные переменные - это переменные, расположенные в аппаратном стеке, статические - в статической пам€ти. ѕрограммист, пишущий на —и, всегда достаточно точно представл€ет себе, как созданна€ им программа будет работать на любой конкретной архитектуре. ƒругими словами, €зык —и предоставл€ет программисту полный контроль над компьютером.

ѕервоначально €зык —и задумывалс€ как заменитель јссемблера дл€ написани€ операционных систем. ѕоскольку —и - это €зык высокого уровн€, не завис€щий от конкретной архитектуры, текст операционной системы оказывалс€ легко переносимым с одной платформы на другую. ѕервой операционной системой, написанной практически целиком на —и, была система Unix. ¬ насто€щее врем€ почти все используемые операционные системы написаны на —и.  ро- ме того, средства программировани€, которые операционна€ система предоставл€ет разработчикам прикладных программ (так называемый API - Application Program Interface), - это наборы системных функций на €зыке —и.

“ем не менее, область применени€ €зыка —и не ограничилась разработкой операционных систем. язык —и оказалс€ очень удобен в программах обработки текстов и изображений, в научных и инженерных расчетах. ќбъектно-ориентированные €зыки на основе —и отлично подход€т дл€ программировани€ в оконных средах.

¬ данном разделе будут приведены лишь основные пон€ти€ €зыка —и (и частично C++). Ёто не замен€ет чтени€ полного учебника по —и или C++, например, книг [6] и [8].

ћы будем использовать компил€тор C++ вместо Cи. ƒело в том, что €зык —и почти целиком входит в C++, т.е. нормальна€ программа, написанна€ на —и, €вл€етс€ корректной C++ программой. —лово "нормальна€" означает, что она не содержит неудачных конструкций, оставшихс€ от ранних версий —и и не используемых в насто€щее врем€.  омпил€тор C++ предпочтительнее, чем компил€тор —и, т.к. он имеет более строгий контроль ошибок.  роме того, некоторые конструкции C++, не св€занные с объектно-ориентированным программированием, очень удобны и фактически €вл€ютс€ улучшением €зыка —и. Ёто, прежде всего, комментарии //, возможность описывать локальные переменные в любой точке программы, а не только в начале блока, и также задание констант без использовани€ оператора #define препроцесора. ћы будем использовать эти возможности C++, остава€сь по существу в рамках €зыка —и.

—труктура —и-программы

Ћюба€ достаточно больша€ программа на —и (программисты используют термин проект) состоит из файлов. ‘айлы транслируютс€ —и-компил€тором независимо друг от друга и затем объедин€ютс€ программой-построителем задач, в результате чего создаетс€ файл с программой, готовой к выполнению. ‘айлы, содержащие тексты —и-программы, называютс€ исходными.

¬ €зыке —и исходные файлы бывают двух типов:

  • заголовочные, или h-файлы;
  • файлы реализации, или Cи-файлы.

»мена заголовочных файлов имеют расширение ".h". »мена файлов реализации имеют расширени€ ".c" дл€ €зыка —и и ".cpp", ".cxx" или ".cc" дл€ €зыка C++.

  сожалению, в отличие от €зыка —и, программисты не сумели договоритьс€ о едином расширении имен дл€ файлов, содержащих программы на C++. ћы будем использовать расширение ".h" дл€ заголовочных файлов и расширение ".cpp" дл€ файлов реализации.

«аголовочные файлы содержат только описани€. ѕрежде всего, это прототипы функций. ѕрототип функции описывает им€ функции, тип возвращаемого значени€, число и типы ее аргументов. —ам текст функции в h-файле не содержитс€. “акже в h-файлах описываютс€ имена и типы внешних переменных, константы, новые типы, структуры и т.п. ¬ общем, h-файлы содержат лишь интерфейсы, т.е. информацию, необходимую дл€ использовани€ программ, уже написанных другими программистами (или тем же программистом раньше). «аголовочные файлы лишь сообщают информацию о других программах. ѕри трансл€ции заголовочных файлов, как правило, никакие объекты не создаютс€. Ќапример, в заголовочном файле нельз€ определить глобальную переменную. —трока описани€

int x;

определ€юща€ целочисленную переменную x, €вл€етс€ ошибкой. ¬место этого следует использовать описание

    
extern int x;

означающее, что переменна€ x определена где-то в файле реализации (в каком - неизвестно). —лово extern (внешн€€) лишь сообщает информацию о внешней переменной, но не определ€ет эту переменную.

‘айлы реализации, или Cи-файлы, содержат тексты функций и определени€ глобальных переменных. √овор€ упрощенно, —и-файлы содержат сами программы, а h-файлы - лишь информацию о программах.

ѕредставление исходных текстов в виде заголовочных файлов и файлов реализации необходимо дл€ создани€ больших проектов, имеющих модульную структуру. «аголовочные файлы служат дл€ передачи информации между модул€ми. ‘айлы реализации - это отдельные модули, которые разрабатываютс€ и транслируютс€ независимо друг от друга и объедин€ютс€ при создании выполн€емой программы.

‘айлы реализации могут подключать описани€, содержащиес€ в заголовочных файлах. —ами заголовочные файлы также могут использовать другие заголовочные файлы. «аголовочный файл подключаетс€ с помощью директивы препроцессора #include. Ќапример, описани€ стандартых функций ввода-вывода включаютс€ с помощью строки

    
#include <stdio.h>

(stdio - от слов standard input/output). »м€ h-файла записываетс€ в угловых скобках, если этот h-файл €вл€етс€ частью стандартной —и-библиотеки и расположен в одном из системных каталогов. »мена h-файлов, созданных самим программистом в рамках разрабатываемого проекта и расположенных в текущем каталоге, указываютс€ в двойных кавычках, например,

    
#include "abcd.h"

ѕрепроцессор - это программа предварительной обработки текста непосредственно перед трансл€цией.  оманды препроцессора называютс€ директивами. ƒирективы препроцессора содержат символ диез # в начале строки. ѕрепроцессор используетс€ в основном дл€ подключени€ h-файлов. ¬ —и также очень часто используетс€ директива #define дл€ задани€ символических имен констант. “ак, строка

#define PI 3.14159265

задает символическое им€ PI дл€ константы 3.14159265. ѕосле этого им€ PI можно использовать вместо числового значени€. ѕрепроцессор находит все вхождени€ слова PI в текст и замен€ет их на константу. “аким образом, препроцессор осуществл€ет подмену одного текста другим. Ќеобходимость использовани€ препроцессора всегда свидетельствует о недостаточной выразительности €зыка. “ак, в любом јссемблере средства препроцессировани€ используютс€ довольно интенсивно. ¬ —и по возможности следует избегать чрезмерного увлечени€ командами препроцессора - это затрудн€ет понимание текста программы и зачастую ведет к трудно исправл€емым ошибкам. ¬ C++ можно обойтись без использовани€ директив #define дл€ задани€ констант. Ќапример, в C++ константу PI можно задать с помощью нормального описани€

const double PI = 3.14159265;

Ёто €вл€етс€ одним из аргументов в пользу применени€ компил€тора C++ вместо —и даже при трансл€ции программ, не содержащих конструкции класса.

‘ункции

‘ункци€ €вл€етс€ основной структурной единицей €зыка —и. ¬ других €зыках функции иногда называют подпрограммами. ‘ункци€ - это фрагмент программы, который может вызыватьс€ из других программ. ‘ункци€ обычно выполн€ет алгоритм, который описываетс€ и реализуетс€ отдельно от других алгоритмов. ѕри вызове функции передаютс€ аргументы, которые могут быть использованы в теле функции. ¬ результате своей работы функци€ возвращает значение некоторого типа. Ќапример, функци€ sin, прототип которой задаетс€ строкой

double sin(double x);

имеет один аргумент x типа double (вещественное число). –езультат функции также имеет тип double. ѕри вызове фукци€ sin вычисл€ет синус числа, переданного ей в качестве фактического аргумента, и возвращает вычисленное значение в вызывающую программу.

¬ызов функции происходит в результате использовани€ ее имени в выражении. «а именем функции следуют круглые скобки, внутри которых перечисл€ютс€ фактические значени€ ее аргументов. ƒаже если аргументов нет, круглые скобки с пустым списком аргументов об€зательно должны присутствовать!

ѕосле вызова функции значение, возвращенное в результате ее выполнени€, используетс€ в выражении (им€ функции как бы замен€етс€ возвращенным значением). ѕримеры:

x = sin(1.0);

«десь в результата вызова функции sin вычисл€етс€ синус числа 1.0, затем вычисленное значение записываетс€ в переменную x при выполнени€ оператора присваивани€ "=". ƒругой пример:

    
f();

¬ызываетс€ функци€ f, не имеюща€ параметров. «начение, возвращенное в результате выполнени€ функции f, не используетс€. ѕрограмма на —и состоит из функций. –абота программы всегда начинаетс€ с функции с именем main. –ассмотрим минимальный пример —и-программы

ѕрограмма "Hello, World!"

ѕриведенна€ ниже программа печатает фразу "Hello, World!" на экране терминала.

 
    #include <stdio.h>

    int main() {
        printf("Hello, World
");
        return 0;
    }

ѕерва€ строка подключает заголовочный файл с описани€ми стандартных функций ввода-вывода —и-библиотеки. ¬ частности, в этом файле описан прототип функции printf (печать по формату), используемой дл€ вывода информации в стандартный поток вывода (по умолчанию он назначен на терминал). ¬ыполнение программы начинаетс€ с функции main. ‘ункци€ main возвращает по окончании работы целое число, которое трактуетс€ операционной системой как код завершени€ задани€. „исло ноль обычно означает успешное выполнение задачи, но вообще-то программист волен по своему усмотрению определ€ть коды завершени€. ¬о многих книгах привод€тс€ примеры функций main, которые ничего не возвращают, - строго говор€, это ошибка (на которую, к сожалению, многие компил€торы никак не реагируют).

“ело любой функции заключаетс€ в фигурные скобки. ¬ теле функции main вызываетс€ функци€ printf. ¬ данном случае ее единственным аргументом €вл€етс€ строка, котора€ выводитс€ в стандартный поток вывода. —троковые константы в —и заключаютс€ в двойные апострофы. —трока заканчиваетс€ символом перевода курсора в начало следующей строки (читаетс€ как "new line", нова€ строка). ∆елательно любую печать завершать этим символом, иначе при следующей печати нова€ строка будет дописана в конец предыдущей.

—трока

     
return 0;

завершает выполнение функции main и возвращает нулевой результат ее выполнени€. ќперационна€ система трактует нулевой результат как признак успешного завершени€ программы.

ƒл€ выполнени€ данной программы надо сначала ввести ее текст в файл "hello.cpp", использу€ любой текстовый редактор. «атем надо скомпилировать и собрать готовую программу.  онкретные команды завис€т от операционной системы и установленного —и-компил€тора. ¬ системе Unix с компил€тором gcc из пакета GNU это делаетс€ с помощью команды

     
g++ hello.cpp

¬ результате создаетс€ выполн€емый файл с именем "a.out". ƒл€ запуска программы следует выполнить команду

     
./a.out

≈сли необходимо, чтобы в результате компил€ции и сборки создавалс€ выполн€емый файл с именем "hello", то надо выполнить следующую команду:

 
g++ -o hello hello.cpp

«десь в командной строке используетс€ ключ "-o hello" (от слова "output"), задающий им€ "hello" дл€ выходного файла. ¬ этом случае программа запускаетс€ с помощью команды

     
./hello

«аметим, что в системе Unix имена выполн€емых файлов обычно не имеют никакого расширени€. ¬ системах MS DOS и MS Windows выполн€емые файлы имеют расширение ".exe".

“ипы переменных

ѕри рассмотрении типов переменных в —и и C++ следует различать пон€ти€ базового типа и конструкции, позвол€ющей строить новые типы на основе уже построенных. Ѕазовых типов совсем немного - это целые и вещественные числа, которые могут различатьс€ по диапазону возможных значений (или по длине в байтах) и, в случае €зыка C++, логический тип.   конструкци€м относ€тс€ массив, указатель и структура, а также класс в C++.

Ѕазовые типы

¬ €зыке —и используютс€ всего два базовых типа: целые и вещественные числа.  роме того, имеетс€ фиктивный тип void ("пустота"), который примен€етс€ либо дл€ функции, не возвращающей никакого значени€, либо дл€ описани€ указател€ общего типа (когда неизвестна информации о типе объекта, на который ссылаетс€ указатель).

¬ C++ добавлен логический тип.

÷елочисленные типы

÷елочисленные типы различаютс€ по длине в байтах и по наличию знака. »х четыре - char, short, int и long.  роме того, к описанию можно добавл€ть модификаторы unsigned или signed дл€ беззнаковых (неотрицательных) или знаковых целых чисел.

“ип int

—амый естественный целочисленный тип - это тип int, от слова integer - целое число. “ип int всегда соответствует размеру машинного слова или адреса. ¬се действи€ с элементами типа int производ€тс€ максимально быстро. ¬сегда следует выбирать именно тип int, если использование других целочисленных типов не диктуетс€ €вно спецификой решаемой задачи. ѕараметры большинства стандартных функций, работающих с целыми числами или символами, имеют тип int. ÷елочисленные типы были подробно рассмотрены в разделе . ѕодчеркнем еще раз, что целочисленные переменные хран€т на самом деле не целые числа, а элементы кольца вычетов по модулю m, где m - степень двойки.

¬ современных архитектурах элемент типа int занимает 4 байта, т.е. m = 232. Ёлементы типа int трактуютс€ в —и как числа со знаком. ћинимальное отрицательное число равно -231 = -2147483648, максимальное положительное равно 231-1 = 2147483647.

ѕри описании переменной сначала указываетс€ базовый тип, затем - им€ переменной или список имен, разделенных зап€тыми, например,

int x;
int y, z, t;

ѕри описании переменных можно присваивать им начальные значени€:

    
int maxind = 1000;
int a = 5, b = 7;

 роме типа int, существуют еще три целочисленных типа: char, short и long.

“ип char

“ип char представл€ет целые числа в диапазоне от -128 до 127. Ёлементы типа char занимают один байт пам€ти. —лово "char" €вл€етс€ сокращением от character, что в переводе означает "символ". ƒействительно, традиционно символы представл€ютс€ их целочисленными кодами, а код символа занимает один байт (см. раздел ). “ем не менее, подчеркнем, что элементы типа char - это именно целые числа, с ними можно выполн€ть все арифметические операции. — математической точки зрени€, элементы типа char - это элементы кольца вычетов m = Z256. —тандарт —и не устанавливает, трактуютс€ ли элементы типа char как знаковые или беззнаковые числа, но большинство —и-компил€торов считают char знаковым типом. ѕримеры описаний переменных типа char:

char c;
char eof = (-1);
char letterA = ′A′;

¬ последнем случае значение переменной "letterA" инициализируетс€ кодом латинской буквы ′A′, т.е. целым числом 65. ¬ —и символьные константы записываютс€ в одинарных апострофах и означают коды соответствующих символов в кодировке ASCII. –ассмотрим следующий пример:

    
char c = 0;
char d = ′0′;

«десь переменна€ c инициализируетс€ нулевым значением, а переменна€ d - значением 48, поскольку символ ′0′ имеет код 48.

“ипы short и long

—лова short и long означают в —и короткое и длинное целое число со знаком. —тандарт —и не устанавливает конкретных размеров дл€ типов short и long. ¬ самой распространенной в насто€щее врем€ 32-разр€дной архитектуре переменна€ типа short занимает 2 байта (диапазон значений - от -32768 до 32767), а тип long совпадает с типом int, размер его равен четырем байтам. ѕримеры описаний:

short s = 30000;
long x = 100000;
int y = 100000;

¬ 32-разр€дной архитектуре переменные x и y имеют один и тот же тип.

ћодификатор unsigned

“ипы int, short и long представл€ют целые числа со знаком. ƒл€ типа char стандарт —и не устанавливает €вно наличие знака, однако большинство компил€торов трактуют элементы типа char как целые числа со знаком в диапазоне от -128 до 127. ≈сли необходимо трактовать целые числа как неотрицательные, или беззнаковые, следует добавить модификатор unsigned при описании переменных. ѕримеры:

unsigned char c = 255;
unsigned short s = 65535;
unsigned int i = 1000000000;
unsigned j = 1;

ѕри описании типа "unsigned int" слово "int" можно опускать, что и сделано в последнем примере.

—ледует по возможности избегать беззнаковых типов, поскольку арифметика беззнаковых чисел не на всех компьютерах реализована одинаково и из-за этого при переносе программы с одной платформы на другую могут возникнуть проблемы. ѕо этой причине в €зыке Java беззнаковые числа запрещены.

»меетс€ также модификатор signed (знаковый). ≈го имеет смысл использовать на тех платформах, в которых тип char €вл€етс€ беззнаковым. ѕример описани€:

signed char d = (-1);
¬ещественные типы

¬ещественных типов два: длинное вещественное число double (переводитс€ как "двойна€ точность") и короткое вещественное число float (переводитс€ как "плавающее"). ¬ещественные типы были подробно рассмотрены в разделе 1.4.2. ¬ещественное число типа double занимает 8 байтов, типа float - 4 байта.

“ип double €вл€етс€ основным дл€ компьютера. “ип float - это, скорее, атавизм, оставшийс€ от ранних версий €зыка —и.  омпьютер умеет производить арифметические действи€ только с элементами типа double, элементы типа float приходитс€ сначала преобразовывать к double. “очность, которую обеспечивает тип float, низка и не достаточна дл€ большинства практических задач. ¬се стандартные функции математической библиотеки работают только с типом double. –екомендуем вам никогда не использовать тип float!

ѕримеры описаний вещественных переменных:

double x, y, z;
double a = 1.5, b = 1e+6, c = 1.5e-3;

¬ последних двух случа€х использовалось задание вещественных констант в экспоненциальной форме (см. раздел 1.4.2).

Ћогический тип

¬ €зыке —и специального логического типа нет, вместо него используютс€ переменные целого типа. «начению "истина" соответствует любое ненулевое целое число, значению "ложь" - ноль. Ќапример, в —и допустим такой фрагмент программы:

int b;
double s;
. . .
if (b) {
    s = 1.0;
}

«десь целочисленна€ переменна€ b используетс€ в качестве условного выражени€ в операторе if ("если"). ≈сли значение b отлично от нул€, то выполн€етс€ тело оператора if, т.е. переменной s присваиваетс€ значение 1.0; если значение b равно нулю, то тело оператора if не выполн€етс€.

Ќа самом деле, приведенный пример представл€ет собой дурной стиль программировани€. √ораздо €снее выгл€дит следующий фрагмент, эквивалентный приведенному выше:

if (b != 0) {
    s = 1.0;
}

¬ более строгом €зыке Java второй фрагмент корректен, а первый нет.

язык C++ вводит логический тип bool в €вном виде (отметим, что этот тип по€вилс€ в C++ далеко не сразу!). ѕеременные типа bool принимают два значени€: false и true (истина и ложь). —лова false и true €вл€ютс€ ключевыми словами €зыка C++.

ѕримеры описани€ логических переменных в C++:

bool a, b;
bool c = false, d = true;
ќператор sizeof

ѕеременна€ одного и того же типа на разных платформах может занимать различное число байтов пам€ти. язык —и предоставл€ет программисту возможность получить размер элемента данного типа или размер переменной в байтах, дл€ этого служит оператор sizeof. јргумент sizeof указываетс€ в круглых скобках, он может быть типом или переменной. –ассмотрим несколько примеров. ѕусть определены следующие переменные:

int i; char c; short s; long l;
double d; float f; bool b;

“огда приведенные ниже выражени€ в 32-разр€дной архитектуре имеют следующие значени€:

размер переменнойразмер типазначение
sizeof(i)sizeof(int)4
sizeof(c)sizeof(char)1
sizeof(s)sizeof(short)2
sizeof(l)sizeof(long)4
sizeof(d)sizeof(double)8
sizeof(f)sizeof(float)4
sizeof(b)sizeof(bool)1
“ип void

—лово void означает "пустота". “ип void в —и обозначает отсутствие чего-либо там, где обычно предполагаетс€ описание типа. Ќапример, функци€, не возвращающа€ никакого значени€, в —и описываетс€ как возвращающа€ значение типа void:

void f(int x);

ƒругое применение ключевого слова void состоит в описании указател€ общего типа, когда заранее не известен тип объекта, на который он будет ссылатьс€.

 онструирование новых типов

ƒл€ создани€ новых типов в —и можно использовать конструкции массива, указател€ и структуры.

ћассивы

ќписание массива в —и состоит из имени базового типа, названи€ массива и его размера, который указываетс€ в квадратных скобках. –азмер массива об€зательно должен быть целочисленной константой или константным выражением. ѕримеры:

int a[10];
char c[256];
double d[1000];

¬ первой строке описан массив целых чисел из 10 элементов. ѕодчеркнем, что нумераци€ в —и всегда начинаетс€ с нул€, так что индексы элементов массива измен€ютс€ в пределах от 0 до 9. ¬о второй строке описан массив символов из 256 элементов (индексы в пределах 0...255), в третьей - массив вещественных чисел из 1000 элементов (индексы в пределах 0...999). ƒл€ доступа к элементу массива указываетс€ им€ массива и индекс элемента в квадратных скобках, например,

    
a[0], c[255], d[123].

ќператор sizeof возвращает размер всего массива в байтах, а не в элементах массива. ¬ данном примере

sizeof(a) = 10*sizeof(int) = 40,  
sizeof(c) = 256*sizeof(char) = 256,  
sizeof(d) = 1000*sizeof(double) = 8000. 
”казатели

”казатели - это переменные, которые хран€т адреса объектов. ”казатели - фамильна€ принадлежность €зыка —и. ¬ не€вном виде указатели присутствовали и в других €зыках программировани€, но в —и они используютс€ гораздо чаще, а работа с указател€ми огранизована максимально просто.

ѕри описании указател€ надо задать тип объектов, адреса которых будут содержатьс€ в нем. ѕеред именем указател€ при описании ставитс€ звездочка, чтобы отличить его от обычной переменной. ѕримеры описаний указателей:

int *a, *b, c, d;
char *e;
void *f;

¬ первой строке описаны указатели a и b на тип int и простые переменныe c и d типа int (c и d - не указатели!).

— указател€ми возможны следующие два действи€:

  1. присвоить указателю адрес некоторой переменной. ƒл€ этого используетс€ операци€ вз€ти€ адреса, котора€ обозначаетс€ амперсендом &. Ќапример, строка
    a = &c;
    
    указателю a присваивает значение адреса переменной c;
  2. получить объект, адрес которого содержитс€ в указателе; дл€ этого используетс€ операци€ звездочка ′*′, котора€ записываетс€ перед указателем. («аметим, что звездочкой обозначаетс€ также операци€ умножени€.) Ќапример, строка
    d = *a;
    
    присваивает переменной d значение целочисленной переменной, адрес которой содержитс€ в a. “ак как ранее указателю a был присвоен адрес переменной c, то в результате переменной d присваиваетс€ значение c, т.е. данна€ строка эквивалентна следующей:
    d = c;
    

Ќиже будут рассмотрены также арифметические операции с указател€ми, которые в €зыке —и чрезвычайно важны.

—ложные описани€

 онструкции массива и указател€ при описании типа можно примен€ть многократно в произвольном пор€дке.  роме того, можно описывать прототип функции. “аким образом можно строить сложные описани€ вроде "массив указателей", "указатель на указатель", "указатель на массив", "функци€, возвращающа€ значение типа указатель", "указатель на функцию" и т.д. ѕравила здесь таковы:

  • дл€ группировки можно использовать круглые скобки, например, описание
    int *(x[10]);
    
    означает "массив из 10 элементов типа указатель на int";
  • при отсутствии скобок приоритеты конструкций описани€ распределены следующим образом:
    • - операци€ * определени€ указател€ имеет самый низкий приоритет. Ќапример, описание
      int *x[10];
      
      означает "массив из 10 элементов типа указатель на int". «десь к имени переменной x сначала примен€етс€ операци€ определени€ массива [] (квадратные скобки), поскольку она имеет более высокий приоритет, чем звездочка. «атем к полученному массиву примен€етс€ операци€ определени€ указател€. ¬ результате получаетс€ "массив указателей", а не указатель на массив! ≈сли нам нужно определить указатель на массив, то следует использовать круглые скобки при описании:
      int (*x)[10];
      
      «десь к имени x сначала примен€етс€ операци€ * определени€ указател€;
    • операции определени€ массива [] (квадратные скобки после имени) и определени€ функции (круглые скобки после имени) имеют одинаковый приоритет, более высокий, чем звездочка. ѕримеры:
      int f();
      
      ќписан прототип функции f без аргументов, возвращающей значение типа int.
      int (*f())[10];
      
      ќписан прототип функции f без аргументов, возвращающей значение типа указатель на массив из 10 элементов типа int;
  • последний пример уже не €вл€етс€ очевидным. ќбщий алгоритм разбора сложного описани€ можно охарактеризовать как чтение изнутри. —начала находим описываемое им€. «атем определ€ем, кака€ операци€ примен€етс€ к имени первой. ≈сли нет круглых скобок дл€ группировки, то это либо определение указател€ (звездочка слева от имени), либо определение массива (квадратные скобки справа от имени), либо определение функции (круглые скобки справа от имени). “аким образом получаетс€ первый шаг сложного описани€. «атем находим следующую операцию описани€, котора€ примен€етс€ к уже выделенной части сложного описани€, и повтор€ем это до тех пор, пока не исчерпаем все описание. ѕроиллюстрируем этот алгоритм на примере:
    void (*a[100])(int x);
    
    ќписываетс€ переменна€ a.   ней сначала примен€етс€ операци€ описани€ массива из 100 элементов, далее - определение указател€, далее - функци€ от одного целочисленного аргумента x типа int, наконец - определение возвращаемого типа int. ќписание читаетс€ следующим образом:
    1. a - это
    2. массив из 100 элементов типа
    3. указатель на
    4. функцию с одним аргументом x типа int, возвращающую значение типа
    5. void.

    Ќиже расставлены номера операций в пор€дке их применени€ в описании переменной a:

    void (*  a  [100])(int x);
    5)    3) 1) 2)    4)
    
—троки

—пециального типа данных строка в —и нет. —троки представл€ютс€ массивами символов (а символы - их числовыми кодами, см. раздел 1.4.3). ѕоследним символом массива, представл€ющего строку, должен быть символ с нулевым кодом. ѕример:

char str[10];
str[0] = ′e′; str[1] = ′2′;
str[2] = ′e′; str[3] = ′4′;
str[4] = 0;

ќписан массив str из 10 символов, который может представл€ть строку длиной не более 9, поскольку один элемент должен быть зарезервирован дл€ терминирующего нул€. ƒалее в массив str записываетс€ строка "e2e4". —трока терминируетс€ нулевым символом. ¬сего запись строки использует 5 первых элементов массива str с индексами 0...4. ѕоследние 5 элементов массива не используютс€. ћассив можно инициализировать непосредственно при описании, например

    
char t[] = "abc";

«десь мы не указываем в квадратных скобках размер массива t, компил€тор его вычисл€ет сам. ѕосле операции присваивани€ записана строкова€ константа "abc", котора€ заноситс€ в массив t. ¬ результате компил€тор создает массив t из четырех элементов, поскольку на строку отводитс€ 4 байта, включа€ терминирующий ноль.

—троковые константы заключаютс€ в —и в двойные апострофы, в отличие от символьных, которые заключаютс€ в одинарные. «начением строковой константы €вл€етс€ адрес ее первого символа.  огда компил€тор встречает строковую константу в программе, он записывает ее текст в область статической пам€ти, обычно защищенную от изменени€, и использует этот адрес. Ќапример, в результате следующего описани€

const char *s = "abcd";

создаетс€ указатель s, а также строка символов "abcd", строка помещаетс€ в область статической пам€ти, защищенную от изменени€, а в указатель s помещаетс€ адрес начала строки. —трока содержит 5 элементов: коды символов abcd и терминирующий нулевой байт.

ћодификатор const

 онстанты в —и можно задавать двум€ способами:

  • с помощью директивы #define препроцессора. Ќапример, строка
        
    #define MILLENIUM 1000
    
    задает символическое им€ MILLENIUM дл€ константы 1000. ѕрепроцессор всюду в тексте замен€ет это им€ на константу 1000, использу€ текстовую подстановку. Ёто не очень хороший способ, поскольку при таком задании отсутствует контроль типов;
  • с помощью модификатора const. ѕри описании любой переменной можно добавить модификатор типа const. Ќапример, вместо #define можно использовать следующее описание:
        
    const int MILLENIUM = 1000;
    
    ћодификатор const означает, что переменна€ MILLENIUM €вл€етс€ константой, т.е. мен€ть ее значение нельз€. ѕопытка присвоить новое значение константе приведет к ошибке компил€ции:
        
    MILLENIUM = 100; // ќшибка: константу
                         //         нельз€ измен€ть
    

ѕри описании указател€ модификатор const, записанный до звездочки, означает, что описан указатель на константный объект, т.е. на объект, мен€ть который нельз€ или запрещено. Ќапример, в строке

const char *p;

описан указатель на константную строку (массив символов, мен€ть который запрещено).

”казатели на константные объекты используютс€ в —и чрезвычайно часто. ѕричина состоит в том, что константный указатель позвол€ет прочесть объект и при этом гарантирует, что объект не будет испорчен в результате ошибки программировани€, т.к. константный указатель не дает возможности изменить объект.

 онстантный указатель ссылаетс€ на константный объект, однако, содержимое самого указател€ может измен€тьс€. Ќапример, следующий фрагмент вполне корректен:

const char *str = "e2e4";
. . .
str = "c7c5";

«десь константный указатель str сначала содержит адрес константной строки "e2e4". «атем в него записываетс€ адрес другой константной строки "c7c5".

¬ —и можно также описать указатель, значение которого не может быть изменено; дл€ этого модификатор const указываетс€ после звездочки. Ќапример, фрагмент кода

int i;
int * const p = &i;

навечно записывает в указатель p адрес переменной i, перенаправить указатель p на другую переменную уже нельз€. —трока

    
p = &n;

€вл€етс€ ошибкой, т.к. указатель p - константа, а константе нельз€ присвоить новое значение. ”казатели, значени€ которых измен€ть нельз€, используютс€ в —и значительно реже, в основном при заполнении константных таблиц.

ћодификатор volatile

—лово volatile в переводе означает "изменчивый, непосто€нный". ¬ —и к описанию переменной следует добавл€ть слово volatile, если ее значение может измен€тьс€ не в результате выполнени€ программы, а из-за каких-либо внешних событий. Ќапример, переменна€ может изменитьс€ при выполнении программы-обработчика аппаратного прерывани€ (см. раздел 2.5). ƒругой причиной "внезапного" изменени€ значени€ переменной может быть переключение между нит€ми при параллельном программировании (см. 2.6.2) и модификаци€ переменной в параллельной нити.

Ќеобходимо об€зательно сообщать компил€тору о таких изменчивых переменных. ƒело в том, что процессор выполн€ет все действи€ с регистрами, а не с элементами пам€ти. ќптимизирующий компил€тор держит значени€ большинства переменных в регистрах, свод€ к минимуму обращени€ к пам€ти. Ќепосто€нна€ переменна€ может изменить свое значение в пам€ти, но программа будет по-прежнему использовать значение в регистре, которое осталось прежним. »з-за этого выполнение программы нарушитс€. ћодификатор volatile запрещает даже временно помещать переменную в регистр процессора.

ѕример описани€ переменной:

volatile int inputPort;

«десь мы описываем целочисленную переменную inputPort и сообщаем компил€тору, что ее значение может внезапно мен€тьс€ в результате каких-либо внешних событий. Ётим мы запрещаем компил€тору помещать переменную в регистр процессора в цел€х оптимизации программы.

ќператор typedef

¬ €зыке —и можно задать им€ типа, если его описание достаточно громоздко и его не хочетс€ повтор€ть много раз. ¬ дальнейшем можно использовать им€ типа при описании переменных. ƒл€ определени€ типа примен€етс€ оператор typedef. —интаксически оператор typedef аналогичен обычному описанию переменной, к которому в самом начале добавлено слово typedef. ѕри этом вместо переменной определ€етс€ им€ нового типа. —равните следующее описание переменной "real" и определение нового типа "Real":

double real;         // ќписание переменной real
typedef double Real; // ќпределение нового типа Real,
                         // эквивалентного типу double.

ћы как бы описываем переменную, добавл€€ к описанию слово typedef. ѕри этом описываемое им€ становитс€ именем нового типа. ≈го можно использовать затем дл€ задани€ переменных:

Real x, y, z;

„аще всего определение типов с помощью typedef используют, когда описание типа достаточно громоздко. ќператор typedef позвол€ет задать его только один раз, что облегчает исправление программы при необходимости. Ќапример, следующа€ строка определ€ет тип callback как указатель на функцию с одним целым параметром, возвращающую значение логического типа:

typedef bool (*callback)(int);

—трока, описывающа€ три переменные p, g, r,

callback p, q, r;

эквивалентна строке

bool (*p)(int), (*q)(int), (*r)(int);

но перва€ строка, конечно, пон€тнее и нагл€днее.

≈ще одна цель использовани€ оператора typedef состоит в том, чтобы сделать текст программы менее зависимым от особенностей конкретной архитектуры (разр€дности процессора, конкретного —и-компил€тора и т.п.). Ќапример, в старых —и-компил€торах, которые использовались дл€ 16-разр€дных процессоров Intel 80286, существовали так называемые близкие (near) и далекие (far) указатели. ¬ эталонном €зыке —и ключевых слов near и far нет, они использовались лишь в —и-компил€торах дл€ Intel 80286 как расширение €зыка. ѕоэтому, чтобы тексты программ не зависели от компил€тора, в системных h-файлах с помощью оператора typedef определ€лись имена дл€ типов указателей, а в текстах программ использовались не типы эталонного €зыка —и, а введенные имена типов. Ќапример, тип "далекий указатель на константную строку" в соответствии с соглашени€ми фирмы Microsoft называетс€ LPCTSTR (Long Pointer to Constant Text STRing). ѕри использовании 16-разр€дного компил€тора он определ€етс€ в системных h-файлах как

typedef const char far *LPCTSTR;

в 32-разр€дной архитектуре он определ€етс€ без ключевого слова far (поскольку в ней все указатели "далекие"):

typedef const char *LPCTSTR;

¬о всех программах указатели на константные строки описываютс€ как имеющие тип LPCTSTR:

    
LPCTSTR s;

благодар€ этому программы Microsoft можно использовать как в 16-разр€дной, так и в 32-разр€дной архитектуре.

¬ыражени€

¬ыражени€ в —и составл€ютс€ из переменных или констант, к которым примен€ютс€ различные операции. ƒл€ указани€ пор€дка операций можно использовать круглые скобки.

ќтметим, что, помимо обычных операций, таких, как сложение или умножение, в —и существует р€д операций, несколько непривычных дл€ начинающих. Ќапример, зап€та€ и знак равенства (оператор присваивани€) €вл€ютс€ операци€ми в —и; помимо операции сложени€ +, есть еще операци€ увеличить на += и операци€ увеличени€ на единицу ++. «ачастую они позвол€ют писать эстетически красивые, но не очень пон€тные дл€ начинающих программы.

¬прочем, эти непривычные операции можно не использовать, замен€€ их традиционными.

ќператор присваивани€

ќператор присваивани€ €вл€етс€ основой любого алгоритмического €зыка (см. лекцию 3). ¬ —и он записываетс€ с помощью символа равенства, например, строка

x = 100;

означает присвоение переменной x значени€ 100. ƒл€ сравнени€ двух значений используетс€ двойное равенство ==, например, строка

bool f = (2 + 2 == 5);

присваивает логической переменной f значение false (поскольку 2+2 не равно п€ти, логическое выражение в скобках ложно).

Ќепривычным дл€ начинающих может быть то, что оператор присваивани€ "=" в —и - бинарна€ операци€, така€ же, как, например, сложение или умножение. «начением операции присваивани€ = €вл€етс€ значение, которое присваиваетс€ переменной, сто€щей в левой части. Ёто позвол€ет использовать знак присваивани€ внутри выражени€, например,

x = (y = sin(z)) + 1.0;

«десь в скобках стоит выражение y = sin(z), в результате вычислени€ которого переменной y присваиваетс€ значение sin z. «начением этого выражени€ €вл€етс€ значение, присвоенное переменной y, т.е. sin z.   этому значению затем прибавл€етс€ единица, т.е. в результате переменной x присваиваетс€ значение sin z+1.

¬ыражени€, подобные приведенному в этом примере, иногда используютс€, когда необходимо запомнить значение подвыражени€ (в данном случае sin (z)) в некоторой переменной (в данном случае y), чтобы затем не вычисл€ть его повторно. ≈ще один пример:

n = (k = 3) + 2;

¬ результате переменной k присваиваетс€ значение 3, а переменной n - значение 5.  онечно, в нормальных программах такие выражени€ не встречаютс€.

јрифметические операции

  четырем обычным арифметическим операци€м сложени€ +, вычитани€ -, умножени€ * и делени€ / в —и добавлена операци€ нахождени€ остатка от делени€ первого целого числа на второе, котора€ обозначаетс€ символом процента %. ѕриоритет у операции вычислени€ остатка % такой же, как и у делени€ или умножени€. ќтметим, что операци€ % перестановочна с операцией изменени€ знака (унарным минусом), например, в результате выполнени€ двух строк

x = -(5 % 3);
y = (-5) % 3;

обеим переменным x и y присваиваетс€ отрицательное значение -2.

ќперации увеличени€ и уменьшени€

¬ —и добавлены операции увеличени€ и уменьшени€ на единицу, которые, к примеру, очень удобно примен€ть к счетчикам. ќпераци€ увеличени€ записываетс€ с помощью двух знаков сложени€ ++, операци€ уменьшени€ - с помощью двух минусов --. Ќапример, операци€ ++, примененна€ к целочисленной переменной i, увеличивает ее значение на единицу:

++i;   эквивалентно i = i+1 

ќперации увеличени€ и уменьшени€ на единицу можно примен€ть только к дискретным типам - целочисленным переменным различного вида и указател€м. ќперацию нельз€ примен€ть к вещественным переменным! Ќапример, следующий фрагмент программы €вл€етс€ ошибочным:

double x;
. . .
++x;  // ќшибка! ќпераци€ ++ неприменима
      //         к вещ. переменной

ќпераци€ ++ увеличивает значение переменной на "минимальный атом". “ак как дл€ вещественных переменных такого "атомарного" значени€ нет, операции увеличени€ и уменьшени€ дл€ них запрещены.

ƒл€ указателей операци€ ++ увеличивает значение переменной на размер одного элемента того типа, на который ссылаетс€ указатель. ƒл€ указател€ "атомом" €вл€етс€ один элемент заданного типа, поэтому размер одного элемента и €вл€етс€ шагом изменени€ значени€ указател€. Ёто очень естественно, т.к. после увеличени€ указатель будет содержать адрес следующего элемента данного типа, а после уменьшени€ - адрес предыдущего элемента. ѕример:

double a[100];
double *p = &(a[15]); // в p записываетс€ адрес
                      // элемента массива a[15]
++p; // в p будет адрес элемента a[16]
     // (адрес увеличиваетс€ на sizeof(double) == 8)

ќписаны массив a вещественных чисел типа double и указатель p на элементы типа double. ѕри описании указател€ p в него заноситс€ начальное значение, равное адресу элемента a[15] массива a. ѕосле выполнени€ операции увеличени€ ++ в переменной p будет содержатьс€ адрес следующего элемента a[16]. ‘изически содержимое переменной p увеличиваетс€ на размер одного элемента типа double, т.е. на 8.

ќперации увеличени€ ++ и уменьшени€ -- на единицу имеют префиксную и суффиксную формы. ¬ префиксной форме операци€ записываетс€ перед переменной, как в приведенных выше примерах. ¬ суффиксной форме операци€ записываетс€ после переменной:

++x;    // ѕрефиксна€ форма
x--;    // —уффиксна€ форма

–азница между префиксной и суффиксной формами про€вл€етс€ только при вычислении сложных выражений. ≈сли используетс€ префиксна€ форма операции ++, то сначала переменна€ увеличиваетс€, и только после этого ее новое значение используетс€ в выражении. ѕри использовании суффиксной формы значение переменной сначала используетс€ в выражении и только затем увеличиваетс€. ѕримеры:

int x = 5, y = 5, a, b;
a = (++x) + 2; // переменной a присваиваетс€ значение 8
b = (y++) + 2; // переменной b присваиваетс€ значение 7

— логической точки зрени€, префиксна€ операци€ более естественна (при использовании суффиксной формы надо сперва вычислить сложное выражение и только затем вернутьс€ к увеличению переменной, т.е. операци€ ++ выполн€етс€ не в момент ее использовани€, а как бы откладываетс€ на потом). «абега€ вперед, отметим, что это различие весьма существенно при программировании на C++ в случае переопределени€ операторов увеличени€ дл€ классов. “ем не менее, в большинстве книг по —и суффиксна€ форма используетс€ чаще (скорее всего, эта традици€, св€зана€ с эстетикой текста).

ƒадим два совета (возможно, не бесспорные) по использованию операций ++ и --:

  • никогда не примен€йте эти операции в сложных выражени€х! Ќичего, кроме путаницы, это не дает. Ќапример, вместо фрагмента
    double *p, x, y;
    . . .
    y = *p++ + x;
    
    лучше использовать фрагмент
     
    double *p, x, y;
    . . .
    y = *p + x;
    ++p;
    
    — точки зрени€ компил€тора, они абсолютно эквивалентны, но второй фрагмент проще и пон€тнее (и, значит, веро€тность ошибки программировани€ меньше);
  • всегда отдавайте предпочтение префиксной форме операций ++ и --. Ќапример, вместо фрагмента
    int x, y;
    . . .
    x++; y--; // »спользуетс€ суффиксна€ форма
    
    лучше использовать фрагмент
    int x, y;
    . . .
    ++x; --y; // Ћучше примен€ть префиксную форму
    

ќперации "увеличить на", "домножить на" и т.п.

¬ большинстве алгоритмов при выполнении операции сложени€ чаще всего переменна€-результат операции совпадает с первым аргументом:

x = x + y;

«десь складываютс€ значени€ двух переменных x и y, результат помещаетс€ в первую переменную x. “аким образом, значение переменной x увеличиваетс€ на значение y. ѕодобные фрагменты встречаютс€ в программах гораздо чаще, чем фрагменты вида

x = y + z;

где аргументы и результат различны. –ассмотрим, например, фрагмент программы, вычисл€ющий сумму элементов массива вещественных чисел (забега€ вперед, мы используем в нем конструкцию цикла "пока"):

double a[100];
double s;
int i;
. . .
s = 0.0;
i = 0;
while (i < 100) {
    s = s + a[i];
    ++i;
}

«десь сумма элементов массива накапливаетс€ в переменной s. ¬ строке

s = s + a[i];

к сумме s прибавл€етс€ очередной элемент массива a[i], т.е. значение s увеличиваетс€ на a[i]. ¬ —и существует сокращенна€ запись операции увеличени€:

s += a[i];

ќператор += читаетс€ как "увеличить на". —трока

x += y;    // ”величить значение x на y

эквивалентна в —и строке

x = x + y; // x присвоить значение x + y,

но короче и нагл€днее.

ќператор вида ?= существует дл€ любой операции ?, допустимой в —и. Ќапример, дл€ арифметических операций +, -, *, /, % можно использовать операции

+= увеличить на
-= уменьшить на
*= домножить на
/= поделить на
%= поделить с остатком на

к примеру, строка

x *= 2.0;

удваивает значение вещественной переменной x.

ќператоры вида ?= можно использовать даже дл€ операций ?, которые записываютс€ двум€ символами. Ќапример, операции логического умножени€ и сложени€ (см. раздел 1.4.4) записываютс€ в —и как && (двойной амперсенд) и || (двойна€ вертикальна€ черта). —оответственно, логические операторы "домножить на" и "увеличить на" записываютс€ в виде &&= и ||=, например,

bool x, y;
x &&= y;    // эквивалентно x = x && y;
x ||= y;    // эквивалентно x = x || y;

Ћогические операции

Ћогические операции и выражени€ были подробно рассмотрены в разделе 1.4.4. ¬ —и используютс€ следующие обозначени€ дл€ логических операций:

|| логическое "или" (логическое сложение)
&& логическое "и" (логическое умножение) 
! логическое "не" (логическое отрицание)

Ћогические константы "истина" и "ложь" обозначаютс€ через true и false (это ключевые слова €зыка). ѕримеры логических выражений:

bool a, b, c, d;
int x, y;

a = b || c;            // логическое "или"
d = b && c;            // логическое "и"
a = !b;                // логическое "не"
a = (x == y);          // сравнение в правой части
a = false;             // ложь
b = true;              // истина
c = (x > 0 && y != 1); // c истинно, когда
                           // оба сравнени€ истинны

—амый высокий приоритет у операции логического отрицани€, затем следует логическое умножение, самый низкий приоритет у логического сложени€.

„резвычайно важной особенностью операций логического сложени€ и умножени€ €вл€етс€ так называемое "сокращенное вычисление" результата. ј именно, при вычислении результата операции логического сложени€ или умножени€ всегда сначала вычисл€етс€ значение первого аргумента. ≈сли оно истинно в случае логического сложени€ или ложно в случае логического умножени€, то второй аргумент операции не вычисл€етс€ вовсе! –езультат операции полагаетс€ истинным в случае логического сложени€ или ложным в случае логического умножени€. ѕодробно это рассмотрено в разделе 1.4.4.

ќперации сравнени€

ќпераци€ сравнени€ сравнивает два выражени€. ¬ результате вырабатываетс€ логическое значение - true или false (истина или ложь) в зависимости от значений выражений. ѕримеры:

bool res;
int x, y;
res = (x == y); // true, если x равно y, иначе false
res = (x == x); // всегда true
res = (2 < 1);  // всегда false

ќперации сравнени€ в —и обозначаютс€ следующим образом:

== равно,  != не равно,
> больше,  >= больше или равно,
< меньше,  <= меньше или равно.

ѕобитовые логические операции

 роме обычных логических операций, в —и имеютс€ побитовые логические операции, которые выполн€ютс€ независимо дл€ каждого отдельного бита операндов. ѕобитовые операции имеют следующие обозначени€:

& побитовое логическое сложение ("и")
| побитовое логическое умножение ("или")
~ побитовое логическое отрицание ("не")
^ побитовое сложение по модулю 2 (исключающее "или")

(Ќеобходимо помнить, что логические операции умножени€ и сложени€ записываютс€ с помощью двойных знаков && или ||, а побитовые - с помощью одинарных.)

Ќи в коем случае не используйте побитовые операции в качестве логических условий, это может приводить к непредсказуемым ошибкам!

¬ основном побитовые операции примен€ютс€ дл€ манипул€ций с битовыми масками. Ќапример, пусть целое число x описывает набор признаков некоторого объекта, состо€щий из четырех признаков. Ќазовем их условно A, B, C, D. ѕусть за признак A отвечает нулевой бит слова x (биты в двоичном представлении числа нумеруютс€ справа налево, начина€ с нул€). ≈сли бит равен единице (программисты говор€т бит установлен), то считаетс€, что объект обладает признаком A. «а признаки B, C, D отвечают биты с номерами 1, 2, 3. ќбщеприн€та€ практика состоит в том, чтобы определить константы, отвечающие за соответствующие признаки (их обычно называют масками):

const int MASK_A = 1;
const int MASK_B = 2;
const int MASK_C = 4;
const int MASK_D = 8;

Ёти константы содержат единицу в соответствующем бите и нули в остальных битах. ƒл€ того чтобы проверить, установлен ли в слове x бит, соответствующий, к примеру, признаку D, используетс€ операци€ побитового логического умножени€. „исло x умножаетс€ на константу MASK_D; если результат отличен от нул€, то бит установлен, т.е. объект обладает признаком D, если нет, то не обладает. “ака€ проверка реализуетс€ следующим фрагментом:

 
if ((x & MASK_D) != 0) {
    // Ѕит D установлен в слове x, т.е.
    // объект обладает признаком D
    . . .
} else {
    // ќбъект не обладает признаком D
    . . .
}

ѕри побитовом логическом умножении константа MASK_D обнул€ет все биты слова x, кроме бита D, т.е. как бы вырезает бит D из x. ¬ двоичном представлении это выгл€дит п  началу статьи





ƒобавил: MadvEXƒата публикации: 2006-02-28 01:45:41
–ейтинг статьи:5.00 [√олосов 5] ол-во просмотров: 14875

 омментарии читателей

¬сего комментариев: 8

2017-06-28 06:09:56
Jasonteert
¬куснейший экзотический плод - мангустин, стал насто€щим открытием в диетологии!
ќн содержит –≈ ќ–ƒЌќ≈ количество полезных веществ, стимулирующих активное жиросжигание и снижающих вес!
—ироп мангустина растопит до 10 кг жира за 2 недели!
—паситесь от ожирени€ и сократите риск инфаркта, диабета и гипертонии на 89%.

–Р 39 –Є–Ј –љ–Є—Е —Б–Њ–і–µ—А–ґ–∞—В –њ–ї–Њ–і—Л –Љ–∞–љ–≥—Г—Б—В–Є–љ–∞. –†–∞—Б—В—П–ґ–Ї–Є вАУ —Н—В–Њ –і–µ—Д–µ–Ї—В—Л –Ї–Њ–ґ–Є, –Ї–Њ—В–Њ—А—Л–µ –љ–µ –њ—А–Є—З–Є–љ—П—О—В –≤—А–µ–і–∞ –Ј–і–Њ—А–Њ–≤—М—О, –љ–Њ –љ–µ–≥–∞—В–Є–≤–љ–Њ –≤–ї–Є—П—О—В –љ–∞ –≤–љ–µ—И–љ–Њ—Б—В—М —З–µ–ї–Њ–≤–µ–Ї–∞. –Ґ–∞–Ї –≤—Л —Б–њ—А–∞–≤–Є—В–µ—Б—М –љ–µ —В–Њ–ї—М–Ї–Њ —Б –њ—А–Њ—П–≤–ї–µ–љ–Є—П–Љ–Є —Ж–µ–ї–ї—О–ї–Є—В–∞, –љ–Њ –Є —Б –њ–Њ–≤—Л—И–µ–љ–љ–Њ–є –Њ—В–µ—З–љ–Њ—Б—В—М—О. –Ф–µ–ї–Њ –≤ —В–Њ–Љ, –Ї—В–Њ –Ї–Њ–ґ–∞ —З–µ–ї–Њ–≤–µ–Ї–∞ —Б–Њ—Б—В–Њ–Є—В –Є–Ј –≤–Њ–ї–Њ–Ї–Њ–љ —Н–ї–∞—Б—В–Є–љ–∞ –Є –Ї–Њ–ї–ї–∞–≥–µ–љ–∞. –Э–µ–±–Њ–ї—М—И–∞—П —Б–њ—А–∞–≤–Ї–∞:–Ь—Л—И–µ—З–љ–∞—П –∞—В—А–Њ—Д–Є—П –њ—А–Њ—П–≤–ї—П–µ—В—Б—П –≤ –≤–Є–і–µ –Є—Б—В–Њ–љ—З–µ–љ–Є—П –Є —Г–Љ–µ–љ—М—И–µ–љ–Є—П –≤–Њ–ї–Њ–Ї–Њ–љ –Љ—Л—И–µ—З–љ—Л—Е, —З—В–Њ –ї–Є—И–∞–µ—В –Є—Е –Њ—Б–љ–Њ–≤–љ–Њ–є —Д—Г–љ–Ї—Ж–Є–Є -—Б–Њ–Ї—А–∞—В–Є—В–µ–ї—М–љ–Њ–є. –°–ї–µ–і—Г–µ—В –Њ—В–Љ–µ—В–Є—В—М, —З—В–Њ 100% –Љ–∞–љ–≥—Г—Б—В–∞–љ —Б–Њ–Ї –љ–µ–Љ–љ–Њ–≥–Њ –≥–Њ—А—М–Ї–Є–є –Є–ї–Є —В–µ—А–њ–Ї–Є–є, –Є –њ–Њ—Н—В–Њ–Љ—Г –Њ–љ–∞ —З–∞—Б—В–Њ –њ—А–Є—Е–Њ–і–Є—В –≤ –≤–Є–і–µ —Б–Љ–µ—Б–Є. –Э–Њ –љ–µ —В–Њ–ї—М–Ї–Њ –њ–Њ—Н—В–Њ–Љ—Г. –Э–Њ –µ—Б—В—М –Є —Б–Є–љ—В–µ—В–Є—З–µ—Б–Ї–Є–є, –љ–∞ –Њ—Б–љ–Њ–≤–µ —Б–Є–љ—В–µ—В–Є—З–µ—Б–Ї–Њ–≥–Њ –Ї–∞—Г—З—Г–Ї–∞. –Ш–Ј-–Ј–∞ –ї–Є—И–љ–µ–≥–Њ –≤–µ—Б–∞ —П —Б—В–µ—Б–љ—П–ї—Б—П –Ј–љ–∞–Ї–Њ–Љ–Є—В—М—Б—П —Б –і–µ–≤—Г—И–Ї–∞–Љ–Є, —Б–µ–Љ—М–Є —Г –Љ–µ–љ—П –љ–µ –±—Л–ї–Њ. –Ш–Љ–µ–љ–љ–Њ –њ–Њ—Н—В–Њ–Љ—Г –Њ–љ–Є –≤—Л–љ—Г–ґ–і–µ–љ—Л –њ—А–Є–±–µ–≥–∞—В—М –Ї —А–∞–Ј–ї–Є—З–љ—Л–Љ —Б—А–µ–і—Б—В–≤–∞–Љ. –Ш–Љ–µ–љ–љ–Њ –њ–Њ—Н—В–Њ–Љ—Г –±–Њ–ї—М—И–Є–љ—Б—В–≤–Њ –Є–Ј –љ–Є—Е –±—А–Њ—Б–∞—О—В —Б–≤–Њ–Є –њ–Њ–њ—Л—В–Ї–Є –њ–Њ—Е—Г–і–µ—В—М –њ—А–Є –њ–µ—А–≤–Њ–є –љ–µ—Г–і–∞—З–µ. –≠—В–Њ—В —Д—А—Г–Ї—В —А–∞—Б—В–µ—В –љ–∞ –Ь–∞–ї–∞–є—Б–Ї–Њ–Љ –∞—А—Е–Є–њ–µ–ї–∞–≥–µ, –≥–і–µ –і–∞–≤–љ–Њ –Ј–∞–Љ–µ—В–Є–ї–Є –µ–≥–Њ —Ж–µ–ї–µ–±–љ—Л–µ —Б–≤–Њ–є—Б—В–≤–∞. –≠—В–Њ—В –Ї–Њ–Љ–њ–Њ–љ–µ–љ—В –њ–Њ–і–∞–≤–ї—П–µ—В —З—Г–≤—Б—В–≤–Њ –≥–Њ–ї–Њ–і–∞ –Є –Њ—В–њ—А–∞–≤–ї—П–µ—В –≤ –Љ–Њ–Ј–≥ —Б–Є–≥–љ–∞–ї—Л, —З—В–Њ –≤—Л —Б—Л—В—Л –і–∞–ґ–µ –њ–Њ—Б–ї–µ –њ—А–Є–µ–Љ–∞ –Љ–∞–ї–Њ–є –њ–Њ—А—Ж–Є–Є –њ–Є—Й–Є. –≠—В–Њ —Б–∞–Љ—Л–є –ї—Г—З—И–Є–є –Љ–Њ–є —А–µ–Ј—Г–ї—М—В–∞—В.

ѕерейти на сайт: http://mangjoo77.mangoosteen.com/

2017-06-19 15:39:28
GeorgeKax
ѕолучить первые результаты от применени€ вы сможете уже через несколько процедур  ожа станет заметно более упругой, гладкой, шелковистой  роме того, вас покинут непри€тный зуд и жжение, уйдут покраснени€ ѕрепарат Tinedol, отзывы на который вы найдете в сети, поможет вам не только избавитс€ от уже имеющейс€ проблемы, но и предотвратить заражение в принципе вы можете использовать крем в качестве профилактики ¬ инструкции по применению все подробно описано.
„тобы крем оказывал нужное воздействие на пораженную грибком кожу, его следует правильно хранить Ёто должно быть темное сухое место с температурой не выше 25 градусов —ледует предотвратить попадани€ на упаковку пр€мых солнечных лучей.
4 6 –ешение о выдаче не выдаче персональных данных, принимаетс€ јдминистрацией, лишь на основании запроса, посланного лицом јдминистрации, в установленном нормами действующего законодательства пор€дке.
ѕокраснение стоп, сильный зуд, непри€тный запах все это указывает на грибковую инфекцию ќт подобного паразита т€жело избавитьс€, и многие медикаменты не справл€ютс€ с этой задачей Ѕыстро устранить все непри€тные изменени€ на ногах при заражении грибком поможет инновационное средство Tinedol ѕрепарат содержит только природные компоненты „то представл€ет собой Tinedol ћазь Tinedol hellip.
√лазные капли с гиалуроновой кислотой в полимерном контейнере, объемом 0,4 мл содержат √иалуронат натри€ 0,4 мг; —укцинатный буфер рЌ 7,3 до 0,4 мл.
Tinedol представл€ет собой инновационную разработку ведущих специалистов, котора€ позвол€ет не просто удалить грибок, но и устранить все проблемы с кожей, возникшие из-за развити€ недуга ƒанна€ проблема, при возникновении, довольно быстро поражает большие участки дермы, ухудшает состо€ние ногтей и вызывает другие непри€тные процессы.
2 165  рем —идор “ихонов 04 04 2017 15 14.
7 ¬рем€ года.
„тобы быстро достичь желаемого результата, использовать крем от грибка Tinedol следует регул€рно и в соответствии с инструкцией по применению —редство предназначено исключительно дл€ наружного применени€ и наноситьс€ должно дважды в сутки на чистую и сухую кожу стоп ѕри этом совсем не об€зательно наносить большое количество крема по всей поверхности стопы, достаточно будет лишь покрыть тонким слоем только пораженные грибком участки кожи и ногтей.
ѕрепарат не имеет противопоказаний, так как содержащиес€ в нем компоненты не вызывают побочных эффектов ¬ инструкции к средству можно найти информацию о том, что от крема следует отказатьс€ лишь в одном случае при индивидуальной непереносимости одного или нескольких компонентов “акже стоит обратить внимание на то, что “инедол нужно хранить в сухом месте, куда не попадают пр€мые солнечные лучи “емпература хранени€ должна составл€ть не менее 5 — и не более 25 —.


ќфициальный сайт: http://tinedol.1stbest.info/

2017-06-11 20:33:49
Derekbot
Red Machine (–†—Н–і –Ь—Н—Й–Є–љ –Ї–∞–њ—Б—Г–ї—Л –і–ї—П –њ–Њ—В–µ–љ—Ж–Є–Є. Global-Trend.Club –Ы—Г—З—И–Є–µ –Љ–Є—А–Њ–≤—Л–µ —В—А–µ–љ–і–Њ–≤—Л–µ —В–Њ–≤–∞—А—Л. 365 –Њ—В–Ј—Л–≤–Њ–≤, 85 –њ–Њ–ї–Њ–ґ–Є—В–µ–ї—М–љ—Л—Е. –°–Њ–Њ–±—Й–Є—В—М . biomanix56.moykrest.ru

2017-06-09 19:10:51
ћебель каталог
 аждый из нас когда-нибудь сталкиваетс€ с необходимостью выбора новой мебели. ѕростой на первый взгл€д, этот шаг очень важный и ответственный, особенно если дело касаетс€ выбора спальни, купить которую в отличном качестве - значит обеспечить себе полноценный здоровый отдых. ћногие ограничиваютс€ посещением одного магазина, расположенного по соседству с домом и делают выбор исход€ из ценовой политики продавца, покупа€ мебель подешевле. Ќо, покупа€ спальни недорого, нужно об€зательно ориентироватьс€ на качество мебели. ¬ магазине не каждый обращает внимание на отделку, на присутствие постороннего запаха от ƒ—ѕ, некоторые забывают измерить размеры комнаты, где будет сто€ть мебель.
ѕоэтому, чтобы покупка радовала вас долгие годы и дарила только положительные эмоции, нужно заранее продумать, какой должна быть спальн€. ћосква - город, позвол€ющий найти в достаточном количестве добросовестных производителей и поставщиков мебели, продукци€ которых соответствует самым строгим требовани€м современного покупател€.¬ их магазинах можно получить гарантии качества и квалифицированную консультацию по поводу правильного подбора мебели, уходу за ней.


ќфициальный сайт: http://1stbest.info/

2017-06-09 19:07:45
JosefTromy
Ќемного о составе препарата.
¬ отличие от многих конкурирующих препаратов противогрибкового и антимикробного действи€, “инедол не содержит вредных химикатов, канцерогенов и консервантов ѕрименение препарата полностью безопасно благодар€ его запатентованной растительной формуле ¬се ингредиенты активно взаимодействуют друг с другом, оказыва€ стойкий противогрибковый эффект на ногти и кожу стоп.
6 5  онтактные данные администрации.
ѕродукт предлагаетс€ по доступной цене 990 рублей за тюбик, которого хватит на полноценный лечебный курс ќднако расход средства определ€етс€ областью поражени€ “акже рекомендуетс€ использовать препарат в профилактических цел€х тем, у кого в окружении находитс€ человек, зараженный грибком стопы.
Lanolin ланолин способствует питанию кожи, а также ее см€гчению и увлажнению, защищает дерму от воздействи€ вредных бактерий и микроорганизмов, преп€тствует их распространению.
ќднажды после очень жаркого лета € заметил, что кожа между пальцами покраснела ћне подумалось, что повода дл€ беспокойства нет Ќо вскоре € очень пожалел об этом —топы стали покрыватьс€ трещинами, кожа начала шелушитьс€ ѕосто€нный зуд не давал поко€ ќсобенно т€жело было на работе целый день в носках и туфл€х это насто€щее испытание ƒома € тоже не мог расслабитьс€, ведь у мен€ есть два сына и € не хотел их заразить ѕерепробовал огромное число кремов и присыпок, и ничего не помогало ќднажды встретил школьную подругу, котора€ посоветовала мне Tinedol ’оть € и сомневалс€, но все же купил мазь ÷елый мес€ц € исправно наносил ее на ноги и, к счастью, проблема стала уходить –ешил вз€ть еще одну упаковку, чтобы завершить лечение полностью „ерез два мес€ца мо€ кожа выгл€дела чистой, без воспалений » никакого грибка больше нет.
 лимбазол устран€ет такие симптомы инфекции, как воспалени€, зуд, а также покраснени€, убивает вредные бактерии √ипоаллергенный.
ќќќ ё–ия-‘ј–ћ , ”краина, 03141, г  иев, ул Ќ јмосова, 10 на заводе ќќќ ё–ия-‘ј–ћ , ”краина, 18030, г „еркасы, ул ¬ербовецкого, 108 “ел 044 281-01-01.
ќсновные причины возникновени€ инфекции на ногах.
витамин ≈ усиливает регенерацию тканей, избавл€ет от шелушени€, см€гчает.


ќфициальный сайт: http://tinedol.1stbest.info/

2011-12-18 17:58:15
cookybreed
очень доступно,спасибо большое)

2010-11-01 22:24:38
яяяя
ƒа спасибо большое, правда очень помогло.  ратко, четко и все пон€тно даже дл€ мен€)))

2010-02-11 11:38:32
Ѕаг»ра
—упер. √отовые лекции дл€ моих студентов!!!!! кратко, емко и всем пон€тно!!!!!! —пасибо!!!
¬аше им€: *
“екст записи: *
»м€:

ѕароль:



–егистраци€

 акую P2P-сеть предпочитаете?
Kazaa
6% (7)
Shareaza
2% (3)
Ml'Donkey
9% (11)
BitTorrent
21% (27)
ƒругой
8% (10)
ј что такое P2P?
21% (27)
Ќичем не пользуюсь
28% (35)
Ќенавижу P2P!!!
6% (7)

ѕроголосовало: 127
” женщины-программистки есть три пути сделать себе карьеру: два спереди и один сзади!
–ейтинг: 5/10 (9)
ѕосмотреть все анекдоты