Что больше long long c
Перейти к содержимому

Что больше long long c

Что больше long long c

int _tmain(int argc, _TCHAR* argv[])
unsigned __int64 A = 18446744073709551000;
unsigned __int64 B = 200;
unsigned __int64 C=A+B;
printf(«%i \n»,C);
>
для начала необходимо просто добиться правильного сложения
после выполнения этого кода результат сложения -416. подскажите в чем проблема.

Регистрация: 28.01.2009
Сообщений: 20,999
unsigned __int64=unsigned long long.

Хорошо поставленный вопрос это уже половина ответа. | Каков вопрос, таков ответ.
Программа делает то что написал программист, а не то что он хотел.
Функции/утилиты ждут в параметрах то что им надо, а не то что вы хотите.

Пепел Феникса
Посмотреть профиль
Найти ещё сообщения от Пепел Феникса

Регистрация: 22.12.2010
Сообщений: 5
#include «stdafx.h»
#include
#include
#include
#include
#include

int _tmain(int argc, _TCHAR* argv[])
unsigned long long A = 18446744073709551000;
unsigned long long B = 200;
unsigned long long C=A+B;
printf(«%i \n»,C);
getch();
>

эффект тотже.
-416 получается.
какие идеи?

СтарожилДжуниор
Регистрация: 19.07.2009
Сообщений: 3,336
складывай массивы в столбик.
либо используй либу gmp

I invented the term Object-Oriented, and I can tell you I did not have C++ in mind. (c)Alan Kay

My other car is cdr.

Q: Whats the object-oriented way to become wealthy?
A: Inheritance

Что больше long long c

Каждая переменная имеет определенный тип. И этот тип определяет, какие значения может иметь переменная, какие операции с ней можно производить и сколько байт в памяти она будет занимать. В языке C++ определены следующие базовые типы данных: логический тип bool , целочисленные типы, типа чисел с плавающей точкой, символьные типы. Рассмотрим эти группы по отдельности.

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

Логический тип bool может хранить одно из двух значений: true (истинно, верно) и false (неверно, ложно). Например, определим пару переменных данного типа и выведем их значения на консоль:

#include int main() < bool isAlive ; bool isDead ; std::cout

При выводе значения типа bool преобразуются в 1 (если true) и 0 (если false). Как правило, данный тип применяется преимущество в условных выражениях, которые будут далее рассмотрены.

Значение по умолчанию для переменных этого типа — false .

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

Целые числа в языке C++ представлены следующими типами:

  • signed char : представляет один символ. Занимает в памяти 1 байт (8 бит). Может хранить любой значение из диапазона от -128 до 127
  • unsigned char : представляет один символ. Занимает в памяти 1 байт (8 бит). Может хранить любой значение из диапазона от 0 до 255
  • char : представляет один символ в кодировке ASCII. Занимает в памяти 1 байт (8 бит). Может хранить любое значение из диапазона от -128 до 127, либо от 0 до 255 Несмотря на то, что данный тип представляет тот же диапазон значений, что и вышеописанный тип signed char , но они не эквивалентны. Тип char предназначен для хранения числового кода символа и в реальности может представлять как signed byte , так и unsigned byte в зависимости от конкретного компилятора.
  • short : представляет целое число в диапазоне от –32768 до 32767. Занимает в памяти 2 байта (16 бит). Данный тип также имеет псевдонимы short int , signed short int , signed short .
  • unsigned short : представляет целое число в диапазоне от 0 до 65535. Занимает в памяти 2 байта (16 бит). Данный тип также имеет синоним unsigned short int .
  • int : представляет целое число. В зависимости от архитектуры процессора может занимать 2 байта (16 бит) или 4 байта (32 бита). Диапазон предельных значений соответственно также может варьироваться от –32768 до 32767 (при 2 байтах) или от −2 147 483 648 до 2 147 483 647 (при 4 байтах). Но в любом случае размер должен быть больше или равен размеру типа short и меньше или равен размеру типа long Данный тип имеет псевдонимы signed int и signed .
  • unsigned int : представляет положительное целое число. В зависимости от архитектуры процессора может занимать 2 байта (16 бит) или 4 байта (32 бита), и из-за этого диапазон предельных значений может меняться: от 0 до 65535 (для 2 байт), либо от 0 до 4 294 967 295 (для 4 байт). Имеет псевдоним unsigned
  • long : в зависимости от архитектуры может занимать 4 или 8 байт и представляет целое число в диапазоне от −2 147 483 648 до 2 147 483 647 (при 4 байтах) или от −9 223 372 036 854 775 808 до +9 223 372 036 854 775 807 (при 8 байтах). Занимает в памяти 4 байта (32 бита) или. Имеет псевдонимы long int , signed long int и signed long
  • unsigned long : представляет целое число в диапазоне от 0 до 4 294 967 295. Занимает в памяти 4 байта (32 бита). Имеет синоним unsigned long int .
  • long long : представляет целое число в диапазоне от −9 223 372 036 854 775 808 до +9 223 372 036 854 775 807. Занимает в памяти 8 байт (64 бита). Имеет псевдонимы long long int , signed long long int и signed long long .
  • unsigned long long : представляет целое число в диапазоне от 0 до 18 446 744 073 709 551 615. Занимает в памяти, как правило, 8 байт (64 бита). Имеет псевдоним unsigned long long int .

