Основные операции с типами данных в C/С++




Сайт создан в системе uCoz
Вернуться в Доки-Токи

 

Автор: Andrey Rjavskov(Rzhavskov) as rjaan <rjaan@yandex.ru>


1. Введение

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

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

2. Тип

Типом называется размерность представления данных, которая создает объект, находящийся в оперативной памяти. Он может задавать не только размерность, но и диапазон действительных значений. Эти значение можно назвать свойствами объекта. Краткое обозначение Т.

3. Объект

Объект – это структурированные данные, соответствующие определённому типу, по которому была выделена память. Краткое обозначение О.

4. Выражение

С помощью выражения формируется объект. Выражения бывают двух типов:

  • указателем типа, который содержит адрес объекта в памяти, обозначается E;
  • адресное выражение, ссылается на объект, на который указывает E, обозначается *E;

4.2 lvalue

Понятие lvalue происходит от английского left value – значение в левой части. Обозначает адресное выражение ссылающееся на объект. т.е. E1 = E2 , где E1 – адресное выражение; E2 – выражение типа или его адреса .

5. Фундаментальные типы

Фундаментальные типы(встроенные типы) являются базовыми типами на которых строятся производные типы и типы определённые пользователем.

К фундаментальным типам относят:

  • логические типы;
  • символьные типы;
  • целые типы;
  • Типы с плавающей точкой;

5.2 Логические типы

К таким типам относится тип bool. Он может принимать только два значения TRUE или FALSE. Если применить интегральное продвижение значения типа bool будут иметь следующие значения:

  • false равняется нулю;
  • true равняется единицы;

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

#if !defined Bool_usertype
#define Bool_usertype 1

typedef Bool_type { False=0, True } Bool_t;

#endif /*Bool_usertype*/

5.3 Символьные типы

char относиться к символьному типу. Используется для объявления символьных переменных, содержащих один символ. Может быть представлен с учетом знака, так и без него. Без учётом знака к типу прибавляется префикс unsigned. Таким образом, выражение будет иметь вид:

unsigned char valueЗначение объекта value будет находится в диапазоне 0...65353
signed char valueЗначение объекта value будет находится в диапазоне -127...128

Для создания объекта с типом char с учетом знака допускается опускать префикс signed. Таким образом, будет тождественна следующая запись:

signed T == T

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

Без учёта знака для всех фундаментальных типов будет верна следующая запись:

unsigned T;

При использовании интегрального продвижения этот тип присваивается к unsigned int или int, соответственно.

5.3.2 Тип wchar_t

Размерность wchar_t зависит от реализации. Он используется для хранения символов большего размера.

Символы большего размера могут быть представлены последовательностью из четырех и восьми символов:

\UXXXX и
\UXXXXXXXX,

соответственно. Здесь X – представляет цифру в шестнадцатеричном представлении.

Любые отклонения от количества цифр в последовательности является ошибкой. Этот тип обычно используют в строках, где символы имеют кодировку Unicode.

5.3.3 Символьный литерал

Иногда к символьным типам относится символьный литерал. Хотя на самом деле, он относится к производному типу cоnst char, который будет рассматриваться позднее.

Символьный литерал имеет следующее представление:

char ch = 'a';

5.4 Целые типы

К целым типам относятся: int, signed int, unsigned int.

Целые типы имеют три размерности: short int, int, long int, где имеют быть следующее тождества:

short int == short;
long int == long;

5.4.2 Целые литералы

Целые литералы являются числовым значениями объекта, которые могут иметь следующие представления:

Десятичное01248163264256
Восьмеричное0001020401002004001000400

Десятичное значение 255, что означает 8-мь единиц в байте может быть представлено в шестнадцатеричном виде как 0xff, а в восьмеричном виде как 377.

5.4.2 Размерность типов long и int

