在不编译和执行代码的情况下找到类型大小的最简单方法是什么?

我写了一个bash脚本来确定gcc的数据类型的大小(例如./sizeof int double输出intdouble的相应大小),方法是将它的每个参数包装在下面的P()宏中,然后编译并运行代码。

 #define P(x) printf("sizeof(" #x ") = %u\n", (unsigned int)sizeof(x)) 

问题是这是相对慢的(需要一整秒!),特别是链接步骤(因为用-c-S编译几乎没有时间,运行输出的二进制也是如此)。 一秒钟本身并不是那么慢,但如果我在其他脚本中使用这个脚本,它会加起来。

是否有更快,更简单的方法来找出gcc用于数据类型的大小?

您只能使用GCC的预处理器来实现标准类型的function。 对于标准类型,有预定义的宏:

 __SIZEOF_INT__ __SIZEOF_LONG__ __SIZEOF_LONG_LONG__ __SIZEOF_SHORT__ __SIZEOF_POINTER__ __SIZEOF_FLOAT__ __SIZEOF_DOUBLE__ __SIZEOF_LONG_DOUBLE__ __SIZEOF_SIZE_T__ __SIZEOF_WCHAR_T__ __SIZEOF_WINT_T__ __SIZEOF_PTRDIFF_T__ 

因此,通过使用如下代码:

 #define TYPE_TO_CHECK __SIZEOF_INT__ #define VAL_TO_STRING(x) #x #define V_TO_S(x) VAL_TO_STRING(x) #pragma message V_TO_S(TYPE_TO_CHECK) #error "terminate" 

您甚至无需启动编译就可以从预处理器本身获取__SIZEOF_INT__的值。 在您的脚本中,您可以将TYPE_TO_CHECK (带-D )定义为您需要的任何内容并将其传递给gcc。 当然你会得到一些垃圾输出,但我相信你可以解决这个问题。

您可以使用autoconf (请参阅: AC_COMPUTE_INT )使用的“负数组大小”技巧。 这样,您就不需要链接或执行代码。 因此,它也适用于交叉编译。 例如,

 int n[1 - 2 * !(sizeof(double) == 8)]; 

无法编译if: sizeof(double) != 8

缺点是,您可能必须在命令行中传递-DCHECK_SIZE=8或类似的内容,因为它可能需要多次传递才能检测到exception值。 所以,我不确定这一般是否会更快 – 但你可能能够利用它。

编辑:如果你只使用gcc,我认为@ wintermute的评论可能是最好的解决方案。

这有三种可能的解决方案。

第一个将适用于任何大小小于256的类型。在我的系统上,它需要大约0.04秒(因为它不需要除基本运行时之外的头或库)。 一个缺点是它一次只能做一个,因为输出通道的尺寸很小。 另一个问题是它不能补偿某些系统上的慢速链接(特别是MinGW):

 howbig() { gcc -xc - <<<'int main() { return sizeof ('$*'); }' && ./a.out echo $? } $ time howbig "struct { char c; union { double d; int i[3];};}" 24 real 0m0.041s user 0m0.031s sys 0m0.014s $ time howbig unsigned long long 8 real 0m0.044s user 0m0.035s sys 0m0.009s 

如果你想能够做更大的类型,你可以一次获得一个字节的大小,代价是几厘秒:

 howbig2 () { gcc -xc - <<< 'int main(int c,char**v) { return sizeof ('$*')>>(8*(**++v&3)); }' && echo $((0x$(printf %02x $(./a.out 3;echo $?) $(./a.out 2;echo $?) \ $(./a.out 1;echo $?) $(./a.out 0;echo $?)) )) } $ time howbig2 struct '{double d; long long u[12];}([973])' 101192 real 0m0.054s user 0m0.036s sys 0m0.019s 

如果您正在为x86进行编译,以下内容可能会起作用,尽管我无法在各种体系结构和平台上对其进行彻底测试。 它通过分析编译的程序集输出来避免链接步骤(例如,MinGW上的速度非常慢)。 (分析编译对象二进制文件可能会稍微强一些,但我担心MinGW上的binutils也很慢。)即使在Ubuntu上,它也要快得多:

 howbig3 () { gcc -S -o - -xc - <<< 'int hb(void) { return sizeof ('$*'); }' | awk '$1~/movl/&&$3=="%eax"{print substr($2,2,length($2)-2)}' } $ time howbig3 struct '{double d; long long u[12];}([973])' 101192 real 0m0.020s user 0m0.017s sys 0m0.004s