C++基本数据类型及类型转换

http://blog.csdn.net/pipisorry/article/details/25346379

数据类型

什么样的数据算是byte类型,int类型,float类型,double类型,long类型?

byte类型,就是字符类型.这类数据是字符组成的
FLOAT,为数字浮点型,其小数点后面可以跟N个数字
DOUBLE,为双精度数字类型,其小数点后只能有两个数字

int类型

上面提到了在32位机器和64机器中int类型都占用4个字节。后来,查了The C Programming language这本书,里面有一句话是这样的:Each compiler is free to choose appropriate sizes for its own hardware, subject only to the restriction that shorts and ints are at least 16bits, longs are at least 32bits, and short is no longer than int, which is no longer than long.意思大致是编译器可以根据自身硬件来选择合适的大小,但是需要满足约束:short和int型至少为16位,long型至少为32位,并且short型长度不能超过int型,而int型不能超过long型。这即是说各个类型的变量长度是由编译器来决定的,而当前主流的编译器中一般是32位机器和64位机器中int型都是4个字节(例如,GCC)。

下面列举在GCC编译器下32位机器和64位机器各个类型变量所占字节数:

C类型

           32              64
    char            1               1
    short int            2               2
    int            4               4
    long int            4               8
    long long int            8               8
    char*            4               8
    float            4               4
    double            8               8

关于带符号与无符号类型:整型 int、stort  和  long 都默认为带符号型。要获得无符号型则必须制定该类型为unsigned,比如unsigned long。unsigned int类型可以简写为unsigned,也就是说,unsigned后不加其他类型说明符就意味着是unsigned int。

Note:
c语言中int类型为4bytes(64位机上,32位机应该也是),也就是说总是4bytes而不会变,不过不同语言定义的范围不同,如python中是8bytes(64位机)实际对象占用28bytes。
#include <stdio.h>
#include <limits.h>
int main()
{
    printf("The value of INT_MAX is %i\n", INT_MAX);
    printf("The value of INT_MIN is %i\n", INT_MIN);
    printf("An int takes %ld bytes\n", sizeof(int));
    return 0;
}
The value of INT_MAX is 2147483647
The value of INT_MIN is -2147483648
An int takes 4 bytes

一字节表示八位,即:1byte = 8 bit;
int: 4byte =  32 bit 有符号signed范围:2^31-1 ~ -2^31即:2147483647 ~ -2147483648        无符号unsigned范围:2^32-1 ~ 0即:4294967295 ~ 0
long: 4 byte = 32 bit 同int型
double: 8 byte = 64 bit 范围:1.79769e+308 ~ 2.22507e-308
long double: 12 byte = 96 bit 范围: 1.18973e+4932 ~ 3.3621e-4932
float: 4 byte = 32 bit 范围: 3.40282e+038 ~ 1.17549e-038
int、unsigned、long、unsigned long 、double的数量级最大都只能表示为10亿,即它们表示十进制的位数不超过10个,即可以保存所有9位整数。而short只是能表示5位。

enum类型

enum Color { red, white, blue}; 
Color x;

我们应说x是Color类型的,而不应将x理解成enumeration类型,更不应将其理解成int类型。最好的方法是将这个类型的值看成是red, white和blue。C++编译器提供了Color到int类型的转换,上面的red, white和blue的值即为0,1,2。

enum类型和int类型的转换

但是,你不应简单将blue看成是2。blue是Color类型的,可以自动转换成2,但对于C++编译器来说,并不存在int到Color的自动转换!(C编译则提供了这个转换)

Color会自动转换成int

