C++11中longlong超长整型和nullptr初始化空指针

目录
  • 1. C++11:long long 超长整型
  • 2. C++11:nullptr 初始化空指针

本文介绍 C++11 标准中新添加的 long long 超长整型和 nullptr 初始化空指针。

1. C++11:long long 超长整型

C++ 11 标准中,基于整数大小的考虑,共提供了如下表所示的这些数据类型。与此同时,标准中还明确限定了各个数据类型最少占用的位数。

整数类型 等价类型 C++11标准规定占用最少位数
short short int(有符号短整型) 至少 16 位(2 个字节)
signed short short int(有符号短整型) 至少 16 位(2 个字节)
signed short int short int(有符号短整型) 至少 16 位(2 个字节)
unsigned short unsigned short int(无符号短整型) 至少 16 位(2 个字节)
unsigned short int unsigned short int(无符号短整型) 至少 16 位(2 个字节)
int int(有符号整形) 至少 16 位(2 个字节)
signed int(有符号整形) 至少 16 位(2 个字节)
signed int int(有符号整形) 至少 16 位(2 个字节)
unsigned unsigned int(无符号整形) 至少 16 位(2 个字节)
unsigned int unsigned int(无符号整形) 至少 16 位(2 个字节)
long long int(有符号长整形) 至少 32 位(4 个字节)
long int long int(有符号长整形) 至少 32 位(4 个字节)
signed long long int(有符号长整形) 至少 32 位(4 个字节)
signed long int long int(有符号长整形) 至少 32 位(4 个字节)
unsigned long unsigned long int(无符号长整形) 至少 32 位(4 个字节)
unsigned long int unsigned long int(无符号长整形) 至少 32 位(4 个字节)
long long(C++11) long long int(有符号超长整形) 至少 64 位(8 个字节)
long long int(C++11) long long int(有符号超长整形) 至少 64 位(8 个字节)
signed long long(C++11) long long int(有符号超长整形) 至少 64 位(8 个字节)
signed long long int(C++11) long long int(有符号超长整形) 至少 64 位(8 个字节)
unsigned long long(C++11) unsigned long long int(无符号超长整型) 至少 64 位(8 个字节)
unsigned long long int(C++11) unsigned long long int(无符号超长整型) 至少 64 位(8 个字节)

C++11 标准规定,每种整数类型必须同时具备有符号(signed)和无符号(unsigned)两种类型,且每种具体的有符号整形和无符号整形所占用的存储空间(也就是位数)必须相同。不过需要注意的是,C++11 标准中只限定了每种类型最少占用多少存储空间,不同的平台可以占用不同的存储空间。

在上表罗列的这些数据类型中,long long 超长整型是 C++ 11 标准新添加的。其实早在 1995 年,就有人提议将 long long 整形写入 C++ 98 标准,但被委员会拒绝了。而后 long long 整形被 C99 标准(C语言标准之一)采纳,并逐渐被很多编译器支持,于是 C++ 标准委员会重新决定将 long long 整形写入 C++ 11 标准中。

如同 long 类型整数需明确标注 "L" 或者 "l" 后缀一样,要使用 long long 类型的整数,也必须标注对应的后缀:

  • 对于有符号 long long 整形,后缀用 "LL" 或者 "ll" 标识。例如,"10LL" 就表示有符号超长整数 10;
  • 对于无符号 long long 整形,后缀用 "ULL"、"ull"、"Ull" 或者 "uLL" 标识。例如,"10ULL" 就表示无符号超长整数 10。

如果不添加任何标识,则所有的整数都会默认为 int 类型。

对于 long long 类型来说,如果想了解当前平台上 long long 整形的取值范围,可以使用<climits>头文件中与 long long 整形相关的 3 个宏,分别为 LLONG_MIN、LLONG_MAX 和 ULLONG_MIN:
1)LLONG_MIN:代表当前平台上最小的 long long 类型整数;
2)LLONG_MAX:代表当前平台上最大的 long long 类型整数;
3)ULLONG_MIN:代表当前平台上最大的 unsigned long long 类型整数(无符号超长整型的最小值为 0)。
举个例子:

#include <iostream>
#include <iomanip>
#include <climits>
using namespace std;

int main()
{
    cout <<"long long最大值:" << LLONG_MIN <<" "<< hex << LLONG_MIN <<"\n";
    cout << dec <<"long long最小值:" << LLONG_MAX << " " << hex << LLONG_MAX << "\n";
    cout << dec << "unsigned long long最大值:" << ULLONG_MAX << " " << hex << ULLONG_MAX;
    return 0;
}

程序执行结果为(不唯一):

long long最大值:-9223372036854775808 8000000000000000
long long最小值:9223372036854775807 7fffffffffffffff
unsigned long long最大值:18446744073709551615 ffffffffffffffff

此程序中,输出了各最大值和最小值对应的十六进制,显然在当前平台(Windows10 64位操作系统)上,long long 超长整型占用 64 位(也就是 16 个字节)的存储空间。

2. C++11:nullptr 初始化空指针

实际开发中,避免产生“野指针”最有效的方法,就是在定义指针的同时完成初始化操作,即便该指针的指向尚未明确,也要将其初始化为空指针。

所谓“野指针”,又称“悬挂指针”,指的是没有明确指向的指针。野指针往往指向的是那些不可用的内存区域,这就意味着像操作普通指针那样使用野指针(例如 &p),极可能导致程序发生异常。

C++98/03 标准中,将一个指针初始化为空指针的方式有 2 种:

int *p = 0;
int *p = NULL; //推荐使用

可以看到,我们可以将指针明确指向 0(0x0000 0000)这个内存空间。一方面,明确指针的指向可以避免其成为野指针;另一方面,大多数操作系统都不允许用户对地址为 0 的内存空间执行写操作,若用户在程序中尝试修改其内容,则程序运行会直接报错。
相比第一种方式,我们更习惯将指针初始化为 NULL。值得一提的是,NULL 并不是 C++ 的关键字,它是 C++ 为我们事先定义好的一个宏,并且它的值往往就是字面量 0(#define NULL 0)。

C++ 中将 NULL 定义为字面常量 0,虽然能满足大部分场景的需要,但个别情况下,它会导致程序的运行和我们的预期不符。例如:

#include <iostream>
using namespace std;

void isnull(void *c){
    cout << "void*c" << endl;
}
void isnull(int n){
    cout << "int n" << endl;
}

int main() {
    isnull(0);
    isnull(NULL);
    return 0;
}

程序执行结果为:

int n
int n

对于 isnull(0) 来说,显然它真正调用的是参数为整形的 isnull() 函数;而对于 isnull(NULL),我们期望它实际调用的是参数为 void*c 的 isnull() 函数,但观察程序的执行结果不难看出,并不符合我们的预期。
C++ 98/03 标准中,如果我们想令 isnull(NULL) 实际调用的是 isnull(void* c),就需要对 NULL(或者 0)进行强制类型转换:

isnull( (void*)NULL );
isnull( (void*)0 );

如此,才会成功调用我们预期的函数。

由于 C++ 98 标准使用期间,NULL 已经得到了广泛的应用,出于兼容性的考虑,C++11 标准并没有对 NULL 的宏定义做任何修改。为了修正 C++ 存在的这一 BUG,C++ 标准委员会最终决定另其炉灶,在 C++11 标准中引入一个新关键字,即 nullptr。

在使用 nullptr 之前,需保证自己使用的编译器支持该关键字。以 Visual Studio 和 codeblocks 为例,前者早在 2010 版本就对 C++ 11 标准中的部分特性提供了支持,其中就包括 nullptr;如果使用后者,则需将其 G++ 编译器版本至少升级至 4.6.1(同时开启 -std=c++0x 编译选项)。

nullptr 是 nullptr_t 类型的右值常量,专用于初始化空类型指针。nullptr_t 是 C++11 新增加的数据类型,可称为“指针空值类型”。也就是说,nullpter 仅是该类型的一个实例对象(已经定义好,可以直接使用),如果需要我们完全定义出多个同 nullptr 完全一样的实例对象。

值得一提的是,nullptr 可以被隐式转换成任意的指针类型。举个例子:

int * a1 = nullptr;
char * a2 = nullptr;
double * a3 = nullptr;

显然,不同类型的指针变量都可以使用 nullptr 来初始化,编译器分别将 nullptr 隐式转换成 int*、char* 以及 double* 指针类型。

另外,通过将指针初始化为 nullptr,可以很好地解决 NULL 遗留的问题,比如:

#include <iostream>
using namespace std;

void isnull(void *c){
    cout << "void*c" << endl;
}
void isnull(int n){
    cout << "int n" << endl;
}

int main() {
    isnull(NULL);
    isnull(nullptr);
    return 0;
}

程序执行结果为:

int n
void*c

借助执行结果不难看出,由于 nullptr 无法隐式转换为整形,而可以隐式匹配指针类型,因此执行结果和我们的预期相符。

总之在 C++11 标准下,相比 NULL 和 0,使用 nullptr 初始化空指针可以令我们编写的程序更加健壮。

到此这篇关于C++11:longlong超长整型和nullptr初始化空指针的文章就介绍到这了,更多相关C++11 nullptr初始化空指针内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • C++11 nullptr实现初始化空指针

    实际开发中,避免产生“野指针”最有效的方法,就是在定义指针的同时完成初始化操作,即便该指针的指向尚未明确,也要将其初始化为空指针. 所谓“野指针”,又称“悬挂指针”,指的是没有明确指向的指针.野指针往往指向的是那些不可用的内存区域,这就意味着像操作普通指针那样使用野指针(例如 &p),极可能导致程序发生异常. C++98/03 标准中,将一个指针初始化为空指针的方式有 2 种: int *p = 0; int *p = NULL; //推荐使用 可以看到,我们可以将指针明确指向 0(0x0000

  • C++11中longlong超长整型和nullptr初始化空指针

    目录 1. C++11:long long 超长整型 2. C++11:nullptr 初始化空指针 本文介绍 C++11 标准中新添加的 long long 超长整型和 nullptr 初始化空指针. 1. C++11:long long 超长整型 C++ 11 标准中,基于整数大小的考虑,共提供了如下表所示的这些数据类型.与此同时,标准中还明确限定了各个数据类型最少占用的位数. 整数类型 等价类型 C++11标准规定占用最少位数 short short int(有符号短整型) 至少 16 位

  • 用Python将IP地址在整型和字符串之间轻松转换

    前言 大家应该都有所体会,对于字符串型的IP存入数据库中,实在是个即浪费空间又浪费性能的家伙,所以可爱的人们想出来将IP转换为整型存储.MySQL中存在INET_ATON() .INET_NTOA()函数进行IP整型和字符串之间的转换,那么Python中存在什么方法可以实现MySQL中INET_ATON() .INET_NTOA()的功能呢?方法肯定是有的- 方法如下 # 导入相关模块包 import socket import struct # 将IP从字符串转为整型 >>> int(

  • python3中int(整型)的使用教程

    Python3支持三种不同的数值类型: 整型(int)--通常被称为是整型或整数,可以是正整数或负整数,不带小数点.Python3整型是没有限制大小的,可以当做long类型使用, 但实际上由于机器内存的有限,我们使用的整数是不可能无限大的. 浮点型(float)--浮点型数字由整数部分和小数部分组成,浮点型也可以使用科学计数法表示(2.5e2 = 2.5 x 102 = 250) 复数(complex)--复数由实数部分和虚数部分构成,可以用a + bj,或者complex(a,b)表示,复数的

  • 详解MySQL中的数据类型和schema优化

    最近在学习MySQL优化方面的知识.本文就数据类型和schema方面的优化进行介绍. 1. 选择优化的数据类型 MySQL支持的数据类型有很多,而如何选择出正确的数据类型,对于性能是至关重要的.以下几个原则能够帮助确定数据类型: 更小的通常更好 应尽可能使用可以正确存储数据的最小数据类型,够用就好.这样将占用更少的磁盘.内存和缓存,而在处理时也会耗时更少. 简单就好 当两种数据类型都能胜任一个字段的存储工作时,选择简单的那一方,往往是最好的选择.例如整型和字符串,由于整型的操作代价要小于字符,所

  • C++11中std::move、std::forward、左右值引用、移动构造函数的测试问题

    关于C++11新特性之std::move.std::forward.左右值引用网上资料已经很多了,我主要针对测试性能做一个测试,梳理一下这些逻辑,首先,左值比较熟悉,右值就是临时变量,意味着使用一次就不会再被使用了.针对这两种值引入了左值引用和右值引用,以及引用折叠的概念. 1.右值引用的举例测试 #include <iostream> using namespace std; ​ //创建一个测试类 class A { public: A() : m_a(55) { } ​ int m_a;

  • 详解C++11中的线程锁和条件变量

    线程 std::thread类, 位于<thread>头文件,实现了线程操作.std::thread可以和普通函数和 lambda 表达式搭配使用.它还允许向线程的执行函数传递任意多参数. #include <thread> void func() { // do some work } int main() { std::thread t(func); t.join(); return 0; } 上面的例子中,t是一个线程实例,函数func()在该线程运行.调用join()函数是

  • C++中字符串与整型及浮点型转换全攻略

    目录 一.string 和 char [] 1. string 转 char [] 2. char [] 转 string 二.char [] 与数字互转 1. char [] 转整型和浮点型 2. 整型和浮点型 转char [] 3. 整型转 char [] (特殊函数实现) 首先请出今日主角:stdlib.h (YYDS) 这个库包含有随机数,abs等许多通用函数,当然也有类型的转换 下面我们一点点来看如何完成格式转换 一.string 和 char [] 1. string 转 char

  • 关于C++11中限定作用域的枚举类型的问题

    枚举类型是将一组有限的整数常量组织在一起用以描述变量可取值范围的一种数据类型.C++中有两种类型的枚举:不限定作用域的枚举类型和限定作用域的枚举类型.限定作用域的枚举类型是C++11标准引入的新类型. ● 限定作用域枚举类型是为了弥补不限定作用域枚举类型的不足而出现的,不限定作用域的枚举类型不是类型安全的,主要表现在如下几个方面: ● 不限定作用域的枚举类型中的枚举成员被视为整数,两种不同的枚举类型之间可以进行比较.两种不同类型的数据进行比较,可能带来数据类型转换,引起数据表示不完整. ● 不限

  • C++11中bind绑定器和function函数对象介绍

    目录 一. bind1st和bind2nd 1.C++ STL中的绑定器 2.bind1st和bind2nd的底层原理实现 二. 模板的完全特例化和非完全特例化 三. function函数对象 四. bind和function实现线程池 五. lambda表达式 1.lambda表达式的实现原理 2.lambda表达式的应用实践 一. bind1st和bind2nd 1.C++ STL中的绑定器 bind1st:operator()的第一个形参变量绑定成一个确定的值 bind2nd:operat

随机推荐