В некоторых старых учебниках авторы ссылаясь на стандарты C89 и С99 часто пишут, что размерность типа int составляет два байта. А на самом деле в ОС Linux он имеет 4 байта, потому что мы имеем дело с 32-х разрядной архитектурой процессора, которая определяет размерность типов данных. В 64-х разрядной архитектуре, соответственно, тип int может иметь будет размерность 8 байт, но это не факт о чем скажу ниже. А вот как раз на 16-ти разрядной архитектуре, часто используемая в контроллерах, этот тип будет иметь размерность в два байта. Поэтому, когда используем разные архитектуры с отличающийся друг от друга разрядностью обращаем внимание на то, какую размерность имеют типы данных.

В ОС Linux разрядность и диапазоны значений определены в заголовочном файле >limits.h< системной библиотеки, и если мы посмотрим, то что определено в этом файле касательно int увидим следующее

/* Minimum and maximum values a `signed int' can hold. */
# define INT_MIN (-INT_MAX - 1)
# define INT_MAX 2147483647

/* Maximum value an `unsigned int' can hold. (Minimum is 0.) */
# define UINT_MAX 4294967295U

что соответствует 4 байтaм( 2 ^ 32 ). Между прочим, давным-давно разбираясь с представлением типов С/С++ в Linux обнаружил, что в 64-х разрядной архитектуре тип int будет иметь размерность 4-байта. В тоже время, тип long будет иметь 8 байт, как следует из того же заголовочного файла >limits.h<

/* Minimum and maximum values a `signed long int' can hold. */
# if __WORDSIZE == 64
# define LONG_MAX 9223372036854775807L
# else
# define LONG_MAX 2147483647L
# endif
# define LONG_MIN (-LONG_MAX - 1L)

/* Maximum value an `unsigned long int' can hold. (Minimum is 0.) */
# if __WORDSIZE == 64
# define ULONG_MAX 18446744073709551615UL
# else
# define ULONG_MAX 4294967295UL
# endif

5.5 Типы с плавающей точкой

Тип с плавающей точкой представляющий числа с плавающей точкой может быть представлено тремя типами:

ТипТип вещественного значенияРазмерность(в байтах)Допустимый диапазон
floatодинарной точностью43.4E Являются производной от фундаментальных типов, описанные нами ранее . К производным типам относиться: Являются производной от фундаментальных типов, описанные нами ранее . К производным типам относиться: +/- 38 (7 разрядов)
doubleдвойной точностью81.7E +/- 308 (15 разрядов)
long doubleрасширенной точностью83.4e-/+4932 (31 разряд)

5.5.2 Литерал

Для объектов содержащие вещественные числа с одинарной точностью требуется добавлять суффикс fили F. А для объектов содержащие целочисленные значения расширенной точности L или l. Так же для целочисленных чисел без знака добавляется суффикс U или u.

5.6 Размерность арифметических типов

К Арифметическими типами относятся: логические, символьные, целые, типы с плавающей точкой.

Арифметические типы образуют объекты с некоторым диапазоном значений и размерностью. Диапазон значений задается максимальными и минимальными экстремумами, а размерность количество байт памяти, которое будет выделено при создании объекта.

ТипЧисловое значениеРазмерность(в байтах)
booltrue = 1, false = 01
signed char-128...1271
unsigned char0..2551
signed short int-32 768...32 7672
unsigned short int0 ... 655352
signed long int-2 147 483 648 ... 2 147 483 6474
unsigned long int0... 4294 967 2954
float3.4e-38...3.4e+384
double1.7e-308...1.7e+3088
long double3.4e-4932...3.4e+493210

5.7. Интегральное продвижение типов

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

Таким образом, неявные преобразования, которые не изменяют значений целого, принято называть интегральным продвижением. Такое продвижение так же используется во время операций с объектами арифметических типов, когда нужно из объектов из целых типов bool, char или short создать объекты с более крупными, такими как int или long.

5.8. Преобразование знаковое в без знаковое

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

6. Тип void

Тип void не может создавать объекты O. А может быть только частью сложного типа, например как указатель на функцию.

Код:

typedef void* (fptr_t*) (int);
     . . .
int f(void * buf)
{
     int* value = (int*)buf;
     return *value;
}

Давайте рассмотрим некоторые сообщения компилятора об ошибках связанные с использованием типа void.

Сообщение компилятора:

"const from 'void*' to 'char' loses precision"

Объяснение:

Преобразование типов 'void*' к 'char' утрачивает верность. Т.е. такое преобразование не может быть выполнено. Нельзя преобразовывать 'void*', который является lvalue к переменной типа 'char'.

Код:

void f ( void* ptr)
{
     char value = (char)ptr;
}

Сообщение компилятора:

"invalid type argument оf 'unary*' "

Код:

void f ( void* ptr)
{
     int value = *(int)ptr;
}

Сообщение компилятора:

"__FILE__:__LINE__: error: «‘void*’ is not a pointer-to-object type"

Объяснение:

"Сложный тип 'void*' не является типом указатель на объект"

Код:

void f ( void* ptr)
{
     int value = (int*)ptr;
}

7. Производные типы

Являются производной от фундаментальных типов, описанные нами ранее . К производным типам относиться:

  • массивы объектов данного типа;
  • указатели на объекты данного типа;
  • ссылки на объект данного типа;
  • константы, являющиеся значениями данного типа;
  • структуры, объединяющие объекты любых типов;
  • функции возвращающие или получающие объекты данного типа.

7.2 Массивы данного типа

Набор элементов одного типа является массивом, исключая списки(enum) и объединения(union). Нумерация в массиве начинается с нуля по size-1. Обозначение массива:

T O[size], где size – размер массива.

Элементы массива O[0],O[1], O[2], ... ,O[size-1], где каждый объект самостоятельный объект O.

7.2.2 Многомерные массивы

Многомерные массивы описывается, как массив, состоящий из m элементов производного типа: T' = T[size], где T[size] – одномерный массив.

Запись T' O[m] = T[m][size] O, где m – количество одномерных массивов, которые содержит объект O.

7.2.3 Инициализация

7.2.3.1 Для одномерных массивов

Пусть имеется массив T O[size], где T = int, а size = 8, array – имя объекта O:

int array [8] = { 1,2,3,4 };

Первым четырем элементам будет присвоены значения: 1,2,3,4 – а последующим четырем элементам значение нуль. Это обнуление производится всегда для не про инициализированных элементов одномерного массива.

7.2.3.2 Для многомерных массивов

Пусть имеется массив T O[m][size], где T= int, а m = 2, size = 8, array – имя объекта O:

int array [2][8] = { {1,2,3,4} };

Первый массив объектов array[0], состоящий из 8-ми однородных объектов типа int будет про инициализирован, как это было бы сделано для однородного массива, который рассматривался ранее.

Второй массив объектов array[1] состоящий из 8-ми однородных объектов типа int будет про инициализирован нулями. Хотя была бы правильнее такая запись

int array [2][8] = { {1,2,3,4},{ 0 } }; /br>

7.2.3.3 Инициализация пустого массива разных типов

int empties [8] = { 0 }; unsigned int empties [8] = { 0u }; long int empties [8] = { 0L }; float empties [8] = { 0f }; double empties [8] = { 0.0 }; long double empties [8] = { 0.0L };

7.2.4 Размер массива

Размер одного элемента массива T O[n] будет равна:

sizeof(O[i]) = sizeof(T);

тогда размер всего массива будет равна

sizeof(O) = n*sizeof(T);

где n – число объектов массива; i – любой из n однородных объектов массива.

7.3 Указатели

Указателем является lvalue имеет постфиксный оператор '*' после объявление типа T. Объявление указателя производится следующим образом:

T* p; где p – указатель на объект произвольного типа.

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

Для присвоение адреса объекта того же типа T, что и указателя, следует пользоваться префиксным или унарным '&', т.е.

T* p = &O;

Для присвоение адреса объекта другого типа, отличного от указателя, рекомендуется пользоваться преобразованием типа:

T0 O;

T1* p= (T1*)&O;

Для двойного указателя T** присвоение адреса одинарного указателя производится по тому же правилу, как адрес объекта одинарному указателю.

T0* op;

T0** dp = &op;

7.2 Операции с указателями

Существуют три основных операторов:

  • &' - присвоения адреса;
  • '*' - разыменовывания;
  • '=' - присвоения.

Оператор '*' называется оператором разыменования. Он производит получение значения по адресу на который ссылается указатель T*. Оператор разыменования является унарным(префиксным).

