C++基本資料型別及型別轉換

-柚子皮-發表於2014-05-09

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

c++基本資料型別

什麼樣的資料算是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位。


c++型別轉換

1. c++中string到int的轉換

1) 在C標準庫裡面,使用atoi:

#include <cstdlib> 
#include <string>

std::string text = "152"; 
int number = std::atoi( text.c_str() ); 
if (errno == ERANGE) //可能是std::errno 

 //number可能由於過大或過小而不能完全儲存 

else if (errno == ????) 
//可能是EINVAL 

 //不能轉換成一個數字 
}

2) 在C++標準庫裡面,使用stringstream:(stringstream 可以用於各種資料型別之間的轉換)

#include <sstream> 
#include <string>

std::string text = "152"; 
int number; 
std::stringstream ss;


ss << text;//可以是其他資料型別
ss >> number; //string -> int
if (! ss.good()) 

//錯誤發生 
}

ss << number;// int->string
string str = ss.str(); 
if (! ss.good()) 

 //錯誤發生 
}

3) 在Boost庫裡面,使用lexical_cast:

#include <boost/lexical_cast.hpp> 
#include <string>

try 

 std::string text = "152"; 
 int number = boost::lexical_cast< int >( text ); 

catch( const boost::bad_lexical_cast & ) 

 //轉換失敗 
}                      

[如何將字串轉換int64_t]

int轉換成string

c++中將輸入的數字以字元(串)形式輸出

  1. #include <iostream>  
  2. #include <sstream>  
  3. #include <string>  
  4. using namespace std;  
  5.   
  6. void main(){  
  7.     int i = 65;   
  8.     cout<<char(i)<<endl;                    //輸出‘A' <=>printf("%c\n", i);  
  9.   
  10.     stringstream ss;  
  11.     ss<<i;  
  12.     string s;  
  13.     ss>>s;  
  14.     cout<<s<<endl;                      //輸出”65“  
  15.       
  16.     char *c = new char;  
  17.     itoa(65, c, 10);  
  18.     cout<<c<<endl;                      //輸出”65“  
  19.     //cout<<strcmp(c, "65")<<endl;    
  20. }  
[http://bbs.csdn.net/topics/390401758?page=1#post-394058528]


2.string 轉 CString

CString.format(”%s”, string.c_str());
用c_str()確實比data()要好;

3.char 轉 CString

CString.format(”%s”, char*);

4.char 轉 string

string s(char *);
只能初始化,在不是初始化的地方最好還是用assign().

5.string 轉 char *

char *p = string.c_str();

6.CString 轉 string

string s(CString.GetBuffer());
GetBuffer()後一定要ReleaseBuffer(),否則就沒有釋放緩衝區所佔的空間.

7.字串的內容轉換為字元陣列和C—string

(1)  data(),返回沒有”\0“的字串陣列
(2)  c_str(),返回有”\0“的字串陣列
(3)  copy()

8.CString與int、char*、char[100]之間的轉換

(1) CString互轉int

將字元轉換為整數,可以使用atoi、_atoi64或atol。而將數字轉換為CString變數,可以使用CString的Format函式。如
CString s;
int i = 64;
s.Format(”%d”, i)
Format函式的功能很強,值得你研究一下。

void CStrDlg::OnButton1()
{
   CString
   ss=”1212.12″;
   int temp=atoi(ss);
   CString aa;
   aa.Format(”%d”,temp);
   AfxMessageBox(”var is ” + aa);
}

(2) CString互轉char*

///char * TO cstring
CString strtest;
char * charpoint;
charpoint=”give string a value”; //?
strtest=charpoint;

///cstring TO char *
charpoint=strtest.GetBuffer(strtest.GetLength());

(3) char *轉成CString

標準C裡沒有string,char *==char []==string, 可以用CString.Format(”%s”,char *)這個方法來將char *轉成CString。
    要把CString轉成char *,用操作符(LPCSTR)CString就可以了。
    CString轉換 char[100]
   char a[100];
   CString str(”aaaaaa”);
   strncpy(a,(LPCTSTR)str,sizeof(a));


static_cast型別轉換

static_cast < type-id > ( expression )

該運算子把expression轉換為type-id型別,但沒有執行時型別檢查來保證轉換的安全性。它主要有如下幾種用法:
①用於類層次結構中基類(父類)和派生類(子類)之間指標或引用的轉換。
進行上行轉換(把派生類的指標或引用轉換成基類表示)是安全的;
進行下行轉換(把基類指標或引用轉換成派生類表示)時,由於沒有動態型別檢查,所以是不安全的。
②用於基本資料型別之間的轉換,如把int轉換成char,把int轉換成enum。這種轉換的安全性也要開發人員來保證。
③把空指標轉換成目標型別的空指標。
④把任何型別的表示式轉換成void型別。

注意:static_cast不能轉換掉expression的const、volatile、或者__unaligned屬性。

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: http://blog.csdn.net/pipisorry/article/details/25346379

ref: 

相關文章