Для представления чисел в С++ применятся целочисленные литералы со знаком или без, типа -10 или 10. Например, определим ряд переменных целочисленных типов и выведем их значения на консоль:

#include int main() < signed char num1< -64 >; unsigned char num2< 64 >; short num3< -88 >; unsigned short num4< 88 >; int num5< -1024 >; unsigned int num6< 1024 >; long num7< -2048 >; unsigned long num8< 2048 >; long long num9< -4096 >; unsigned long long num10< 4096 >; std::cout u или U. Литералы типов long и long long имеют суффиксы L/l и LL/ll соответственно:

#include int main() < unsigned int num6< 1024U >; // U - unsigned int long num7< -2048L >; // L - long unsigned long num8< 2048UL >; // UL - unsigned long long long num9< -4096LL >; // LL - long long unsigned long long num10< 4096ULL >;// ULL - unsigned long long std::cout #include int main() < int num< 1'234'567'890 >; std::cout 
Различные системы исчисления

По умолчанию все стандартные целочисленные литералы представляют числа в привычной нам десятичной системе. Однако C++ также позволяет использовать и числа в других системах исчисления.

Чтобы указать, что число - шестнадцатеричное, перед числом указывается префикс 0x или 0X . Например:

int num1< 0x1A>; // 26 - в десятичной int num2< 0xFF >; // 255 - в десятичной int num3< 0xFFFFFF >; //16777215 - в десятичной

Чтобы указать, что число - восьмеричное, перед числом указывается ноль 0 . Например:

int num1< 034>; // 26 - в десятичной int num2< 0377 >; // 255 - в десятичной

Бинарные литералы предваряются префиксом 0b или 0B :

int num1< 0b11010>; // 26 - в десятичной int num2< 0b11111111 >; // 255 - в десятичной

Все эти типы литералов также поддерживают суффиксы U/L/LL :

unsigned int num1< 0b11010U>; // 26 - в десятичной long num2< 0377L >; // 255 - в десятичной unsigned long num3< 0xFFFFFFULL >; //16777215 - в десятичной

Числа с плавающей точкой

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

Например, число 365 может быть записано в виде числа с плавающей точкой следующим образом:

3.650000E02

В качестве разделителя целой и дробной частей используется символ точки. Мантисса здесь имеет семь десятичных цифр - 3.650000 , показатель степени - две цифры 02 . Буква E означает экспоненту, после нее указывается показатель степени (степени десяти), на которую умножается часть 3.650000 (мантисса), чтобы получить требуемое значение. То есть, чтобы вернуться к обычному десятичному представлению, нужно выполнить следующую операцию:

3.650000 × 102 = 365

Другой пример - возьмем небольшое число:

-3.650000E-03

В данном случае мы имеем дело с числом –3.65 × 10 -3 , что равно –0.00365 . Здесь мы видим, что в зависимости от значения показателя степени десятичная точка "плавает". Собственно поэтому их и называют числами с плавающей точкой.