T* p;

T O = *p;

Для равнозначных типов существует оператор присвоение '=':

7.3.3 Строковый литерал

Строковым литералов называется последовательность символов, заключенных в двойные кавычки. На его адрес указывает lvalue, ссылающиеся на адрес однородного массива объектов, к которым относятся символы последовательности.

Пример. Инициализации строкового литерала( lvalue имеет тип int*).

     . . .
void f()
{
int* chs = «It's first my of string literal»;
cout <<__FUNSTION__<<'':''< }
     . . .

Создание такого lvalue с типом 'int*' является ошибкой, потому что для строкового литерала тип lvalue должен быть const char*.

Сообщение компилятора:

__FILE__:__LINE__: error: cannot convert ‘const char*’ to ‘int*’ in initialization

Объяснение:

При инициализации невозможно преобразовать тип const char* к int*

Код:

см. пример ниже «Инициализации строкового литерал»

Объявляем lvalue, как требует от нас следующее правило: lvalue строкового литерала должен быть всегда тип const char*.

Пример. Инициализации строкового литерал lvalue имеет тип const char*.

     . . .
void f ()
{
int* chs = «It's first my of string literal»;
cout << __FUNSTION__<<'':''< }
     . . .

При вызове функции f() на стандартное устройство ввода/вывода будет выведено:

f:it's 1st my of characters literal

lvalue является указателем типа 'const char*' на постоянный объект, в данном случае на однородный массив объектов типа 'const char' (константы и указатели будут рассмотрены в ПП 4.3 «Указатели» настоящего документа). Поэтому выше сказанное, что lvalue должен быть указатель типа 'const char*' не со всем верно. Можно использовать указатель 'char*'. (см. пример ''Использование в качестве возвращаемое значения функции'');

Размер массива будет (n-1) * 1 байт, т.к. n-1 символом является невидимый символ 'конца строки', которым эквивалентен символьному литерал '\0'.

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

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

nbsp;    . . .
char* f()
{
char* literal = ''It\'s a string's literal'';
return literal;
}
nbsp;    . . .

Итак, строковый литерал является постоянным, т.е. неизменяемым объектом. Поэтому его можно использовать, при инициализации однородного массива, при условии что выполняется следующее условие:

m ≤ n,

где m – размерность массива, а n – размерность литерала. Для того, чтобы не задумываться сколько должено быть выделено памяти под однородный массив для инициализации его литералом, можно использовать неопределённый массив. В этом случае, всю головную боль за Вас возьмёт компилятор.

Пример. Инициализация однородного массива с помощью литерала.

nbsp;    . . .
void f()
{
char array[] = ''It\'s a string's literal'';
cout << __FUNCTION__ << '':'' << array << endl;
} nbsp;    . . .

При вызове функции f(), на стандартное устройство ввода/ввода будет выведено все та же строчка, что и в примере «Инициализации строкового литерал(где lvalue имеет тип 'const char*' ):

f:it's 1st my of characters literal

Но, в отличии от первого примера, где происходила инициализация литералом постоянного объекта, в этом случае мы инициализируем модифицируемый объект.

Пример. Модификация однородного массива, инициализируемого строковым литералом.

