c++ primer初学笔记

本文讲解了字符型与无字符型的区别,无符号类型溢出处理,字面值常量、类型别名与引用的概念,以及const限定符、constexpr和auto的使用。重点介绍了如何避免混合使用有符号和无符号类型带来的问题,以及如何正确使用const和auto提升代码可读性和效率。
摘要由CSDN通过智能技术生成

第二章 变量与基本类型

2.1.2字符型与无字符型

 字符型可以用来表示负值,但无字符型可以表达的范围更大

8比特位的signde char:-127 - 127;

unsigende char:0 - 255;

 当我们赋给无符号类型一个超出范围的值时,结果是初始值对无符号类型表示值总数取模后的余数。例如当把-1赋给一个unsigned char时,输出的结果最终为255。

用无符号值进行循环时可能会出现死循环/*本循环的关键是要将0也输出*/

#include<iostream>
int main()
{
	for (unsigned u = 10; u >= 0; u--)
	{
		std::cout << u<<std::endl;
	}
	return 0;

}

因为当循环进行到u = 0时,u--本该等于-1;但是由于u为无符号数,所以u会自动转化为最大数42946....。所以程序会陷入无限循环之中。

改正:

1.当无需打印0时直接将u>=0改为u>0;即可

2.我们可以在循环到0时进行判断,此时可以借助while循环来进行。

#include<iostream>
int main()
{
	unsigned u = 11;//此处是为了将10也打印出来,否则u先自减无法将10打印出。
	while (u > 0)
	{
		u--;
		std::cout << u << std::endl;
	}
	return 0;

}

特殊:

请勿将无符号型与有符号型的变量混用。

例:当两个变量都是有符号型的

#include<iostream>
int main()
{
	int a = -1;
	int b = 1;
	std::cout << a * b;
	return 0;

}

此时的输出结果正常,为-1。

当一个变量为有符号型,另一个为无符号型时:

#include<iostream>
int main()
{
	int a = -1;
	unsigned int b = 1;
	std::cout << a * b;
	return 0;

}

此时的结果却无法得到-1,而是4294967295(无符号数中十进制的最大值)

这是由于当两者混用时有符号型的值会自动的转化为无符号型,使得a的值由原来的-1变成了无符号数中的最大值4294967295。

2.1.3 字面值常量

以0开头的数为八进制数;以0x或OX开头的数为十六进制的数

  20/*十进制*/            020/*八进制数*/      0x14/*十六进制数*/

浮点型字面值表现为一个小数或奕科学计数法表示的指数。(指数部分用e/E来表示)

  3.14159      3.14159e0    0e0    .001

由单括号括起来的字符称为char型字面值;

有双括号括起来的零个或多个字符则构成了字符串;


转义字符(常用)

换行符  \n       制表符\t   

 /后面也可以跟上一到三个八进制的数即泛化的转义序列。

也可以/x后面跟上一个或多个十六进制的数。

 换行符  /12        空格  /40   空字符  /0

2.2.2 变量声明和定义的关系

声明使得变量为程序所知,一个文件如果想使用其他文件定义的变量必须要声明。

其他文件是指与源文件不同的文件 (头文件...)

声明的变量必须是先前被定义的

声明的主要作用是为了读取其他文件中的变量值

定义是负责创建与名字相关联的实体。

如果想单单声明变量 只需在原本定义之前加入(extern):

extern int i;  //声明了变量而非定义
int j;//声明并定义了一个新变量j

注:

变量能且只能被定义一次,但是可以被多次声明。

嵌套的作用域

#include<iostream>
int m = 1;
int main()
{
	int m = 2;
	std::cout << m << std::endl;//输出局部变量
	std::cout <<:: m << std::endl;//输出全局变量
	return 0;
}

运用:一般在for循环中 常常会不经意间定义一个已经存在的变量名作为全局变量,但是当for循环结束以后,for循环中定义的值无法被读出。

2.3.1 引用:

引用不占用地址,只是另一个数的别名

#include<iostream>
int main()
{
	int i;
	int& m = i;
	m = 2;
	std::cout << i;
	return 0;
}

