如何在C中编译时打印sizeof()的结果?

问题描述 投票:36回答:9

如何在C中编译时打印sizeof()的结果?

现在我使用静态断言(基于其他Web资源自制)来将sizeof()结果与各种常量进行比较。虽然这有效但它远非优雅或快速。我还可以创建变量/ struct的实例并查看映射文件,但这比直接调用/命令/运算符更不优雅和快速。此外,这是一个使用多个交叉编译器的嵌入式项目......因此,为目标构建和加载示例程序然后读出一个值比上述任何一个都更麻烦。

在我的情况下(旧的GCC),#warning sizeof(MyStruct)在打印警告之前实际上并不解释sizeof()。

c sizeof compile-time
9个回答
51
投票

当我偶然发现这个时,我正在寻找类似的功能:

Is it possible to print out the size of a C++ class at compile-time?

这给了我这个想法:

char (*__kaboom)[sizeof( YourTypeHere )] = 1;

这导致VS2015中出现以下警告:

warning C4047: 'initializing': 'DWORD (*)[88]' differs in levels of indirection from 'int'

在这种情况下,88将是您正在寻找的大小。

超级hacky,但它的确如此。可能要晚了几年,但希望这对某人有用。

我还没有机会尝试使用gcc或clang,但是如果有人在我之前没有达到它,我会尝试确认它是否有效。

编辑:为clang 3.6开箱即用

我可以为GCC工作的唯一技巧是滥用-Wformat并让宏定义如下函数:

void kaboom_print( void )
{
    printf( "%d", __kaboom );
}

哪个会给你一个警告:

...blah blah blah... argument 2 has type 'char (*)[88]'

比原始建议稍微粗略一点,但也许有人知道更好的gcc可以想到更好的警告滥用。


6
投票

所有你需要的是一个技巧,导致编译器抱怨一些编译时整数值被错误地使用,如重复的case常量:

struct X {
    int a,b;
    int c[10];
};
int _tmain(int argc, _TCHAR* argv[])
{
    int dummy;

    switch (dummy) {
    case sizeof(X):
    case sizeof(X):
        break;
    }
    return 0;
}

------构建开始:项目:cpptest,配置:调试Win32 ------ cpptest.cpp c:\ work \ cpptest \ cpptest \ cpptest.cpp(29):错误C2196:大小写值'48'已经使用==========构建:0成功,1失败,0最新,0跳过==========

所以struct X的大小是48


5
投票

还有一种方法(实际上有效):

char __foo[sizeof(MyStruct) + 1] = {[sizeof(MyStruct)] = ""};

适用于old'ish gcc 5.x.产生如下错误:

a.c:8:54: error: initializer element is not computable at load time
a.c:8:54: note: (near initialization for 'a[8]')

附:显然,这个是(非常)gcc特定的。所有其他方法都不适合我。


2
投票

以下方式适用于GCC,Clang,MSVC等,即使在旧版本中,也是基于函数参数从指针到数组到标量类型的转换失败。编译器会打印数组的大小,因此您可以从输出中获取值。适用于C和C ++模式。

找出sizeof(long)play with it online)的示例代码:

char checker(int);
char checkSizeOfInt[sizeof(long)]={checker(&checkSizeOfInt)};

相关产出的例子:

  • GCC 4.4.7

<source>:1: note: expected 'int' but argument is of type 'char (*)[8]'

  • 铿锵3.0.0

<source>:1:6: note: candidate function not viable: no known conversion from 'char (*)[8]' to 'int' for 1st argument;

  • MSVC 19.14

<source>(2): warning C4047: 'function': 'int' differs in levels of indirection from 'char (*)[4]'


0
投票

我偶然发现了一个类似于Bakhazardgreat solution的解决方案,而且这个解决方案会产生一个不那么详细的警告,所以你可能会发现它很有用:

char (*__fail)(void)[sizeof(uint64_t)] = 1;

这会产生错误消息

Function cannot return array type 'char [8]'

这是使用最新版本的clang(1)测试的。


0
投票

我的gcc C编译器拒绝使用上述任何解决方案打印大小。我将逻辑反转为注入编译器警告的大小不是。

enum e
{
    X = sizeof(struct mystruct)
};

void foo()
{
    static enum e ev;

    switch (ev)
    {
    case 0:
    case 4:
    case 8:
    case 12:
    case 16:
    case 20:
        break;
    }
}

然后我必须查看丢失号码的警告。

warning: case value '0' not in enumerated type 'e' [-Wswitch]
warning: case value '4' not in enumerated type 'e' [-Wswitch]
warning: case value '12' not in enumerated type 'e' [-Wswitch]
warning: case value '16' not in enumerated type 'e' [-Wswitch]
warning: case value '20' not in enumerated type 'e' [-Wswitch]

那么我的结构大小是8。

我的包装是4。

嗯......这是一个选择。


0
投票

虽然这不完全在编译时,但它在运行时之前,所以它仍然可能与某些人相关。

您可以像这样定义一个数组:

uint8_t __some_distinct_name[sizeof(YourTypeHere)];

然后,在编译之后,从目标文件中获取大小:

$ nm -td -S your_object_file |       # list symbols and their sizes, in decimal
  grep ' __some_distinct_name$' |    # select the right one
  cut -d' ' -f2 |                    # grab the size field
  xargs printf "Your type is %d B\n" # print

0
投票

@jws好主意! Howewer,sizeof(xxx)是一个常量表达式(VLA,https://en.cppreference.com/w/c/language/sizeof除外),因此sizeof运算符应该在选择的情况下工作:

enum e1 {dummy=-1};
enum e1 ev;
switch (ev) {
    case sizeof(myType):;
    break;
    default:;
}

..它在我的GCC中工作:“.. \ WinThreads.c:18:9:警告:案例值'4'不在枚举类型'enum e1'[--Wswitch]”


-4
投票

你不能这样做,不能用结构。在编译发生之前调用预处理器,因此甚至没有结构的概念;你不能评估不存在/未定义的东西的大小。预处理器会对转换单元进行标记,但它只是为了定位宏调用。

最接近的是依靠一些实现定义的宏来评估内置类型的大小。在gcc中,您可以找到以下内容:

gcc -dM -E - </dev/null | grep -i size

在我的系统中打印:

#define __SIZE_MAX__ 18446744073709551615UL
#define __SIZEOF_INT__ 4
#define __SIZEOF_POINTER__ 8
#define __SIZEOF_LONG__ 8
#define __SIZEOF_LONG_DOUBLE__ 16
#define __SIZEOF_SIZE_T__ 8
#define __SIZEOF_WINT_T__ 4
#define __SIZE_TYPE__ long unsigned int
#define __SIZEOF_PTRDIFF_T__ 8
#define __SIZEOF_FLOAT__ 4
#define __SIZEOF_SHORT__ 2
#define __SIZEOF_INT128__ 16
#define __SIZEOF_WCHAR_T__ 4
#define __SIZEOF_DOUBLE__ 8
#define __SIZEOF_LONG_LONG__ 8

在没有编写程序并执行它的情况下,您无法知道自定义结构的大小。

© www.soinside.com 2019 - 2024. All rights reserved.