Однако хотя такая запись позволяет определить очень большой диапазон чисел, не все эти числа могут быть представлены с полной точностью; числа с плавающей запятой в целом являются приблизительными представления точного числа. Например, число 1254311179 выглядело бы так: 1.254311E09 . Однако если перейти к десятичной записи, то это будет 1254311000 . А это не то же самое, что и 1254311179 , поскольку мы потеряли три младших разряда.

В языке C++ есть три типа для представления чисел с плавающей точкой:

  • float : представляет вещественное число одинарной точности с плавающей точкой в диапазоне +/- 3.4E-38 до 3.4E+38. В памяти занимает 4 байта (32 бита)
  • double : представляет вещественное число двойной точности с плавающей точкой в диапазоне +/- 1.7E-308 до 1.7E+308. В памяти занимает 8 байт (64 бита)
  • long double : представляет вещественное число двойной точности с плавающей точкой не менее 8 байт (64 бит). В зависимости от размера занимаемой памяти может отличаться диапазон допустимых значений.

В своем внутреннем бинарном представлении каждое число с плавающей запятой состоит из одного бита знака, за которым следует фиксированное количество битов для показателя степени и набор битов для хранения мантиссы. В числах float 1 бит предназначен для хранения знака, 8 бит для экспоненты и 23 для мантиссы, что в сумме дает 32 бита. Мантисса позволяет определить точность числа в виде 7 десятичных знаков.

В числах double : 1 знаковый бит, 11 бит для экспоненты и 52 бит для мантиссы, то есть в сумме 64 бита. 52-разрядная мантисса позволяет определить точность до 16 десятичных знаков.

Для типа long double расклад зависит от конкретного компилятора и реализации этого типа данных. Большинство компиляторов предоставляют точность до 18 - 19 десятичных знаков (64-битная мантисса), в других же (как например, в Microsoft Visual C++) long double аналогичен типу double .

В C++ литералы чисел с плавающими точками представлены дробными числами, которые в качестве разделителя целой и дробной частей применяют точку:

double num ;

Даже если переменной присваивается целое число, чтобы показать, что мы присваиваем число с плавающей точкой, применяется точка:

double num1< 1 >; // 1 - целочисленный литерал double num2< 1. >; //1. - литерал числа с плавающей точкой

Так, здесь число 1. представляет литерал числа с плавающей точкой, и в принципе аналогичен 1.0 .

По умолчанию все такие числа с точкой расцениваются как числа типа double. Чтобы показать, что число представляет другой тип, для float применяется суффикс f / F , а для long double - l / L :

float num1< 10.56f >; // float long double num2< 10.56l >; // long double

В качестве альтернативы также можно применять экспоненциальную запись:

double num1< 5E3 >; // 5E3 = 5000.0 double num2< 2.5e-3 >; // 2.5e-3 = 0.0025

Размеры типов данных

При перечислении типов данных указывался размер, который он занимает в памяти. Но стандарт языка устанавливает лишь минимальные значения, которые должны быть. Например, для типов int и short минимальное значение - 16 бит, для типа long - 32 бита, для типа long double - 64 разряда. При этом размер типа long должен быть не меньше размера типа int, а размер типа int - не меньше размера типа short, а размер типа long double должен быть не меньше double . А разработчики компиляторов могут выбирать предельные размеры для типов самостоятельно, исходя из аппаратных возможностей компьютера.

К примеру, компилятор g++ Windows для long double использует 16 байт. А компилятор в Visual Studio, который также работает под Windows, и clang++ под Windows для long double используют 8 байт. То есть даже в рамках одной платформы разные компиляторы могут по разному подходить к размерам некоторых типов данных. Но в целом используются те размеры, которые указаны выше при описании типов данных.

Однако бывают ситуации, когда необходимо точно знать размер определенного типа. И для этого в С++ есть оператор sizeof() , который возвращает размер памяти в байтах, которую занимает переменная:

#include int main() < long double number ; std::cout 
sizeof(number) = 16

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

