Integral类型的跨平台使用

fundamental integral types or extended integral types

我们先通过下图,来了解可以跨平台使用的整数类型:

之所以我们需要以上各种明确指定宽度的int类型是因为int类型本身比较特殊,其具体的字节数同机器字长和编译器有关(标准并没有规定其具体所占的字节数)。

因此如果要保证移植性,我们应该尽量使用上图中带宽度的int类型。这种数据类型在所有平台下都分配相同的字节,因此在移植上不存在问题。

需要注意的问题

我们以整数类型int64_t为例来说明。我们都知道,int64_t用来表示64位整数,在32位系统中是long long int,在64位系统中是long int,所以打印int64_t的格式化方法如下:

printf("%ld" , value);  // 64bit OS
printf("%lld", value);  // 32bit OS

那么这样在32位系统和64位系统中,编译相同的代码,就有可能会出错。跨平台的方法是使用PRId64来格式化输出,如下:

#ifndef __STDC_FORMAT_MACROS
#define __STDC_FORMAT_MACROS
#endif

#include <inttypes.h>

printf("%" PRId64 "\n", value);

具体可以参看下图:

注意:上述宏定义针对C语言,如果C++需要使用PRId64等宏,需要定义一个__STDC_FORMAT_MACROS宏显示打开它。具体可以参见/usr/include/inttypes.h中宏__STDC_FORMAT_MACROS的定义,如下:

/* The ISO C99 standard specifies that these macros must only be
   defined if explicitly requested.  */
#if !defined __cplusplus || defined __STDC_FORMAT_MACROS  

# if __WORDSIZE == 64
#  define __PRI64_PREFIX    "l"
#  define __PRIPTR_PREFIX   "l"
# else
#  define __PRI64_PREFIX    "ll"
#  define __PRIPTR_PREFIX
# endif  

/* Macros for printing format specifiers.  */  

/* Decimal notation.  */
# define PRId8      "d"
# define PRId16     "d"
# define PRId32     "d"
# define PRId64     __PRI64_PREFIX "d"

举例

MUDUO开源库中也使用了上文所提到的方式,源码如下:

#include <muduo/base/Timestamp.h>

#include <sys/time.h>
#include <stdio.h>

#ifndef __STDC_FORMAT_MACROS
#define __STDC_FORMAT_MACROS
#endif

#include <inttypes.h>

#include <boost/static_assert.hpp>

using namespace muduo;

BOOST_STATIC_ASSERT(sizeof(Timestamp) == sizeof(int64_t));

Timestamp::Timestamp(int64_t microseconds)
  : microSecondsSinceEpoch_(microseconds)
{
}

string Timestamp::toString() const
{
  char buf[32] = {0};
  int64_t seconds = microSecondsSinceEpoch_ / kMicroSecondsPerSecond;
  int64_t microseconds = microSecondsSinceEpoch_ % kMicroSecondsPerSecond;
  snprintf(buf, sizeof(buf)-1, "%" PRId64 ".%06" PRId64 "", seconds, microseconds);
  return buf;
}

string Timestamp::toFormattedString(bool showMicroseconds) const
{
  char buf[32] = {0};
  time_t seconds = static_cast<time_t>(microSecondsSinceEpoch_ / kMicroSecondsPerSecond);
  struct tm tm_time;
  gmtime_r(&seconds, &tm_time);

  if (showMicroseconds)
  {
    int microseconds = static_cast<int>(microSecondsSinceEpoch_ % kMicroSecondsPerSecond);
    snprintf(buf, sizeof(buf), "%4d%02d%02d %02d:%02d:%02d.%06d",
             tm_time.tm_year + 1900, tm_time.tm_mon + 1, tm_time.tm_mday,
             tm_time.tm_hour, tm_time.tm_min, tm_time.tm_sec,
             microseconds);
  }
  else
  {
    snprintf(buf, sizeof(buf), "%4d%02d%02d %02d:%02d:%02d",
             tm_time.tm_year + 1900, tm_time.tm_mon + 1, tm_time.tm_mday,
             tm_time.tm_hour, tm_time.tm_min, tm_time.tm_sec);
  }
  return buf;
}

Timestamp Timestamp::now()
{
  struct timeval tv;
  gettimeofday(&tv, NULL);
  int64_t seconds = tv.tv_sec;
  return Timestamp(seconds * kMicroSecondsPerSecond + tv.tv_usec);
}

Timestamp Timestamp::invalid()
{
  return Timestamp();
}

说明

对于支持C++11标准的编译器,不用添加宏__STDC_FORMAT_MACROS,也可以直接编译通过。

参考文献

1. http://www.cplusplus.com/reference/cinttypes/?kw=inttypes.h

2. http://www.cprogramdevelop.com/4787258/

