菜鸟的C++翻身之路(1)

本文介绍了C++中的类型转换,包括无符号类型溢出规则,并通过实例解释了-1赋值给unsigned int的表示形式。此外,详细讨论了引用的概念,对比了引用与指针的区别,提到了野指针的问题以及void*指针的使用。还涵盖了const限定符、constexpr和常量表达式、typedef与using别名,以及decltype和auto的用法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.类型转换:

当我们赋给无符号类型一个超出它表示范围的值时,结果是初始值对无符号类型表示值总数取模后的余数。
比如: unsigned int i = -1;
在计算机中 负数是以补码的形式存储的。
原码:将一个数转换成二进制就是它的原码。
1的原码: 0000 0000 0000 0001
-1的原码:1000 0000 0000 0001
反码:正数的补码是本身,负数的补码是除符号位按位取反。
1的反码: 0000 0000 0000 0001
-1的反码:1111 1111 1111 1110
补码:正数是本身 负数是反码+1
1的补码: 0000 0000 0000 0001
-1的补码:1111 1111 1111 1111
-1是超出unsigned int 范围的,无符号int 可以表示的总数是[0, 0xffff) 一共2^16 个数,所以-1赋给unsigned int 的值应该是 (216-1)%216,所以-1的表示形式 是 0xffff
16位的编译器 int占16位(2个字节)
32或64位的编译器 int占32位(4个字节)

 unsigned int i = -1;
    printf("%u\n", i);  //4294967295
    printf("%d\n", i);  //-1  相当于强制转换成signed
  1. sizeof & memset

sizeof 用来返回类型或对象所占的字节数,是一个操作符。
sizeof 三种语法形式:

  • sizeof (对象)
  • sizeof 对象
  • sizeof (类型)

e.g.
int i;
sizeof(i); //4
sizeof i; //4
sizeof (int); //4
memset(void *buffer, int c, int count)
buffer 指针 c赋给buffer指向对象的值 count 是长度(字节数)
memset(data, 0x0f, sizeof(data))
data[0] : 0000 0001 0000 0001 0000 0001 0000 0001

3.引用 & 指针

  • 我们所说的引用,指的是左值引用。相当于给对象起了另外一个名字。
  • 不能用常量对引用进行初始化。即 int &data = 9是错误的。

指针与引用的区别

指针是一个对象,而引用是别名。
指针可以不赋初值,引用不可以。
指针可以在其生命周期内指向不同的对象,引用只能在它初始化的时候赋值。

野指针

野指针是指指向了一块随机的内存空间,不受程序控制。如指针指向已经被删除的对象或者指向一块没有访问权限的内存空间,之后再对其解引用。
产生原因:

  • 指针定义时未被初始化(static修饰的指针变量会被置空)
  • 指针释放的时候没有被置空。
  • 指针操作超越变量作用域。

void* 指针

void* 是一种特殊的指针类型,可用于存放任意对象的地址。利用void* 指针能做的事儿也比较有限:拿它和别的指针比较、作为函数的输入输出,或者赋给另一个void*指针。

指向指针的引用

int i = 42;
int  *p;
int *&r = p  //r是一个指向指针的引用。
r = &i;
r = 0;

4.const限定符

  • 因为const对象一旦创建后其值就不能再改变,所以const必须初始化(引用也是)
  • 如果想在多个文件之间共享const 对象,必须在变量的定义之前添加extern关键字。
  • 非常量可以转换成const;
int i = 42;
const int &r1 = i;  //允许将const int & 绑定到一个普通int 对象上
const int &r2 = 42; //正确:r2是一个常量引用
const int &r3 = r1 * 2;  //正确: r3是一个常量引用
int &r4 = r1 * 2;  //错误:不能用非常量来绑定一个常量。
int i = 43;
const int *p = &i;  //p是一个指针 指向整型常量 p指的对象的值不变(底层const)
int *const p = &i; //p是一个常量指针 指向整型  p永远指向i (顶层const)
const int* const p = &i;  //p是一个常量指针 指向整型常量

5.constexpr和常量表达式

  • 常量表达式是指值不会改变并且在编译过程就能得到计算结果的表达式。
const int max_files = 20;
  • 将变量声明为constexpr,编译器可以来验证变量值是否是一个常量表达式。

  • 在constexpr声明中如果定义了一个指针,限定符constexpr仅对指针有效。

    constexpr int mf = 20;
    constexpr int limit = mf + 1;
    constexpr int sz = get_size();   //编译器报错

    const int *p = nullptr;
    constexpr int *q = nullptr;  //q是一个指向整型的常量指针

6.typedef(类型别名) & using (别名声明)

typedef long long LL;
using LL = long long;

7.decltype类型指示符 & auto

  • auto会忽视顶层const, 底层const被保留下来。decltype都会保留下来。

  • decltype的结果类型与表达式形式密切相关。如果给变量加上了一层或多层括号,编译器会把它当成是一个表达式。变量是一种可以作为赋值语句左值得特殊表达式,所以这样的decltype就会得到引用类型。

  • 表达式的内容是解引用操作,decltype将得到引用类型。

  • 赋值也会产生引用;

int i = 42, *p = &i;
decltype(*p) c;  //错误, c是int&, 必须初始化
decltype((i)) d; //错误:d是int&, 必须初始化
decltype(i) e;  e是一个未初始化的int
decltype(a = b) c;//错误, c是int&, 必须初始化  a并没有真的等于b
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值