В C++ есть следующие символьные типы данных:

  • char : представляет один символ в кодировке ASCII. Занимает в памяти 1 байт (8 бит). Может хранить любое значение из диапазона от -128 до 127, либо от 0 до 255
  • wchar_t : представляет расширенный символ. На Windows занимает в памяти 2 байта (16 бит), на Linux - 4 байта (32 бита). Может хранить любой значение из диапазона от 0 до 65 535 (при 2 байтах), либо от 0 до 4 294 967 295 (для 4 байт)
  • char8_t : представляет один символ в кодировке Unicode. Занимает в памяти 1 байт. Может хранить любой значение из диапазона от 0 до 256
  • char16_t : представляет один символ в кодировке Unicode. Занимает в памяти 2 байта (16 бит). Может хранить любой значение из диапазона от 0 до 65 535
  • char32_t : представляет один символ в кодировке Unicode. Занимает в памяти 4 байта (32 бита). Может хранить любой значение из диапазона от 0 до 4 294 967 295
char

Переменная типа char хранит числовой код одного символа и занимает один байт. Стандарт языка С++ не определяет кодировку символов, которая будет использоваться для символов char, поэтому производители компиляторов могут выбирать любую кодировку, но обычно это ASCII.

В качестве значения переменная типа char может принимать один символ в одинарных кавычках, либо числовой код символа:

#include int main() < char a1 ; char a2 ; std::cout

В данном случае переменные a1 и a2 будут иметь одно и то же значение, так как 65 - это числовой код символа "A" в таблице ASCII. При выводе на консоль с помощью cout по умолчанию отображается символ.

Кроме того, в C++ можно использовать специальные управляющие последовательности, которые предваряются слешем и которые интерпретируются особым образом. Например, "\n" представляет перевод строки, а "\t" - табуляцию.

Однако ASCII обычно подходит для наборов символов языков, которые используют латиницу. Но если необходимо работать с символами для нескольких языков одновременно или с символами языков, отличных от английского, 256-символьных кодов может быть недостаточно. И в этом случае применяется Unicode .

Unicode (Юникод) — это стандарт, который определяет набор символов и их кодовых точек, а также несколько различных кодировок для этих кодовых точек. Наиболее часто используемые кодировки: UTF-8, UTF-16 и UTF-32. Разница между ними заключается в том, как представлена кодовая точка символа; числовое же значение кода для любого символа остается одним и тем же в любой из кодировок. Основные отличия:

  • UTF-8 представляет символ как последовательность переменной длины от одного до четырех байт. Набор символов ASCII появляется в UTF-8 как однобайтовые коды, которые имеют те же значения кодов, что и в ASCII. UTF-8 на сегодняшний день является самой популярной кодировкой Unicode.
  • UTF-16 представляет символы как одно или два 16-битных значения.
  • UTF-32 представляет все символы как 32-битные значения

В C++ есть четыре типа для хранения символов Unicode: wchar_t , char8_t , char16_t и char32_t ( char16_t и char32_t были добавлены в C+11, а char8_t - в C++20).

wchar_t

Тип wchar_t — это основной тип, предназначенный для наборов символов, размер которых выходит за пределы одного байта. Собственно отсюда и его название: wchar_t - wide (широкий) char. происходит от широкого символа, потому что этот символ «шире», чем обычный однобайтовый символ. Значения wchar_t определяются также как и символы char за тем исключением, что они предваряются символов "L":

wchar_t a1 ;

Также можно передать код символа

wchar_t a1 ;

Значение, заключенное в одинарные кавычки, представляет собой шестнадцатеричный код символа. Обратная косая черта указывает на начало управляющей последовательности, а x после обратной косой черты означает, что код шестнадцатеричный.

Стоит учитывать, что для вывода на консоль символов wchar_t следует использовать не std::cout , а поток std::wcout :

#include int main() < char h = 'H'; wchar_t i ; std::wcout

При этом поток std::wcout может работать как с char, так и с wchar_t. А поток std::cout для переменной wchar_t вместо символа будет выводить его числовой код.