3. https://github.com/chenshuo/muduo/blob/master/muduo/base/Timestamp.cc

时间: 2024-10-14 13:35:02

Integral类型的跨平台使用的相关文章

(3)风色从零单排《C++ Primer》 重要的基本类型

从零单排<C++ Primer> --(3)重要的基本类型    算数类型(Arithmetic Types) c++算数类型 Type Meaning Minimum Size bool boolean NA char character 8 bits wchar_t wide character 16 bits char16_t Unicode character 16 bits char32_t Unicode character 32 bits short short integer

04-Integral类型数据

Integral类型: 1,整型(不可变类型)int    123456,93524359324,    转换方法:int() 可用类 -计算一个整数转换为二进制后所需的最小位数 .bit_length() a = 1 print(a.bit_length()) b = 8 print(b.bit_length()) c = 128 print(c.bit_length()) 输出结果: 1 4 8 -转换为字节类型,用指定位数的字节来表示 .to_bytes(位长n, byteorder='b

C++primer读书笔记9转换与类类型

有时候指定了自己类类型来表示某种类型数据如SmallInt,那么为了方便计算就会指定一个转换操作符,将该类类型在某种情况下自动的转换为指定的类型 <1>转换操作符 operator type(); 转换函数必须是类成员函数,不能指定返回类型,并且形参列表必须为空,并且通常不应该改变转换对象,所以操作符通常定义为const成员. #include <iostream> using namespace std; class SmallInt { public: SmallInt(int

第19课 类型萃取(3)_类型选择的traits

1. std::conditional (1)原型:template <bool Cond, class T, class F> struct conditional; //根据条件获取T或F类型 template<bool Cond, class T, class F> //泛化 struct conditional { typedef T type; }; template<class T, class F> //偏特化 struct conditional<

关于js的一些基础随笔

JS基础 01. js API:别人准备好的东西,我们负责使用. 能够独立写出所有代码. 五天之后说有代码从新写一遍. 十天过后提问. 问题用red标出 02. js分为三部分.语法.注释(总结).异步以及同步(简单介绍).交换两个变量量的值. 命名规范必须遵守.类型转换.运算符.流程控制. 重点 03. 快捷键  等待添加 04. 浏览器 五大浏览器:chrome.firefox.safari.ie(*).opera. 浏览器兼容问题(important) 测试只测试这五个(chrome.fi

Python 二、Python过程型程序设计快速入门

一.数据结构 程序=数据结构+算法 数据结构: 通过某种方式(例如对元素进行编号)组织在一起的数据元素的集合,这些数据元素可以是数字或者字符,甚至可以是其它的数据结构. python的最基本数据结构是序列 序列中的每个元素被分配一个序号(即元素的位置),也陈为索引:索引从0开始编号 python包含6中内建的数据序列:列表.元祖.字符串.Unicode字符串.buff对象和xrange对象 二.python的关键要素 基本数据类型 对象引用 组合数据类型 逻辑操作符 控制流语句 算术操作符 输入

什么是Python?

Python(大蟒蛇)是一门解释型.面向对象.带有动态语义的高级程序设计语言. 在于1989年,由一位名叫Guido van Rossum(吉多.范罗苏姆),为打发时间设计了Python语言,第一个发行版公开于1991年. Python是一款纯粹的自由软件,源代码和解释器CPython都遵循了GPL(GNU General Public License)协议. Python语法清晰简洁,最有特色的是用空白符作为语句的缩进. Python具有强大而丰富的类库,也经常被别人说是胶水语言,可以跟其它语

Nginx+Tomcat群集服务

一.简介 Tomcat是Apache 软件基金会(Apache SoftwareFoundation)的Jakarta 项目中的一个核心项目,由Apache.Sun 和其他一些公司及个人共同开发而成.由于有了Sun 的参与和支持,最新的Servlet 和JSP 规范总是能在Tomcat 中得到体现,Tomcat 5支持最新的Servlet 2.4 和JSP 2.0 规范.因为Tomcat 技术先进.性能稳定,而且免费,因而深受Java 爱好者的喜爱并得到了部分软件开发商的认可,成为目前比较流行的

2015.9.29-数据存取(SQLite)

SQLite 主流嵌入式关系数据库:轻量级,跨平台 基于C语言,在ios中需要用C语言进行数据库操作 采用动态数据类型,即使创建时定义了一种类型,在实际操作时也可以 存储其他类型,推荐建库时使用合适的类型(跨平台) 建立连接后通常不需要关闭连接(可以手动关闭) 使用SQLite步骤,先在项目中导入libsqlite3框架 1.打开库:sqlite3_open(),指定一个数据库文件保存路径,如果文件存在就直接打开,否则就创建然后打开,得到一个sqlite3类型的对象 2.执行sql语句 3.如果