nbsp;    . . .
void f()
{
char array[] = ''It\'s a string's literal'';
cout << __FUNCTION__ << '':'' << array << endl;
char* ptr = array;
for ( ; *ptr ; ptr++ ) {
*ptr = 'A';
}
. . .

При вызове функции f() на стандартное устройство ввода/ввода вместо строки '' It's a string's literal'' будет выведено:

f:AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

7.3.4 указатели на массивы

7.3.4.1 Первый элемент массива

Имя массива всегда ассоциируются с его адресом, который указывает на его первый элемент. Таким образом,

T M[24];

Массив M – является адресом на первый элемент массива, состоящего из 24-х элементов типа T.

Следующий пример показывает, что адрес первого элемента и массива равнозначны.

nbsp;    . . .
void f ( ) {
int array [10] = { 0 };
cout.setf(std::ios_base::hex, std::ios_base::basefield);
cout << "array's address " << array << endl;
cout << "first element address " << &array[0] << endl;
}

Результат выполнения функции f():

array's address 0xbf8bdfd8
first element address 0xbf8bdfd8

Для вывода адреса в этом примере используется форматирование потока вывода объекта cout. Он управляет выводом на буфер потока, который ассоциируются с объектом stdout(Стандартное устройство вывода), декларируемое в <cstdio>. По умолчанию, потоки стандартов C и C++ являются синхронизируемыми.

7.3.4.2 Операция присвоение адреса массива

При операции присвоения (=) происходит назначение адреса массива указателю. Допустим имеется массив из 14-ти символов, который при создании будет инициализирован.

nbsp;    . . .
char chs[14] = «Hello World!»; char* p = chs; nbsp;    . . .

Операция присвоение адреса указателю можно так же назвать операцией преобразования типов, потому что тип T[] преобразуется к T*.

Следующий пример иллюстрирует как тип T[] преобразуется к T*.

     . . .
void f ( ) {
      char hello[] = "Hello world!";
      char* ptr = hello;
      cout << "Characters message(array type):"<< hello << << endl;
      cout << "Characters message(ponter type)" << ptr << endl;
     . . .
}

Результат выполнения функции f():

Characters message(array type):Hello world!
Characters message(pointer type):Hello world!

7.3.4.3 Вывод адреса указателя, массива

Вывод адреса указателя, массива на стандартное устройства ввода/вывода производится cout из стандартной библиотеки C++.

Следующий пример иллюстрирует вывод адреса массива и указателя с помощью преобразования типов.

     . . .
void f ( ) {
      typedef unsigned long int* paddr_t;
      char hello[] = "Hello world!";
      paddr_t ptr = (paddr_t)hello;
      cout << "Characters message(array type):"<< hello << endl;
      cout << "Characters message(pointer type):" << ptr << endl; }
     . . .

Результат выполнения:

Characters message(array type):Hello world!
Characters message(pointer type):0xbfbc7307

В четвертой строке определения функции f() производится явное преобразование типа char[] к unsigned long int*, который определен как пользовательский тип paddr_t в начале примера.

7.3.4.4 Доступ к элементам массива

Индексация или доступ к элементам массива осуществляется оператором []. Следующий пример иллюстрирует использование этого оператора:

void f() {       char hello[] = "Hello world!";       int index;       String mess = hello;       for ( index = 0; index < mess.length(); index++ ) {          cout << index << "\'s element: " << hello[index] << endl;      } }

В результате выполнения функции f() будет выведен каждый элемент массива.

0's element: H
1's element: e
2's element: l
3's element: l
4's element: o
5's element:
6's element: w
7's element: o
8's element: r
9's element: l
10's element: d
11's element: !

Второй способ доступа к элементам массива — по указателю. Для этого используется оператор разыменования . Индексация производится с помощью операторов +, и перегруженных операторов ++, −−.

Следующий пример иллюстрирует такой способ доступа к элементам массива.

void f() {
      typedef unsigned long int* paddr_t;
      char hello[] = "Hello world!";
      char* ptr = hello;
      char* first = hello;

      cout.setf(std::ios_base::dec,std::ios_base::basefield);

      while ( *ptr ) {
         cout << ptr - first << "\'s element:" << *ptr << endl;
         ptr++;
      }
}

Результат выполнения функции f() будет таким.

0's element:H
1's element:e
2's element:l
3's element:l
4's element:o
5's element:
6's element:w
7's element:o
8's element:r
9's element:l
10's element:d
11's element:!

7.3.5 указатели и константы

Префиксное помещение const перед типом T* не делает указатель константой.

const T* P;

Такая форма записи декларирует, что этот указатель содержит адрес константного объекта.

Для объявление константного указателя необходимо сделать постфиксное помещение const вместе с типом T*.

const T* const P;

Константный указатель P содержит адрес на константный объект.

Таким образом, существуют следующие типы указателей содержащие const:

const T* const P;// Константный указатель на объект типа T
T*    const   P; // Указатель на константный объект
const   T*   P; // Указатель на константный объект

Сообщение компилятора:

__FILE__:__LINE__: error: assignment of read_only location

Объяснение:

Попытка записи в область памяти доступной только для чтения

Код:

void f(){
   const char* hello = ''Неllo world!'';
   *hello = 'c';
}

Сообщение компилятора:

__FILE__:__LINE__: error: invalid conversion from 'const T* const' to 'T*'

Объяснение:

Нельзя присваивать адрес указателя на константный объект константному указателю. В данном случае, p2 является константным указателем, а p1 указателем на константный объект.

Код:

void f() {
    const char* p1 = "pppp", p3;
    const char* const p2 = p1;
    p3 = p2;
}

Сообщение компилятора:

__FILE__:__LINE__: error: uninitialized const ‘p3’

Объяснение:

константный указатель p3 – не был проинициализирован.

Код:

см. предыдущий пример.

7.4 Ссылки

Ссылка это тип, который указывает на объект, которому реально выделена память. Т.к. как понятие переменная в С++ отсутствует, то инициализатором ссылки s является lvalue или объект адрес которого можно получить.

T& s = O;

где s – ссылка.

В случае, если ссылкой является константный объект, то инициализатор для const T& не обязан быть lvalue.

const T& s = (const)C;

где s – ccылка, С – константный объект.

В таких случаях:

  • производится неявное приведение к типу T;
  • результирующее значение помещается во временную переменную того же тип, что и ссылка;
  • временная переменная используется как значение инициализатора.

Сообщение компилятора:

__FILE__:__LINE__: error: invalid initialization of reference of type 'long int &' from expression of type 'int'

Объяснение:

Неправильная инициализация ссылки типа ''int &' от выражения типа 'int'. Т.о. тип ссылки и тип объекта должен быть равнозначным.

Неправильная инициализация ссылки типа ''int &' от выражения типа 'int'. Т.о. тип ссылки и тип объекта должен быть равнозначным.

Код:

void f() {
    long int p = 123;
    int & s = p;
}

Отсюда, если имеется O размерности Т, то и ссылка должна иметь тип такой же размерности.

Т& s = O: To == T&s

7.4.2 Временные переменные

Временная переменная существует до конца области видимости, где она была объявлена.

T t = T(n);

где t – временная переменная, n – значение такой переменной.

Для ссылок будут верными следующие выражения:

T t = T(n);
const T& s = t;

При использовании такого инициализатора создается временная переменная с присвоением значения n, которое используется как инициализатор.

В отличии от lvalue, временная переменная может иметь тип большей размерности чем ссылка. И обратно, может иметь тип меньшей размерности. А при использовании типов не равной размерности происходит явное преобразование типов.

7.5 Использование спецификатора typedef

Cпецификатор typedef не создает новых типов в памяти, а присваивает идентификатор синтаксически эквивалентный ключевому слову спецификатора типа T. Поэтому, при использование данного спецификатора нельзя говорить о создание новых типов, а лишь о возможности присваивания им синонимов (P_t) существующим типам используемого стандарта C/C++.

typedef  T  P_t;

Возможность создания P_t от типа T используется различными библиотеками системного и прикладного программного обеспечения для задания базового набора, применяемых типов используемого стандарта C/C++. Одним из таких примеров является библиотека Gtk+, являющейся мультиплатформенным инструментарием для создания графических пользовательских интерфейсов. В ней задается базовый набор типов языка Си, призванный облегчить программисту жизнь при их использовании и дальнейшей портируемости.

Библиография

  1. Const Correctness in C++
  2. ISBN 5-7989-0223-4, 5-7940-0064-3, 0-201-70073-5 Бьерн Страуструп. Язык прораммирования С++. Специальное издание 3-е издание.
  3. The typeid operator (C++ only)
  4. Data Type Ranges
  5. Преобразование 32-биного приложения в 64-битное: что нужно учитывать
  6. Беззнаковая арифметика
  7. Объявление typedef

 

Вернуться в Доки-Токи


Copyright © 2010 rjaan as Andrey Rjavskov(Rzhavskov) <rjaan@yandex.ru> <arjavskov@gmail.com>