Проблема с типом wchar_t заключается в том, что его размер сильно зависит от реализации и применяемой кодировки. Кодировка обычно соответствует предпочтительной кодировке целевой платформы. Так, для Windows wchar_t обычно имеет ширину 16 бит и кодируется с помощью UTF-16. Большинство других платформ устанавливают размер в 32 бита, а в качестве кодировки применяют UTF-32. С одной стороны, это позволяет больше соответствовать конкретной платформе. Но с другой стороны, затрудняет написание кода, переносимого на разные платформы. Поэтому в общем случае часто рекомендуется использовать типы char8_t , char16_t и char32_t . Значения этих типов предназначены для хранения символов в кодировке UTF-8, UTF-16 или UTF-32 соответственно, а их размеры одинаковы на всех распространенных платформах.

Для определения символов типов char8_t , char16_t и char32_t применяются соответственно префиксы u8, u и U:

char8_t c< u8'l' >; char16_t d< u'l' >; char32_t e< U'o' >;

Стоит отметить, что для вывода на консоль значений char8_t/char16_t/char32_t пока нет встроенных инструментов типа std:cout/std:wcout .

Спецификатор auto

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

auto number = 5; // number имеет тип int auto sum ; // sum имеет тип double auto distance ; // distance имеет тип unsigned long

На основании присвоенного значения компилятор выведет тип переменной. Неинициализированные переменные со спецификатором auto не допускаются:

C2017/Типы данных в C

Целочисленные типы данных используются для хранения целых чисел (тип char также используется для хранения ASCII-символов). Все размеры диапазонов представленных ниже типов данных минимальны и на отдельно взятой платформе могут быть больше.

Минимальный диапазон значений целых типов по стандарту определяется с [math]-(2^N-1)[/math] по [math]2^N-1[/math] , где [math]N[/math] — разрядность типа. Реализация компиляторов может расширять этот диапазон по своему усмотрению. Отметим, что такие ограничения позволяют использовать то или иное представление знаковых чисел:

  • дополнительный код (two’s complement) — для отрицательного числа код можно получить инвертированием его двоичного модуля и прибавлением к инверсии единицы
  • обратный код (ones’ complement) — двоичный код отрицательного целого числа состоит из одноразрядного кода знака (двоичной цифры 1), за которым следует ( [math]n−1[/math] )-разрядное двоичное число, представляющее собой инвертированное ( [math]n−1[/math] )-разрядное представление модуля числа
  • прямой код (sign and magnitude method) — знаковый бит и затем модуль числа без инвертирования.

Отдельное внимание стоит уделить типу char . Формально это отдельный тип, но фактически char эквивалентен либо signed char , либо unsigned char , в зависимости от компилятора.

Для того, чтобы избежать путаницы между размерами типов стандарт C99 ввел новые типы данных, описанные в файле stdint.h. Среди них такие типы как: intN_t , int_leastN_t , int_fastN_t , где N = 8, 16, 32 или 64. Приставка least- обозначает минимальный тип, способный вместить N бит, приставка fast- обозначает тип размером не менее 16 бит, работа с которым наиболее быстрая на данной платформе. Типы без приставок обозначают типы с фиксированном размером, равным N бит.

Типы с приставками least- и fast- можно считать заменой типам int , short , long , с той лишь разницей, что первые дают программисту выбрать между скоростью и размером.

Тип данных Размер Минимальный диапазон значений Первое появление
signed char минимум 8 бит от -127 (= -(2 8 -1)) до 127 K&R C
unsigned char минимум 8 бит от 0 до 255 (=2 8 -1) K&R C
char минимум 8 бит от -127 до 127 или от 0 до 255 в зависимости от компилятора K&R C
short int минимум 16 бит от -32,767 (= -(2 15 -1)) до 32,767 K&R C
unsigned short int минимум 16 бит от 0 до 65,535 (= 2 16 -1) K&R C
int минимум 16 бит от -32,767 до 32,767 K&R C
unsigned int минимум 16 бит от 0 до 65,535 (= 2 16 -1) K&R C
long int минимум 32 бита от -2,147,483,647 до 2,147,483,647 K&R C
unsigned long int минимум 32 бита от 0 до 4,294,967,295 (= 2 32 -1) K&R C
long long int минимум 64 бита от -9,223,372,036,854,775,807 до 9,223,372,036,854,775,807 C99
unsigned long long int минимум 64 бита от 0 до 18,446,744,073,709,551,615 (= 2 64 -1) C99
int8_t 8 бит от -127 до 127 C99
uint8_t 8 бит от 0 до 255 (=2 8 -1) C99
int16_t 16 бит от -32,767 до 32,767 C99
uint16_t 16 бит от 0 до 65,535 (= 2 16 -1) C99
int32_t 32 бита от -2,147,483,647 до 2,147,483,647 C99
uin32_t 32 бита от 0 до 4,294,967,295 (= 2 32 -1) C99
int64_t 64 бита от -9,223,372,036,854,775,807 до 9,223,372,036,854,775,807 C99
uint64_t 64 бита от 0 до 18,446,744,073,709,551,615 (= 2 64 -1) C99
Ошибки
#include int main() { unsigned int a = 1000; int b = -1; printf("%s is bigger\n", (a > b ? "a" : "b")); return 0; }

