int64_t 在 32 位环境下其实是 long long

这里说的类型长度指的是相同类型在不同环境下长度不一致的情况,下面总结表格:

由于这里出现了 32 位和 64 位环境下长度不一致的情况,C 语言特意提供了 stdint.h 头文件 (C++ 中在 cstddef 中引用),定义了定长类型,例如 int64_t 在 32 位环境下其实是 long long,而在 64 位环境下其实是 long。

但这里的问题点在于:

  • 并没有定长格式符

例如 uint64_t 在 32 位环境下对应的格式符是 % llu,但是在 64 位环境下对应的格式符是 % lu。有一种折中的解决办法是自定义一个宏:

#if(sizeof(void*) == 8)
#define u64 "%lu"
#else
#define u64 "%llu"
#endif

void demo() {
  uint64_t a;
  printf("a="u64, a);
}

但这样会让字符串字面量从中间断开,非常不直观。

  • 类型不一致

例如在 64 位环境下,long 和 long long 都是 64 位长,但编译器会识别为不同类型,在一些类型推导的场景会出现和预期不一致的情况,例如:

template <typename T>
void func(T t) {}

template <>
void func<int64_t>(int64_t t) {}

void demo() {
  long long a;
  func(a); // 会匹配通用模板,而匹配不到特例
}

上述例子表明,func<int64_t> 和 func<long long > 是不同实例,尽管在 64 位环境下 long 和 long long 真的看不出什么区别,但是编译器就是会识别成不同类型。

格式化字符串

格式化字符串算是非常经典的 C 的产物,不仅是 C++,非常多的语言都是支持这种格式符的,例如 java、Go、python 等等。

但 C++ 中的格式化字符串可以说完全就是 C 的那一套,根本没有任何扩展。换句话说,除了基本数据类型和 0 结尾的字符串以外,其他任何类型都没有用于匹配的格式符。

例如,对于结构体类型、数组、元组类型等等,都没法匹配到格式符:

struct Point {
  double x, y;
};

void Demo() {
  // 打印Point
  Point p {1, 2.5};
  printf("(%lf,%lf)", p.x, p.y); // 无法直接打印p
  // 打印数组
  int arr[] = {1, 2, 3};
  for (int i = 0; i < 3; i++) {
    printf("%d, ", arr[i]); // 无法直接打印整个数组
  } 
  // 打印元组
  std::tuple tu(1, 2.5, "abc");
  printf("(%d,%lf,%s)", std::get<0>(tu), std::get<1>(tu), std::get<2>(tu)); // 无法直接打印整个元组
}

对于这些组合类型,我们就不得不手动去访问内部成员,或者用循环访问,非常不方便。

针对于字符串,还会有一个严重的潜在问题,比如:

std::string str = "abc";
str.push_back('\0');
str.append("abc");

char buf[32];
sprintf(buf, "str=%s", str.c_str());

由于 str 中出现了 '\0',如果用 % s 格式符来匹配的话,会在 0 的位置截断,也就是说 buf 其实只获取到了 str 中的第一个 abc,第二个 abc 就被丢失了。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值