// variables_primitive_types.cc
// 基本内置类型
// 变量
// const限定符
// 处理类型
// 自定义数据类型
#include <iostream>
// 头文件,用于于编译处理。iostream标准库,头文件替换此条命令。
using std::endl; using std::cin; using std::cout;
#include "Sales_item.h"
int cifang();
int reused = 42;
int main()
{
// ========基本内置类型字符,整型,浮点数,布尔========
short short_integer = 10; // 短整型 2 字节
int integer = 20; // 整型: 长度大于等于短整型 4 字节
long int l_integer = 30; // 长整型: 长度大于等于整型 8 字节
long long ll_integer = 40; // 长长整形:长度大于等于长整型 8 字节
/*
* 大多数计算机以2的整数次幂个比特作为块来处理内存,
* 可寻址的最小内存块称为“字节byte”,
* 存储的基本单元称为“字word”,它通常由几个字节组成。
* 大多数机器的字节由8 bit 比特构成,
* 字则由32或64 bit 构成,也就是4或8字节。
*/
cout << "short int的大小:" << sizeof(short_integer) << "字节" << endl;
cout << " int的大小:" << sizeof(int) << "字节" << endl;
cout << " long int的大小:" << sizeof(l_integer) << "字节" << endl;
cout << " ll int的大小:" << sizeof(long long) << "字节" << endl;
cout << "===========================================================================" << endl;
char char_character = 'a'; // 字符 16位
wchar_t wchar_t_character = 'b'; // 宽字符 32位
char16_t char16_t_character = 'c'; // Unicode字符 16位
char32_t char32_t_character = 's'; // Unicode字符 32位
cout << "char 的大小: " << sizeof(char) << "字节" << endl; // 2
cout << "wchar_t 的大小: " << sizeof(wchar_t) << "字节" << endl; // 4
cout << "char16_t 的大小:" << sizeof(char16_t) << "字节" << endl; // 2
cout << "char32_t 的大小:" << sizeof(char32_t) << "字节" << endl; // 4
cout << "===========================================================================" << endl;
float float_decimals = 1.0; // 单精度浮点数 6位有效数字
double double_decimals = 2.0; // 双精度浮点数 10位有效数字
long double longd_decimals = 3.0; // 扩展精度浮点数 10位有效数字
cout << "float 的大小: " << sizeof(float) << "字节" << endl; // 4
cout << "double 的大小: " << sizeof(double) << "字节" << endl; // 8
cout << "long double 的大小:" << sizeof(long double) << "字节" << endl; // 16
cout << "===========================================================================" << endl;
bool boole = true;
/*
* bool 的取值是true或者false
* 0是false,非0是true
*/
cout << "bool 的大小:" << sizeof(bool) << "字节,boole: " << boole << endl;
cout << "===========================================================================" << endl;
/*
* 带符号类型和无符号类型:
* 除去bool和扩展字符型之外,其他整型可以划分为signed带符号的和unsigned无符号两种。
* 带符号可以表示正数,负数,0,
* 无符号表示大于等于0的数。
*/
unsigned char us_character = 25;
signed char sn_character = -20;
// 由于char在机器中不一定是无符号的还是带符号的,所以声明char时需清楚声明是带符号的
// 的还是无符号的。
cout << "us_character: " << us_character << " "
<< "sn_character: " << sn_character << endl;
cout << "unsigned char size: " << sizeof(unsigned char) << endl;
cout << "signed char size: " << sizeof(signed char) << endl;
cout << "unsigned char 范围是:" << "0 ~ 255" << endl;
cout << "===========================================================================" << endl;
unsigned u_integer = 10, u_integer_2 = 42; // unsigned 为无符号整型类型
cout << u_integer_2 - u_integer << endl; // 输出32
cout << u_integer - u_integer_2 << endl; // 输出4294967264
// 因为unsigned 在本机是32位的,所以它的范围是0 ~ 2^32-1(0~4294967295)
// 无符号的溢出是用该数对最大值求模取余减余数。
// 无符号的结果没有负数
int i_integer = 10, i2_integer = 42;
std::cout << i2_integer - i_integer << std::endl;
std::cout << i_integer - i2_integer << std::endl;
// 有符号的结果有负数
u_integer = 42;
i_integer = 10;
std::cout << i_integer - u_integer << std::endl; // 输出4294967264
std::cout << u_integer - i_integer << std::endl; // 输出32
// 有符号和无符号做运算,会首先把有符号转换为无符号类型
cout << "===========================================================================" << endl;
i_integer = 10;
while (i_integer >= 0) {
std::cout << i_integer << " ";
--i_integer; // --自减运算符,先使用对i减1的结果,再对i赋值
}
cout << endl;
// 和上面的while效果一样
for (int i = 10; i >= 0; --i)
std::cout << i << " ";
cout << endl;
for (unsigned u = 0; u <= 10; ++u)
std::cout << u << " "; // prints 0 . . . 10
cout << endl;
/* NOTE: the condition in the following loop
will run indefinitely
WRONG: u can never be less than 0; the condition will always succeed
for (unsigned u = 10; u >= 0; --u)
std::cout << u << std::endl;
这里的 u 因为是无符号的,所以永远都大于等于 0 ,循环条件将一直满足。
*/
u_integer = 11; // start the loop one past the first element we want to print
while (u_integer > 0) {
--u_integer; // decrement first, so that the last iteration will print 0
std::cout << u_integer << " ";
}
cout << endl;
// be wary of comparing ints and unsigned
// 比较带符号整型和无符号整型
u_integer = 10;
i_integer = -42;
if (i_integer < u_integer) // false: i 被转换成无符号类型
std::cout << i_integer << std::endl;
else
std::cout << u_integer << std::endl; // prints 10
// ========类型转换========
/*
* 类型所能表示的值的范围决定了转换的过程:
* 当把一个非bool的算术值赋给bool类型时,初始值为 0 则结果为false,否则true。
* 一个bool赋给非bool,初始值为false结果为0, 否则 1。
* 浮点赋给整数,结果只保留浮点前的部分。
* 整数赋给浮点类型,小数部分为 0。
* 赋给无符号类型一个超出它表示范围的值时,结果是初始值对无符号类型表示
* 数值总数取模后的余数。
* 赋值给带符号类型一个超出它表示范围的值时,结果是未定义的。
*/
i_integer = 42;
std::cout << i_integer << std::endl; // prints 42
if (i_integer) // condition will evaluate as true
i_integer = 0;
std::cout << i_integer << std::endl; // prints 0
bool b = 42; // b is true
std::cout << b << std::endl; // prints 1
int j_integer = b; // j has value 1
std::cout << j_integer << std::endl; // prints 1
double pi = 3.14; // pi has value 3.14
std::cout << pi << std::endl; // prints 3.14
j_integer = pi; // j has value 3
std::cout << j_integer << std::endl; // prints 3
unsigned char c_unchar = -1; // assuming 8-bit chars, c has value 255
i_integer = c_unchar; // the character with value 255 is an unprintable character
// assigns value of c (i.e., 255) to an int
std::cout << i_integer << std::endl; // prints 255
cout << "===========================================================================" << endl;
/*
* ========字面值常量========
* 一个形如 42 的值被称为字面值常量。
* 整型和浮点型字面值
* 字符和字符串字面值
* 转义序列
* 指定字面值的类型
*/
// ====整型和浮点型字面值====
// 20 // 十进制 , 类型是能容纳下当前值的int,long,longlong中最小的一个
// 024 // 八进制 , 类型是能容纳下当前值的int, unsigned int, loong,unsigned long,
// longlong,unsgned ll
// 0x14 // 十六进制, 中最小的一个
// 3.14159, 3.14159E0, 0., 0e0, .001 // 默认的浮点字面值是一个double
// ====字符和字符串字面值====
// 'a' // 字符字面值
// "Hello World!" // 字符串字面值,实际是由常量字符构成的数组array;
// 编译器在每个字符串的结尾添加一个空字符('\0')
std::cout << "a really, really long string literal "
"that spans two lines" << std::endl;
// multiline string literal 分多行书写的字符串字面值。
// ====转义序列====
// \n 换行 \t 横向制表符 \a 报警符
// \v 纵向制表符 \b 退格符 \" 双引号
// \\ 反斜线 \? 问号 \' 单引号
// \r 回车符 \f 进纸
std::cout << '\n'; // prints a newline
std::cout << "\tHi!\n"; // prints a tab followd by "Hi!" and a newline
std::cout << "Hi \x4dO\115!\n"; // prints Hi MOM! followed by a newline
std::cout << '\115' << '\n'; // prints M followed by a newline
// three ways to print a capital M
std::cout << 'M' << " " << '\115' << " " << '\x4d' << std::endl;
// ====指定字面值的类型====
// L'a' // 宽字符型字面值,类型是 wchar_t
// u8"hi!" // utf-8 字符串字面值
// 42ULL // 无符号整型字面值,类型是 unsigned long long
// 1E-3F // 单精度浮点型字面值,类型是 float
// 3.14159L // 扩展精度浮点型字面值,类型是 long double
/*
* 字符和字符串字面值
*前缀 含义 类型
* u Unicode 16字符 char16_t
* U Unicode 32字符 char32_t
* L 宽字符 wchar_t
* u8 UTF-8 仅用于字符串字面值常量 char
* 整型字面值
* 后缀 最小匹配类型
* u or U unsigned
* l or L long
* ll or LL long long
* 浮点型字面值
* 后缀 最小匹配类型
* f or F float
* l or L long double
*/
unsigned long long bigVal = -1ULL;
std::cout << bigVal << std::endl;
// ====布尔字面值和指针字面值====
// true and false is bool type literal.
// nullptr 是指针字面值。
bool test_bool = false;
// ================变量================
/*
* 变量提供一个具名的、可供程序操作的存储空间。C++的每个变量都有其数据类型,
* 数据类型决定着变量所占内存空间的大小和布局方式、该空间能存储的值的范围,
* 以及变量能参与的运算。对C++来说,变量和对象一般可以互换使用。
*/
// =========变量定义========
// 变量定义的基本形式: 类型说明符 变量名,变量名,变量名 = 初值;
int sum_int = 0, value_int, units_sold_int = 0; // sum_int value_int units_sold_int 都是 int
// sum_int units_sold_int 初值为 0
Sales_item item; // item 的类型是 Sales_item
std::string book("0-201-78345-X"); // book 通过一个 string 字面值初始化
// book 的定义用到了库类型 std::string ,像 iostream 一样,string 也是在命名空间std中定义的,
// string 是一种表示可变长字符序列的类型
/*
* 何为对象?
* 对象是指一块能存储数据,并具有某种类型的内存空间。
*/
/*
* ====初始值====
* 当对象在创建时获得了一个特定的值,我们说这个对象被初始化 initialized
*/
double price_d = 109.99, discount_d = price_d * 0.16;
// price_d 先被定义并初始化,随后用 price_d 初始化 discount_d
// double salePrice = applyDiscount(price_d, discount_d);
// 调用 applyDiscount 函数,然后用函数的返回值初始化 salePrice
// AAAAA 初始化不是赋值,初始化的含义是创建变量时赋予其一个初始值,
// 而赋值的含义是把对象的当前值擦除,而以一个新值来替代。
// ====列表初始化====
int units_sold = 0;
// int units_sold(0);
// int units_sold = {0}; // 列表初始化 list initialization
// int units_sold{0}; // 列表初始化
// AAAAA 如果我们使用列表初始化,且初始值存在丢失信息的风险,则编译器将报错。
long double ld = 3.14159266536;
// int a_int{ld}, b_int = {ld}; // 编译器报错:
// [Warning] narrowing conversion of 'ld' from 'long double' to 'int' [-Wnarrowing]
// [Warning] narrowing conversion of 'ld' from 'long double' to 'int' [-Wnarrowing]
int c_int(ld), d_int{c_int}; // 转换执行,同类型列表初始化。
int v1(1024); // direct-initialization, functional form
int v3 = 1024; // copy-initialization
// ====默认初始化====
/*
* 如果定义变量时没有指定初值,则变量被默认初始化 default initialized
*/
std::string empty_string; // empty_string 非显示地初始化为一个空串
Sales_item item_item; // 被默认初始化
// AAAAA 定义与函数体内的内置类型的对象如果没有初始化,则其值是未定义。类的对象如果没有显示初始化,
// 则其值由类确定。 对于其值未定义的对象,编译可能通过,但仍可能产生运行结果错误。
// =========变量声明和定义的关系========
/*
* 声明 declaration 使得名字为程序所知,一个文件如果想使用别处定义的名字,则必须包含对该名字的声明。
* 而定义 definition 负责创建与名字关联的实体。
* 变量只能被定义一次,但是可以多次声明。
* AAAAA C++ 是静态语言,会进行类型检查,所以要求我们在使用某个变量之前必须声明其类型。
*/
extern int i_extern; // 声明 i 而非定义 i
int j_definiton; // 声明并定义
// extern double pi_definition = 3.14; // 定义而非声明;
// 函数体内试图初始化一个由extern关键字标记的变量,将引发错误:
// [Eror] 'pi_definition' has both 'extern' and initializer
// ========标识符========
/*
* 标识符 identifer 由字母,数字,下划线组成,必须以字母或下划线开头,大小写敏感。
*/
int somename, someName, SomeName, SOMENAME; // 定义了4个不同的变量
// ====变量命名规范====
/*
* 标识符要能体现实际含义
* 变量名一般要用小写
* 用户自定义类名,一般以大写开头,Sales_item
* 如果标识符由多个单词组成,则应有明显区分,如:student_loan or studentLoan
* AAAAA 若能坚持,必将有效
*/
// ========名字的作用域========
/*
* 作用域 scope 以花括号分隔
* 名字的有效域始于声明,以声明语句所在的作用域末端为结束。
* 全局作用域 global scope : 如 main 函数
* 块作用域 block scope
*/
// ====嵌套的作用域====
// 内层作用域,外层作用域
int unique = 0; // unique has block scope
// output #1: uses global reused; prints 42 0
std::cout << reused << " " << unique << std::endl;
int reused = 0; // new, local object named reused hides global reused
// output #2: uses local reused; prints 0 0
std::cout << reused << " " << unique << std::endl;
// output #3: explicitly requests the global reused; prints 42 0
std::cout << ::reused << " " << unique << std::endl;
cout << "===========================================================================" << endl;
// ================复合类型================
/*
* 复合类型是指基于其它类型定义的类型。一条声明语句由一个基本数据类型和紧随其后的一个声明符列表组成
* 每个声明符命名了一个变量,并指定该变量为与基本类型有关的某种类型
*/
// ========引用========
/*
* 引用refrence 为对象引用另外一个名字,引用类型引用另外一种类型。
* 通过将声明符写成&d的形式来定义引用类型。
*/
int ival_re = 1024;
int &refVal = ival_re; // refVal 指向 ival_re
// 引用必须被初始化,程序一般把引用和它的初始值绑定在一起
// int ival_re2 = 1000;
// &refVal = ival_re2;
// ========指针========
// i is an int; p is a pointer to int; r is a reference to int
int i = 1024, *p = &i, &r = i;
// p 是一个指向int型的指针,p 被初始化 i的地址。引用r被初始化对象i
// three ways to print the value of i
std::cout << i << " " << *p << " " << r << std::endl;
// int型对象名i,指针p解引用得对象i的值,r相当于对象i的别名。
int j = 42, *p2 = &j;
int *&pref = p2; // pref is a reference to the pointer p2
// 引用类型pref 引用的是指向int型的指针,初始化为int型指针p2,相当于p2 的别名为 pref
// prints the value of j, which is the int to which p2 points
std::cout << *pref << std::endl;
// 输出 pref 的解引用 :*p2 : 42
// pref refers to a pointer; assigning &i to pref makes p2 point to i
pref = &i;
// pref 引用的是指针p2,所以相当于 p2=&i, p2 指向 i
std::cout << *pref << std::endl; // prints the value of i
// dereferencing pref yields i, the int to which p2 points;
*pref = 0; // changes i to 0
std::cout << i << " " << *pref << std::endl; // 输出 0
p = &j; // p 指向 j
pref = p; // 给引用赋新值,引用指针p
std::cout << "*p: " << *p << " *pref: " << *pref << " j: " << j << endl;
// 输出 42
// ====空指针====
int *p1_nullptr = nullptr; // 等价于int *P1_nullptr = 0;
int *p2_nullptr = 0;
int i_int = 2;
int *p1 = &i_int; // p1 points to i
*p1 = *p1 * *p1; // equivalent to i = i * i
cout << "i_int = " << i_int << endl;
*p1 *= *p1; // equivalent to i *= i
cout << "i_int = " << i_int << endl;
// ====void * 指针====
/*
* void * 是一种特殊的指针类型,可用于存放任意对象的地址
*/
double obj = 3.14, *pd = &obj;
void *pv = &obj;
pv = pd;
// ====指向指针的指针====
int ival = 1024;
int *pi_point = &ival; // pi points to an int
int **ppi = &pi_point; // ppi points to a pointer to an int
// 指向int型指针的指针
cout << "The value of ival\n"
<< "direct value: " << ival << "\n"
<< "indirect value: " << *pi_point << "\n"
<< "doubly indirect value: " << **ppi << "\n"
<< "*ppi: " << *ppi << " pi_point: " << pi_point
<< endl;
cout << *pi_point << " " << &ival << endl;
// ========const限定符=========
/*
* const 限定的对象,其值不能被改变,所以也必须初始化。
* 默认状态下,const对象仅在文件内有效;
* 多个文件中出现了同名的const变量时,就等同于在不同文件分别定义了独立的变量
*/
const int bufsize = 512;
// 编译器在编译过程中把用到该变量的地方都替换成对应的值。512 替换 bufsize
// extern const int bufsize_const = 0;
// extern const int bufsize_const; // 假设bufusize_const与之前的bufsize_const
// 不是同一个,用extern加以限定,就可以在不同文件使用
// ======== const的引用 ========
const int ci_int = 1024; // const 对象,int 型
const int &ri_int = ci_int; // 引用绑定到const对象上,对常量的绑定。
// ri_int = 42; // error: ri_int 是对常量的引用
// int &r2_int = ci_int; // error: 非常量对象引用常量对象。
// 常量引用是 对 const的引用。
// 引用的对象是常量还是非常量可以决定其所能参与的操作,却无论如何都不会影响到
// 引用和对象的绑定关系本身。
// ==== 初始化和对 const 的引用 ====
i_int = 42;
const int &r_const_int = i_int; // 允许将 const int & 绑定到一个普通的int上
const int &r_const_2 = 42; // 常量引用
const int &r_const_3 = r_const_int * 2;
// int &r_4 = r_const_int * 2; // 非常量引用 引用字面值
// ======== 指针和const ========
const double pi_double = 3.14;
// double *ptr_pi = &pi_double; error: 普通指针引用常量指针
const double *const_double_ptr = &pi_double; // 指针指向const常量
// 指向常量的指针。
// *const_double_ptr = 40; // error; 不能给const指针指向的值赋值
int errNumber = 0;
// 常量指针
int *const curErr = &errNumber; // curErr 将一直指向errNumber
// 被const修饰的curErr 里面的值(地址)一直不变。
const double pi_dou = 3.14;
const double *const c_pi_c = &pi_dou; // 常量指针指向const常量
// ======== constexpr 和常量表达式 ========
/*
* 常量表达式:是指值不会改变并且在编译过程就能得到计算结果的表达式。
*/
const int max_files = 20; // const expression
const int limit = max_files; // const expression
int staff_size = 28; // not const expression
// const int sz = get_size(); // sz not const expression
// ==== constexpr 变量 ====
constexpr int mf = 20; // const expression
constexpr int limit_ex = mf + 1; // const expression
// constexpr int sz = size();
// ==== pointer and constexpr ====
const int *p_cpoint = nullptr; // p_cpoint point to int type
constexpr int *q_cpoint = nullptr; // q_cpoint point to integer
// ================ processing type ================
/*
* type alias
* 类型别名(type alias)是一个名字,它是某种类型的同义词。
*/
typedef double wages; // wages is doble's synonym
typedef wages base, *pp;
using SI = Sales_item; // SI is Sales_itme's synonym
typedef char *pstring;
const pstring cstring = 0;
const pstring *ps;
// ======== auto ========
auto item_auto = i_int + i_int; // item is int type
// auto sz_auto = 0, pi_coin = 3.1415; // error: sz pi_coin type not same
int i_auto = 0, &r_auto = i_auto;
auto a_auto = r_auto; // a_auto is int type;
// auto 忽略顶层const,保留底层const;
const int ci_auto = 1, &cr_auto = ci_auto;
auto b_auto = ci_auto; // b_auto is int type
auto c_auto = cr_auto; // c_auto is int refrence type
auto d_auto = &i_auto; // d_auto 是整形指针
auto e_auto = &ci_auto; // e_auto type is: const int *e_auto
auto &f_auto = ci_auto; // const int f_auto = ci_auto;
const auto &g_auto = 20;
// const int &g_auto = 20;
/*
* decltype
*/
int a = 0;
decltype(a) c_decl = a; // c is an int, c 的类型为 a 表达式的类型
decltype((a)) d_decl = a; // d is a reference to a
// 带括号的类型为引用 :int &d
const int ci_de = 0, &cr_de = ci_de;
decltype(ci_de) x_de = 0;
decltype(cr_de) y_de = ci_de;
// decltype(cr_de) z_de; // error
// 自增和自减
++c_decl; // increments c, a (and d) unchanged
cout << "a: " << a << " c_decl: " << c_decl << " d_decl: " << d_decl << endl;
++d_decl; // increments a through the reference d
cout << "a: " << a << " c_decl: " << c_decl << " d_decl: " << d_decl << endl;
int A = 0, B = 0;
decltype((A)) C = A; // C is a reference to A
decltype(A = B) D = A; // D is also a reference to A
++C;
cout << "A: " << A << " C: " << C << " D: " << D << endl;
++D;
cout << "A: " << A << " C: " << C << " D: " << D << endl;
// 字符串初始化
// alternative ways to initialize string from a character string literal
std::string titleA = "C++ Primer, 5th Ed.";
std::string titleB("C++ Primer, 5th Ed.");
std::string all_nines(10, '9'); // all_nines = "9999999999"
std::cout << "Hello World!"; // simple character string literal
std::cout << ""; // empty character string literal
// literal using newlines and tabs
std::cout << "\nCC\toptions\tfile.[cC]\n";
int &ri = i; // ri is a reference to i
// ri is just another name for i;
// this statement prints the value of i twice
std::cout << i << " " << ri << std::endl;
i = 5; // changing i is reflected through ri as well
std::cout << i << " " << ri << std::endl;
ri = 10; // assigning to ri actually assigns to i
std::cout << i << " " << ri << std::endl;
/* Sales_data data1, data2;
// 定义了两个类对象data1 data2
// code to read into data1 and data2
double price = 0; // price per book, used to calculate total revenue
// read the first transactions: ISBN, number of books sold, price per book
std::cin >> data1.bookNo >> data1.units_sold >> price;
// calculate total revenue from price and units_sold
data1.revenue = data1.units_sold * price;
// read the second transaction
std::cin >> data2.bookNo >> data2.units_sold >> price;
data2.revenue = data2.units_sold * price;
// code to check whether data1 and data2 have the same ISBN
// and if so print the sum of data1 and data2
if (data1.bookNo == data2.bookNo) {
unsigned totalCnt = data1.units_sold + data2.units_sold;
double totalRevenue = data1.revenue + data2.revenue;
// print: ISBN, total sold, total revenue, average price per book
std::cout << data1.bookNo << " " << totalCnt
<< " " << totalRevenue << " ";
if (totalCnt != 0)
std::cout << totalRevenue/totalCnt << std::endl;
else
std::cout << "(no sales)" << std::endl;
return 0; // indicate success
} else { // transactions weren't for the same ISBN
std::cerr << "Data must refer to the same ISBN"
<< std::endl;
*/
return 0;
}
C++ 变量和基本类型
最新推荐文章于 2024-08-28 14:35:43 发布