Memsize-типы

Для представления величин, связанных с памятью, в C есть typedef'ы size_t и ptrdiff_t. Размер определяется архитектурой процессора.

#include

size_t — беззнаковый тип для представления размера любого объекта (включая массив). Он способен хранить в себе размер максимального массива, который может быть теоретически выделен в рамках данной архитектуры.

Оператор sizeof возвращает результат типа size_t. Для size_t гарантируется, что он как минимум 16-битный.

Тип ptrdiff_t знаковый, используется для хранения разности указателей. Стандартом допускается вычисление разности только для указателей одного типа, для разных типов — зависит от реализации.

Модели данных

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

Примеры приведены в таблице.

Data-model.png

Вещественные типы

Стандартом гарантируется только, что sizeof(float)

На большинстве платформ применяются типы с плавающей точкой в соответствии со стандартом IEEE 754.

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

В языке C в стандарте C99 введён тип _Bool.

#include #include int main() { bool b = 123456; printf("%s\n", (b == 1) ? "true" : "false"); return 0; }

Массивы

Для каждого типа T, кроме void и типов функций, существует тип «массив из элементов N типа T». Массив - это коллекция значений одного типа, хранящихся последовательно в памяти. Массив размера N индексируется целым числом от 0 до N-1.

int cat[10] = {5,7,2}; // массив из 10 элементов, каждый типа int

Массивы могут быть инициализированы с помощью списка инициализации, но не могут быть присвоены друг к другу.

int a[10][8]; // массив из 10 элементов, каждый типа 'массив из 8 int элементов' float f[][32] = {{0},{4,5,6}};

В C99 добавлены динамические многомерные массивы:

double (*A)[n] = malloc(sizeof(double[n][n]));
#include #include #include void Fill(int n, int m, int a[][m]) { int x = 0; for (int i = 0; i  n; ++i) { for (int j = 0; j  m; ++j) { a[i][j] = ++x; } } } void Print(int n, int m, int a[][m]) { for (int i = 0; i  n; ++i) { for (int j = 0; j  m; ++j) { printf("%3d", a[i][j]); } putchar('\n'); } } int main() { int n, m; scanf("%d %d", &n, &m); int (*a)[m] = malloc(sizeof(int[n][m])); Fill(n, m, a); Print(n, m, a); free(a); int b[n][m]; Fill(n, m, b); Print(n, m, b); return 0; }

Указатели

Для любого типа T существует тип «указатель на T».

Переменные могут быть объявлены как указатели на значения различных типов с помощью символа * . Для того чтобы определить тип переменной как указатель, нужно предварить её имя звёздочкой.

char letterC = 'C'; char *letter = &letterC; //взятие адреса переменной letterC и присваивание в переменную letter printf("This code is written in %c.", *letter); //"This code is written in C."

Поскольку указатель — тоже тип переменной, правило «для любого типа T» выполняется и для них: можно объявлять указатели на указатели. К примеру, можно пользоваться int*** :

int w = 100; int *x = &w; int **y = &x; int ***z = &y; printf("w contains %d.", ***z); //"w contains 100."

Существуют также указатели на массивы и на функции. Указатели на массивы имеют следующий синтаксис:

char *pc[10]; // массив из 10 указателей на char char (*pa)[10]; // указатель на массив из 10 переменных типа char

