Размеры встроенных типов данных C/C++ выбраны компанией Analog Devices таким образом, чтобы обычные программы C/C++ выполнялись с подходящими под аппаратуру типами данных (hardware-native data types), что повышает быстродействие кода [2]. Рабочее окружение выполнения кода (C/C++ run-time environment) использует встроенные типы данных C/C++ и форматы данных, показанные в таблице 1-44 и на рисунках 1-4 и 1-5.
Таблица 1-44. Форматы хранения данных и размеры типов данных.
Тип |
Количество бит, знак |
Формат представления |
sizeof вернет |
bool
|
8 бит, signed |
8 бит, дополнение до 2 |
1 |
char
|
8 бит, signed |
8 бит, дополнение до 2 |
1 |
unsigned char
|
8 бит, unsigned |
8 бит, число без знака |
1 |
short
|
16 бит, signed |
16 бит, дополнение до 2 |
2 |
unsigned short
|
16 бит, unsigned |
16 бит, число без знака |
2 |
int
|
32 бита, signed |
32 бита, дополнение до 2 |
4 |
unsigned int
|
32 бита, unsigned |
32 бита, число без знака |
4 |
long
|
32 бита, signed |
32 бита, дополнение до 2 |
4 |
unsigned long
|
32 бита, unsigned |
32 бита, число без знака |
4 |
long long
|
64 бита, signed |
64 бита, дополнение до 2 |
8 |
unsigned long long
|
64 бита, signed |
64 бита, число без знака |
8 |
указатель
|
32 бита |
32 бита, дополнение до 2 |
4 |
указатель на функцию
|
32 бита |
32 бита, дополнение до 2 |
4 |
double
|
32 бита |
32 бита, IEEE одинарной точности |
4 |
float
|
32 бита |
32 бита, одинарной точности |
4 |
double
|
64 бита |
64 бита, IEEE двойной точности |
8 |
long double
|
64 бита |
64 бита, IEEE |
8 |
fract
|
16 бит, signed |
дробное число формата s1.15 |
2 |
long fract
|
32 бита, signed |
дробное число формата s1.31 |
4 |
unsigned short fract
|
16 бит, unsigned |
дробное число формата 0.16 |
2 |
unsigned fract
|
16 бит, unsigned |
дробное число формата 0.16 |
2 |
unsigned long fract
|
32 бита, unsigned |
дробное число формата 0.32 |
4 |
short accum
|
40 бит, signed |
число с фиксированной точкой формата s9.31 |
8 |
accum
|
40 бит, signed |
число с фиксированной точкой формата s9.31 |
8 |
long accum
|
40 бит, signed |
число с фиксированной точкой формата s9.31 |
8 |
unsigned short accum
|
40 бит, unsigned |
число с фиксированной точкой формата 8.32 |
8 |
unsigned accum
|
40 бит, unsigned |
число с фиксированной точкой формата 8.32 |
8 |
unsigned long accum
|
40 бит, unsigned |
число с фиксированной точкой формата 8.32 |
8 |
fract16
|
16 бит, signed |
дробное число формата 1.15 |
2 |
fract32
|
32 бита, signed |
дробное число формата 1.31 |
4 |
Замечание: типы с плавающей запятой (floating-point) и 64-битные типы данных используются на основе программной эмуляции, поэтому они будут обрабатываться медленнее, чем традиционные, поддерживаемые аппаратно типы данных. Эмулированными являются типы float, double, long double, long long и unsigned long long.
Предупреждение: традиционные типы с фиксированной запятой fract и accum недоступны в C++. На языке C они доступны только когда подключен заголовочный файл stdfix.h.
Внимание: типы fract16 и fract32 не являются в действительности встроенными типами данных - они определены через typedef как short и long соответственно. На языке C для выполнения базовой арифметики нужно использовать встроенные функции (см. далее "Дробное значение встроенных функций C++", а также [4]). Вы не можете просто так выполнить умножение fract16 * fract16 и получить правильный результат. На C++ для fract-данных классы fract и shortfract определяют базовые арифметические операторы, в то время как на языке C традиционные типы с фиксированной запятой fract и accum предоставляют более натуральную альтернативу для fract16 и fract32. Таким образом, типы fract16 и fract32 имеет смысл применять только для использования с готовыми, оптимизированными (написанными на ассемблере) библиотеками [2].
[Дробное значение встроенных функций C++]
Компилятор поддерживает два класса C++ для дробных чисел. Класс fract использует тип fract32 языка C для хранения дробного значения, в то время как класс shortfract использует тип fract16 языка C для хранения дробного значения.
Экземпляры классов shortfract и fract инициализированные с суффиксом "r", предоставлены для работы с диапазоном чисел [-1,1). Класс fract реализован компилятором как представление внутреннего типа fract. Пример:
#include < fract>
int main ()
{
fract X = 0.5r;
}
Экземпляры класса shortfract могут быть инициализированы с использованием значений "r" таким же способом, однако они не представлены компилятором как внутренний тип. Вместо этого компилятор генерирует временный fract, который инициализируется с использованием значения "r". Значение класса fract затем копируется в класс shortfract с использованием неявного копирования, и временный fract уничтожается.
Классы fract и shortfract содержат подпрограммы, которые позволяют выполнять базовые арифметические операции и перемещения данных в другие типы данных и из других типов данных. В примере ниже показано использование класса shortfract с операторами * и +.
Математические подпрограммы для сложения, вычитания, деления и умножения для обоих классов fract и shortfract работают с использованием подпрограмм, определенных ETSI для дробных типов C (fract16 и fract32). Подключение заголовочных файлов fract и shortfract неявно определяет макрос ETSI_SOURCE как 1. Это требует использования подпрограмм ETSI, которые определены в libetsi.h, и находятся в библиотеках libetsi53*.dlb.
#include < shortfract>
#include < stdio.h>
#define N 20
shortfract x[N] = {
.5r,.5r,.5r,.5r,.5r,
.5r,.5r,.5r,.5r,.5r,
.5r,.5r,.5r,.5r,.5r,
.5r,.5r,.5r,.5r,.5r};
shortfract y[N] = {
0,.1r,.2r,.3r,.4r,
.5r,.6r,.7r,.8r,.9r,
.10r,.1r,.2r,.3r,.4r,
.5r,.6r,.7r,.8r,.9r};
shortfract fdot(int n, shortfract *x, shortfract *y)
{
int j;
shortfract s;
s = 0;
for (j=0; j < n; j++)
{
s += x[j] * y[j];
}
return s;
}
int main(void)
{
fdot(N,x,y);
}
[Формат IEEE для чисел с плавающей запятой]
По умолчанию компилятор Blackfin предоставляет эмуляцию плавающей точки с использованием форматов IEEE одиночной и двойной точности. Одиночная точность (Single-precision IEEE format, см. рис. 1-4) представлена 32-разрядным значением, где 23 бита используются для мантиссы, 8 бит для экспоненты, и 1 бит для знака. Этот формат используется для типа данных float, а также по умолчанию для типа данных double, и когда используется ключ командной строки компилятора -double-size-32.
Рис. 1-4. Обычный формат хранения чисел float и double (одинарная точность).
На рис. 1-4 одно слово (32-бита) данных применено для выражения:
Здесь:
• Sign - представляет бит знака (sign). • Mantissa - представляет дробную часть мантиссы, 23 бита (в этом формате подразумевается "1."). • Exponent - представляет 8-битную экспоненту.
Формат двойной точности (Double-precision IEEE format, см. рис. 1-5) представлен 64-разрядным значением, с 52 битами для мантиссы, 11 битами для экспоненты и 1 битом для знака. Этот формат используется для типа данных long double, и для типа данных double, когда используется ключ командной строки компилятора -double-size-64.
Рис. 1-5. Формат двойной точности IEEE.
На рис. 1-5 двойное слово (64-бита) данных применено для выражения:
Здесь:
• Sign - представляет бит знака (sign). • Mantissa - представляет дробную часть мантиссы, 52 бита (в этом формате подразумевается "1."). • Exponent - представляет 11-битную экспоненту.
[Ссылки]
1. VisualDSP: использование типов с фиксированной точкой. 2. Библиотека Blackfin DSP Run-Time, общее описание. 3. Поддержка традиционных типов с фиксированной точкой в VisualDSP++. 4. Встроенные функции компиляторов Blackfin VisualDSP и GCC. |