【理論實踐】size_t和std:size_t可能是不同的類型定義,只是定義爲相同的類型

這個很少被人意識到,2個分別對應到c頭文件定義和c++頭文件定義,日常使用沒有影響是因爲先包含的會使後續包含定義觸發條件編譯,而且經常using namespace std;使不區分std:size_t。做爲一個優秀的代碼輸出者,要嚴謹的弄清楚,有針對性的處理,提高代碼質量,降低代碼開發週期。


結論:c和C++混編,尤其是跨平臺時,一定要注意頭文件包含順序,如果是c++,最早的包含c++的頭文件,如果是c,則晚一些包含c++頭文件,這是有差異的,不保證完全等價。


第一部分,影響:

對於業務邏輯,包括typeid等,都沒有影響,因爲條件編譯是預處理階段完成,編譯階段面對的已經是基礎類型定義。

但是,畢竟兩個文件是獨立的,在跨平臺編譯等情況下,類型定義僅爲了保證長度相等,兩個文件可能會產生定義差異,導致類型不匹配,比如

#include <iostream>
#include <typeinfo>
using namespace std;

typedef long long  type1;
typedef int64_t type2;

int main()
{
        type1 s1 = 0;
        type2 s2 = 0;
        cout << sizeof(type1) << " " << sizeof(type2) << endl;
        cout << (typeid(s1) == typeid(s2) ? "eq" : "nq") << endl;
        cout << typeid(s1).name() << endl;
        cout << typeid(s2).name() << endl;
        return 0;
}
輸出
8 8
nq
x
l

這與邏輯是對不上的,位長一樣,符號一樣,卻是不同的類型。


第二部分,驗證一下區別,通過將size_t重定義產生衝突報錯來查看定義源

#include <stdio.h>
typedef bool size_t;
int main()
{
                return 0;
}

編譯報錯:

main.cpp:3:14: error: conflicting declaration ‘typedef bool size_t’
 typedef bool size_t;
              ^
In file included from /usr/include/stdio.h:34:0,
                 from main.cpp:1:
/opt/rh/devtoolset-2/root/usr/lib/gcc/x86_64-redhat-linux/4.8.2/include/stddef.h:212:23: error: ‘size_t’ has a previous declaration as ‘typedef long unsigned int size_ ’
 typedef __SIZE_TYPE__ size_t;
                       ^
make: *** [main] Error 1
繼續追蹤:
/opt/rh/devtoolset-2/root/usr/lib/gcc/x86_64-redhat-linux/4.8.2/include/stddef.h:209:#define __SIZE_TYPE__ long unsigned int

所以C頭文件定義是:long unsigned int


再來看一下c++定義

#include <iostream>
using namespace std;
namespace std
{
        typedef bool size_t;
}
int main()
{
        return 0;
}
編譯報錯
main.cpp:7:15: error: conflicting declaration ‘typedef bool std::size_t’
  typedef bool size_t;
               ^
In file included from /opt/rh/devtoolset-2/root/usr/include/c++/4.8.2/iostream:38:0,
                 from main.cpp:2:
/opt/rh/devtoolset-2/root/usr/include/c++/4.8.2/x86_64-redhat-linux/bits/c++config.h:1857:26: error: ‘std::size_t’ has a previous declaration as ‘typedef long unsigned int std::size_t’
   typedef __SIZE_TYPE__  size_t;
                          ^
make: *** [main] Error 1
進一步追蹤:
bits/c++config.h:1764 if __cplusplus
...
bits/c++config.h:1855 namespace std
{
          typedef __SIZE_TYPE__     size_t;
            typedef __PTRDIFF_TYPE__  ptrdiff_t;


#if __cplusplus >= 201103L
                  typedef decltype(nullptr) nullptr_t;
#endif

}

這個做法非常聰明,直接使用了系統的__SIZE_TYPE__,所以必然和C一致


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章