此处m即为i的引用,通过更改m的值来间接的修改i的值

 对指针的引用

#include<iostream>
#include<cstdlib>
int main()
{
	int i = 1;
	int* p;
	int*& r = p;
	r = &i;
	std::cout << *r << std::endl << r;

	return 0;
}

 注:1.由于引用不占用地址,所以不能定义一

个指向引用的指针。

         2.不能定义引用的引用

         3.引用的对象必须是同一类型的

2.32 指针

利用指针来访问对象时则需要使用解引用符(*)

关键概念:某些符号有着多重含义

#include<iostream>
int main()
{
	int i = 42;  //定义一个整数i;
	int& r = i;  //r为i的引用;
	int* p;
	p = &i;      //p为指向i的指针
	*p = i;      //对p进行解指针得到的值赋为i
	int& r2 = *p;  //r2为p所指对象的引用
	return 0;
}

空指针

定义空指针的三种方式

#include<iostream>
#include<cstdlib>
int main()
{
	int* p = nullptr;
	int* p2 = 0;
	int* p3 = NULL;
	return 0;
}

//在新标准下最好使用nullptr  而不是NULL

//不能将一个变量直接赋给指针(尽管变量的值恰好为0)

指针也可以当做一个判断条件

if(p)  ->当p为一个非空指针时执行循环体

//p为非空  即表示p有一个所指的对象

2.4const  限定符

作用:定义一个变量,使其的值不再发生改变。但是const定义的变量必须初始化。

可以把引用绑定在const上,实现对常量的绑定,但是不能修改其值

const int c = 1024;

const int &i = c;

const:

可以将常量绑定到变量上;但是不可以将变量绑定到常量之上。

#include<iostream>
#include<cstdlib>
int main()
{
	int i = 1;
	const int m = 2;
	//int& r = m;//将变量绑定到了一个常量上   程序会报错
	const int& x = i;//将常量绑定到了一个变量上,可以通过修改变量的值来间接的修改常量的值。
	//std::cout << r;
	std::cout<< x;
	return 0;
}

 const的分类

顶层const:指的是对数值进行常量化;

底层const:指的是对地址进行常量化。

 2.4.4  constexpr和常量表达式

声明为constexpr的变量一定是一个常量,所以定义为constexpr的变量赋值表达式一定是一个可以立马得到数值的常量。

当你认定一个数为常量时,可以优先考虑使用constexpr来定义变量。(由constexpr修饰的变量一定是个常数)

#include<iostream>
#include<cstdlib>
int main()
{
	const int i = 1;
	const int* p = nullptr;//定义了一个指向常量的指针
	constexpr int* q = nullptr;//定义了一个指向整数的常量指针
	constexpr int* m = &i;//指向一个整数i的常量指针
	std::cout << q;
	return 0;
}

指针常量和类型别名

typedef char* pstring;
const pstring sctr = 0;//sctr 是一个指向char的常量指针。
const pstring* ps;//ps 是一个指向char的常量指针

const char* sctr = 0;//与上面的表达式不相等;这里表示的是一个指向const char 的指针。

2.5.2 auto的运用:

auto可以让计算机判断变量的数值类型(auto定义的变量必须要有初始值)

auto可以同时定义多个变量,但是必须都是同一个类型的变量。

2.5.1 类型别名

decltype类型指示符(完全模拟对象的性质)

当我们想仅仅定义个变量,而不像对其进行赋给初始值时,我们可以考虑使用decltype来进行对变量类型的定义。

const int ci = 0;
int i = 1;
const int& cj = ci;
decltype (ci) m; //m的类型为const int。
decltype (cj) x = i;//x为i的引用,直接对cj的模仿。 x的类型为const int &;

如果括号内为解引用操作,则得到的类型即为int & ,此时定义的变量就必须要有初始值(此时变量为一个引用,所以必须要初始化)

如果decltype的表达式带上了括号则结果为引用。(双括号的结果一定为引用)

代码演示:

int i = 42;
int* p = &i;
decltype (*p) m = i;//m为i的引用
decltype ((i)) m = i;//与上面的表达式意义相同

 自定义一个数据结构:

(参考线性表的定义)

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值