该类型std::size_t是一个无符号类型,可以存储任何类型的理论上可能的对象的最大大小,并且std::ptrdiff_t是一个可以保存两个指针差异的有符号类型(这是另一种说法应该是数组的标准整数的方式在C++中索引).C++标准库已决定std::size_t用于数组索引,但通常认为这std::ptrdiff_t是一个更好的选择.哪一个是最好的是一个长期的辩论,我不想进入这里,但我一直认为第二个是第一个的未签名版本.在macOS上运行此程序
#include <cstddef>
#include <cstdio>
void f(int n) { std::printf("int"); };
void f(long n) { std::printf("long"); };
void f(long long n) { std::printf("long long"); };
void f(unsigned int n) { std::printf("unsigned int"); };
void f(unsigned long n) { std::printf("unsigned long"); };
void f(unsigned long long n) { std::printf("unsigned long long"); };
int main() {
const std::ptrdiff_t n_ptrdiff = 0;
const std::size_t n_size = 0;
std::printf("std::ptrdiff_t is an alias for ");
f(n_ptrdiff);
std::printf("\n");
std::printf("std::size_t is an alias for ");
f(n_size);
std::printf("\n");
return 0;
}
Run Code Online (Sandbox Code Playgroud)
在64位平台上,但编译为32位:
clang++ -m32 -std=c++11 type.cpp -o type-32-clang
Run Code Online (Sandbox Code Playgroud)
给我以下结果:
std::ptrdiff_t is an alias for int
std::size_t is an alias for unsigned long
Run Code Online (Sandbox Code Playgroud)
在这种情况下std::size_t,std::ptrdiff_t即使它们具有相同的存储大小(4个字节),也不是未签名的版本.虽然它符合标准,但对我来说似乎很奇怪.
有谁知道这个选择的理由?
小智 8
TL; DR:为了与其他系统兼容,为了与其他系统兼容,这样做等等.
铛通常不得不signed long和unsigned long用于ptrdiff_t和size_t您预期的那样,但承诺"固定在苹果达尔文gcc和铛之间存在一些差异/ X86-32"变ptrdiff_t到signed int了与海湾合作委员会的兼容性.你不能让clang和gcc使用相同的C++库,如果他们不同意这些基本的typedef.
GCC使用unsigned long的size_t,但signed int对于ptrdiff_t因为这是苹果贡献:提交"添加达尔文(Mac OS X的内核)的原生支持." 显示在gcc/config/darwin.h:
Run Code Online (Sandbox Code Playgroud)/* Target definitions for Darwin (Mac OS X) systems. Copyright (C) 1989, 1990, 1991, 1992, 1993, 2000, 2001 Free Software Foundation, Inc. Contributed by Apple Computer Inc. [...] /* The string value for __SIZE_TYPE__. */ #ifndef SIZE_TYPE #define SIZE_TYPE "long unsigned int" #endif /* Type used for ptrdiff_t, as a string used in a declaration. */ #undef PTRDIFF_TYPE #define PTRDIFF_TYPE "int"
无特殊原因被提及,但这个文件不是针对任何处理器类型,它适用于所有Darwin系统,并提交也触动gcc/config/rs6000/rs6000.h,使其成为可能,这是与兼容是,把它回到1995年提交的"添加初步的V.4和eABI支持." :
Run Code Online (Sandbox Code Playgroud)/* Type used for ptrdiff_t, as a string used in a declaration. */ #undef PTRDIFF_TYPE #define PTRDIFF_TYPE "int"
由于这不会重新定义SIZE_TYPE,因此保留默认值"unsigned long".
GCC不是系统的编译器这个平台,所以这反过来很可能与IBM的编译器的兼容性.这似乎得到以下支持gcc/config/rs6000/aix43.h:
Run Code Online (Sandbox Code Playgroud)/* AIX 4.3 typedefs ptrdiff_t as "long" while earlier releases used "int". */ #undef PTRDIFF_TYPE #define PTRDIFF_TYPE "long int"
由于AIX的历史不公开,因此可能不会再发生这种情况.