void f(){
   Color x = red;
   Color z = blue;
 
   int n;
   n = x;   // change n to 0
   n = z;   // change n to 2}

C++编译器并不提供从int转换成Color的自动转换:
void f(){
   Color x;
   x = blue;  // change x to blue
   x = 2;     // compile-time error: can't convert int to Color} 

从int转换成Color,应提供强制类型转换:
void f(){
   Color x;
   x = red;      // change x to red
   x = Color(1); // change x to white
   x = Color(2); // change x to blue
   x = 2;        // compile-time error: can't convert int to Color

最大最小的数

FLT_MAX: 3.402823e+38
FLT_MIN: 1.175494e-38

#include "float.h"就可以直接用了

[C 标准库 – <float.h> | 菜鸟教程]

类型转换

基于最新的C++11标准<string>中已经封装好了对应的转换方法:

其它类型转换为string

标准库中定义了to_string(val);可以将其它类型转换为string

std::to_string

json转string

std::string dump_json(const JsonNode* node) {
  if (!node) {
    return "";
  }
  try {
    rapidjson::StringBuffer buffer;
    rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
    node->Accept(writer);
    return buffer.GetString();
  } catch (std::exception& e) {
    WARN("error while dumping json configuration. reason: %s", e.what());
  } catch (...) {
    WARN("error while dumping json configuration. reason unknown.");
  }
  return "";
}

string转化成int、long、double

   stoi(s,p,b);stol(s,p,b);stoul(s,p,b);stoll(s,p,b);stoull(s,p,b); 返回s的起始子串(表示整数内容的字符串)的数值(非数字开头的会抛出std::invalid_argument异常,数字开头的则会把数字部分转换),返回值的类型分别为:int、long、unsigned long、long long、unsigned long long.其中b表示转换所用的基数,默认为10(表示十进制).p是size_t的指针,用来保存s中第一个非数值字符的下标,p默认为0,即函数不返 回下标.

   stof(s, p); stod(s, p); stold(s, p); 返回s的起始子串(表示浮点数内容)的数值,返回值的类型分别是float、double、long double.参数p的作用与整数转换函数中的一样。

示例:

try {
  double score = std::stod(std::to_string(score0));
} catch (std::exception& e) {
  // pass
}

示例2:

int main(){
    string a = "123asd";
    size_t p;
    uint32_t i = std::stoull( a, &p );

    std::cout << "i=" << i << "  p=" << p << std::endl;
    return 0;
}

i=123 p=3

[c++ string与int(其他的内部类型)转换_c++ 将字符串转成int32-CSDN博客]

强制类型转换

C++将强制类型转换分为4种不同的类型,以提供更加安全可靠的转换。

[C++强制类型转换与字符类型之间的转换_c++强制类型转化字符串-CSDN博客]

static_cast类型转换

static_cast < type-id > ( expression )
该运算符把expression转换为type-id类型,但没有运行时类型检查来保证转换的安全性。

它主要有如下几种用法:
①用于类层次结构中基类(父类)和派生类(子类)之间指针或引用的转换。
进行上行转换(把派生类的指针或引用转换成基类表示)是安全的;
进行下行转换(把基类指针或引用转换成派生类表示)时,由于没有动态类型检查,所以是不安全的。
②用于基本数据类型之间的转换,如把int转换成char,把int转换成enum。这种转换的安全性也要开发人员来保证。
③把空指针转换成目标类型的空指针。
④把任何类型的表达式转换成void类型。
注意:static_cast不能转换掉expression的const、volatile、或者__unaligned属性

示例1:

double f = 100.34;
int ic1 = f;                     //方式一:隐式转换直接转
int ic1 = int(f);                //方式二:C风格的强制类型转换
int ic2 = static_cast<int>(f);   //方式三:C++风格的强制类型转换

示例2:

//This is the old way of converting a variable from its type to a double
double pi = double(a)/3;

//This is the new way of converting a variable from its type to a double
double pi = static_cast<double>(a)/3;

[In C++, what are the differences between static_cast<double>(a) and double(a)? ]

示例3:

用于基本数据类型之间的转换,如把int转换成char,把int转换成double等。
    int val = 110119;
    char c = static_cast<char>(val);
    double d = static_cast<double>(val);

Note: 但是string不是基本数据类型,且和int没有继承关系,所以不能直接使用static_cast<int>(string_a),只能用std::stoi(string_a)了吧。

C++primer第五章里写了 编译器隐式执行任何 类型转换都可由static_cast显示完成;reinterpret_cast通常为操作数的位模式提供较低层的重新解释
1、C++中的static_cast执行非 多态的转换,用于代替C中通常的转换操作。因此,被做为显式 类型转换使用。比如:
1
2
3
inti;
floatf = 166.71;
i =  static_cast< int>(f);
此时结果,i的值为166。
2、C++中的reinterpret_cast主要是将数据从一种类型的转换为另一种类型。所谓“通常为操作数的位模式提供较低层的重新解释”也就是说将数据以 二进制存在形式的重新解释。比如:
1
2
3
inti;
char*p = "This is an example.";
i =  reinterpret_cast< int>(p);
此时结果,i与p的值是完全相同的。 reinterpret_cast的作用是说将指针p的值以 二进制(位模式)的方式被解释为整型,并赋给i,//i 也是指针,整型指针;一个明显的现象是在转换前后没有数位损失。

虽然const_cast是用来去除变量的const限定,但是static_cast却不是用来去除变量的static引用。其实这是很容易理解的,static决定的是一个变量的作用域和生命周期,比如:在一个文件中将变量定义为static,则说明这个变量只能在本Package中使用;在方法中定义一个static变量,该变量在程序开始存在直到程序结束;类中定义一个static成员,该成员随类的第一个对象出现时出现,并且可以被该类的所有对象所使用。对static限定的改变必然会造成范围性的影响,而const限定的只是变量或对象自身。但无论是哪一个限定,它们都是在变量一出生(完成编译的时候)就决定了变量的特性,所以实际上都是不容许改变的。这点在const_cast那部分就已经有体现出来。

static_cast和reinterpret_cast一样,在面对const的时候都无能为力:两者都不能去除const限定。两者也存在的很多的不同,比如static_cast不仅可以用在指针和引用上,还可以用在基础数据和对象上;reinterpret_cast可以用在"没有关系"的类型之间,而用static_cast来处理的转换就需要两者具有"一定的关系"了。reinterpret_cast可以在任意指针之间进行互相转换,即使这些指针所指的内容是毫无关系的,也就是说一下语句,编译器是不会报错的,但是对于程序来说也是毫无意义可言的,只会造成程序崩溃

unsignedshort Hash( void *p ) {

unsignedlong val = reinterpret_cast<unsignedlong>( p );

return ( unsigned short )( val ^ (val >> 16));

}

int main() {

typedefunsignedshort (*FuncPointer)( void *) ;

FuncPointer fp = Hash; //right,this is what we want

int a[10];constint* ch = a; //right, array is just like pointer

char chArray[4] = {'a','b','c','d'};

fp = reinterpret_cast<FuncPointer> (ch); //no error, but does not make sense

ch = reinterpret_cast<int*> (chArray); //no error

cout <<hex<< *ch; //output: 64636261 //it really reinterpret the pointer

}

而以上转换,都是static_cast所不能完成的任务,也就是说把上边程序里所有的reinterpret_cast换成static_cast的话,就会立即得到编译错误,因为目标指针和原始指针之间不存在"关系"

从上边的程序,也就一下子看出来了reinterpret_cast和static_cast之间最本质的区别。

但是从基类到子类的转换,用static_cast并不是安全的,具体的问题会在dynamic_cast一篇阐述。

在指针和引用方便,似乎也只有继承关系是可以被static_cast接受的,其他情况的指针和引用转换都会被static_cast直接扔出编译错误,而这层关系上的转换又几乎都可以被dynamic_cast所代替。这样看起来static_cast运算符的作用就太小了。

实际上static_cast真正用处并不在指针和引用上,而在基础类型和对象的转换上 。 而基于基础类型和对象的转换都是其他三个转换运算符所办不到的

from: C++基本数据类型及类型转换_unsigned short转float-CSDN博客

ref: 

  • 10
    点赞
  • 87
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值