pc — массив указателей, занимающий 10 * sizeof(char*) байт (на распространённых платформах — обычно 40 или 80 байт), а pa — это один указатель; занимает он обычно 4 или 8 байт, однако позволяет обращаться к массиву, занимающему 10 байт: sizeof(pa) == sizeof(int*) , но sizeof(*pa) == 10 * sizeof(char) . Указатели на массивы отличаются от указателей на первый элемент арифметикой. Например, если указатели pa указывает на адрес 2000, то указатель pa+1 будет указывать на адрес 2010.

char (*pa)[10]; char array[10] = "Wikipedia"; pa = &array; printf("An example for %s.\n", *pa); //"An example for Wikipedia." printf("%c %c %c", (*pa)[1], (*pa)[3], (*pa)[7]); //"i i i"

Структуры

Композитный тип данных, инкапсулирующий без сокрытия набор значений различных типов.

При инициализации элементов структуры надо иметь в виду следующий момент:

If there are fewer initializers in a brace-enclosed list than there are elements or members of an aggregate, or fewer characters in a string literal used to initialize an array of known size than there are elements in the array, the remainder of the aggregate shall be initialized implicitly the same as objects that have static storage duration.

Важное отличие между С и C++.

struct Point { int x; int y; };

В C++ можно писать

Point pt;

В C нужно писать

struct Point pt;

Так сделано специально. Названия структур находятся в отдельном пространстве имён. Их всего четыре вида:

  • названия меток (для goto);
  • теги (названия структур, объединений, перечислений);
  • члены структур и объединений;
  • все прочие идентификаторы.

Это позволяет, например, назвать переменную так же, как называется структура.

Или же можно сделать typedef:

typedef struct { int x; int y; } Point;

Доступ к элементам структуры осуществляется с помощью оператора .. Для обращения к полям структуры по указателю существует оператор «стрелочка» ->, синонимичный предыдущей записи: (*p).x — то же самое, что и p->x.

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

Структуры не всегда занимают число байт, равное сумме байт их элементов. Компилятор обычно выравнивает элементы. The Lost Art of C Structure Packing

Адрес памяти первого поля структуры равен адресу самой структуры.

Объединения

Доступ к одним и тем же данным разными способами:

#include struct Point { union { struct XYZ { float x; float y; float z; }; float coords[3]; }; }; int main() { struct Point pt = {.x = 1.f, .y = 2.f, .z = 3.f}; printf("%zu\n", sizeof(pt)); for (int i = 0; i  3; ++i) { printf("%f\n", pt.coords[i]); } return 0; }

Т. н. type punning (каламбур типизации)

#include #include float ChangeSign(float x) { union { float floatValue; uint32_t intValue; } u; u.floatValue = x; u.intValue ^= (1U  31); return u.floatValue; } int main() { printf("%f\n", ChangeSign(1.25f)); return 0; }

Стандартом C99 это разрешается (в отличие от приведения указателей разных типов).

If the member used to read the contents of a union object is not the same as the member last used to store a value in the object, the appropriate part of the object representation of the value is reinterpreted as an object representation in the new type as described in 6.2.6 (a process sometimes called ‘‘type punning’’). This might be a trap representation.

Битовые поля

Перечисления

enum Color { RED, GREEN, BLUE, }; enum Shape { SQUARE, TRIANGLE, }; int main() { enum Color color = SQUARE; // even no warning }

Что больше long long? я хочу узнать сколько 6 в 100 и написал программу но ответ в хз раз больше long long! помогите!

Для работы с длинными целыми и числами с плавающей запятой произвольной точности существует много библиотек, к примеру, https://ru.wikipedia.org/wiki/GNU_Multi-Precision_Library, некоторые языки программирования поддерживают такие числа "из коробки".

Ну и как было сказано в ответе выше, можно самому реализовать работу с "длинными целыми" -- алгоритмы и структуры данных для этого описаны еще при царе горохе.

Aнто)(@Ученик (212) 7 лет назад

ra Высший разум (113230) И че теперь? Обосраться и не жить? Если и дальше будешь задавать вопросы на ответах. мыло. ру, вместо того, чтобы самому порыться в гугле, попытаться разобраться со своим вопросом, то так нубом и останешься.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *