看了下现在已经有的回答,都没有拎出这个语法现象的本质。实际上,常量后缀语法只是对常量进行强制类型转化的语法糖而已。
C 语言的语法比较简单纯粹,所以我们先来举几个 C 语言里的例子
void g(unsigned long long); void f(int i) { g(2333ull * i % 100000007ull); }
相信很多人都见过这样的代码,事实上,这种模式的代码在线性同余的算法中很常见。为何这一行代码不直接写为 2333 * i %100000007 呢?
因为我们知道,C 中的整型运算是封闭的,即两个 int 型数做加减乘除取余运算以后,结果仍是一个 int 型数。那么当两个比较大的整型数做乘法运算,结果可能发生溢出时,如若想保留精确的运算结果,则必须将其中一位提前转换成长整数再参与运算,也即:
voidf(int i) { g((unsigned long long)(2333)* i % (unsigned long long)(100000007ull)); }
试问这么长的表达式你是否喜欢?
同样的,对于浮点数也有类似的道理。C 中,如若直接写小数字面常量,比如 3.14,则默认是 double 类型的,有时我们不需要这么高的精度,只需要保留 float 的精度即可,那么你可以选择写成 (float)(3.14),当然也可以写作 3.14f。
至此,一切已明了。常量后缀只是对常量做强制类型转换的语法糖。
===============================
C++11 以后对这个语法规则做了扩充,不但扩充了常量前缀(和后缀是一个道理),还支持了用户自定义常量后缀。我们不妨再举一些例子。
譬如在新增的前缀中,u8'a' 可用于表示 UTF8 编码的字符;u'汉' 可用于表示 UTF-16 编码的字符,它和 (char16_t)('汉') 是一个道理。
用户自定义常量后缀里,以 chrono 库中对时长的重载最得精髓。
std::this_thread::sleep_for(10ns); // 休眠 10 纳秒 std::this_thread::sleep_for(10us); // 休眠 10 微秒 std::this_thread::sleep_for(10ms); // 休眠 10 毫秒 std::this_thread::sleep_for(10s); // 休眠 10 秒 std::this_thread::sleep_for(10min); // 休眠 10 分钟 std::this_thread::sleep_for(1h + 10min + 20s); // 休眠 1 小时 10 分钟 20 秒
其中最后一句是和
std::this_thread::sleep_for(std::chrono::hours(1) + std::chrono::minutes(10) + std::chrono::seconds(20));
是等价的,请问你喜欢哪种?
再比如,对字符串的字面量后缀重载:
std::cout << (std::string("Hello") + std::string("world")).length() << std::endl;
和
std::cout << ("Hello"s + "world"s).length() << std::endl;
比,你觉得怎么样?
最后再来一组即将到来的 C++20 中,对日期的支持:
auto date = 2019y / 8m / 7d; std::cout << "today is: " << date << std::endl;
最后再给题主一个建议,学 C/C++ 靠的不是死记硬背,不是背下了什么什么语法就是会这么语言了。你必须去理解各个语法现象背后的本质!理解不了就证明你代码写少了,多写点什么东西走过些弯路、踩过些坑自然就明白了。