如何在C中的编译时打印sizeof()的结果?
如何在C中的编译时打印sizeof()的结果 现在,我使用静态断言(基于其他web资源自制)将sizeof()结果与各种常量进行比较。虽然这有效。。。它既不优雅也不快速。我还可以创建变量/struct的实例并查看映射文件,但这也不如直接调用/command/operator优雅和快速。此外,这是一个使用多个交叉编译器的嵌入式项目。。。因此,构建一个示例程序并将其加载到目标中,然后读取一个值,这比上述两种方法都要麻烦如何在C中的编译时打印sizeof()的结果?,c,sizeof,compile-time,C,Sizeof,Compile Time,如何在C中的编译时打印sizeof()的结果 现在,我使用静态断言(基于其他web资源自制)将sizeof()结果与各种常量进行比较。虽然这有效。。。它既不优雅也不快速。我还可以创建变量/struct的实例并查看映射文件,但这也不如直接调用/command/operator优雅和快速。此外,这是一个使用多个交叉编译器的嵌入式项目。。。因此,构建一个示例程序并将其加载到目标中,然后读取一个值,这比上述两种方法都要麻烦 在我的例子(旧GCC)中,#warning sizeof(MyStruct)在打
在我的例子(旧GCC)中,
#warning sizeof(MyStruct)
在打印警告之前实际上不会解释sizeof()。不能这样做,不能使用结构。预处理器在编译之前被调用,因此甚至没有结构的概念;无法评估不存在/未定义的对象的大小。预处理器确实对转换单元进行标记化,但它这样做只是为了定位宏调用
最接近的方法是依赖于一些实现定义的宏,这些宏的计算结果与内置类型的大小相当。在gcc中,您可以找到具有以下特性的:
gcc -dM -E - </dev/null | grep -i size
如果不编写并执行一个程序,就无法知道自定义结构的大小。我正在四处寻找类似的功能,突然发现: 这让我产生了这样的想法:
char (*__kaboom)[sizeof( YourTypeHere )] = 1;
这导致VS2015中出现以下警告:
warning C4047: 'initializing': 'DWORD (*)[88]' differs in levels of indirection from 'int'
在这种情况下,88是您要找的尺寸
超级黑客,但它做到了。可能晚了几年,但希望这对某些人有用
我还没有机会尝试使用gcc或clang,但如果有人在我之前没有使用它,我会尝试确认它是否有效
编辑:为clang 3.6开箱即用
我能为GCC使用的唯一技巧是滥用-Wformat
,并让宏定义如下函数:
void kaboom_print( void )
{
printf( "%d", __kaboom );
}
这会给你一个警告,比如:
...blah blah blah... argument 2 has type 'char (*)[88]'
比最初的建议稍微粗俗一点,但也许对gcc稍有了解的人可以想出一个更好的滥用警告。Duplicate
case
constant是一个保证在所有C编译器中都能工作的技巧,不管每个编译器如何报告错误。对于Visual C++,它是简单的:
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;
}
汇编结果:
------ Build started: Project: cpptest, Configuration: Debug Win32 ------
cpptest.cpp c:\work\cpptest\cpptest\cpptest.cpp(29): error C2196: case value '48' already used
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
所以结构X的大小是48
编辑(2020年6月3日):
对于只打印“重复大小写值”的gcc或任何其他编译器,我使用以下技巧缩小值的范围:
1) 添加一个case值1==2(表示false)
2) 通过反复试验,缩小数值范围,例如,我尝试猜测sizeof(X)
is>16:
#include <stdio.h>
typedef struct _X {
int a;
char b[10];
} X;
int main()
{
printf("Hello World");
int dummy=0 ;
switch (dummy) {
case 1==2:
case sizeof( X)>16:
//case 16:
break;
}
return 0;
}
因此它是错误的,即sizeof(X)我偶然发现了一个类似于的解决方案,而这个解决方案产生了一个不太详细的警告,因此您可能会发现它很有用:
char (*__fail)(void)[sizeof(uint64_t)] = 1;
这将生成错误消息
Function cannot return array type 'char [8]'
这是用最新版本的
clang(1)
测试的。我的gcc编译器拒绝使用上述任何解决方案打印大小。我颠倒了逻辑,为它的大小注入编译器警告
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件
嗯。。。这是一个选项。虽然这并不完全是在编译时,但它是在运行时之前,所以它可能仍然与某些人相关 可以这样定义数组:
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
还有一种方法(实际可行):
使用旧版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]')
p、 显然,这一个是(非常)gcc特定的。所有其他方法对我都不起作用。以下方法适用于GCC、Clang、MSVC等,甚至在旧版本中,都是基于函数参数从指针到数组到标量类型的转换失败。编译器不会打印数组的大小,因此您可以从输出中获取值。在C和C++模式下工作。 查找
sizeof(long)
()的示例代码:
相关输出的示例:
- 通用条款4.4.7
:1:注意:应为“int”,但参数类型为“char(*)[8]”
- 叮当3.0.0
:1:6:注意:候选函数不可行:第一个参数没有从'char(*)[8]'到'int'的已知转换代码>
- MSVC 19.14
(2):警告C4047:“函数”:“int”与“char(*)[4]”的间接寻址级别不同。
@jws
好主意!。但是,sizeof(xxx)是一个常量表达式(除了VLA,),因此sizeof运算符即使在案例选择中也应该起作用:
enum e1 {dummy=-1};
enum e1 ev;
switch (ev) {
case sizeof(myType):;
break;
default:;
}
。。它在我的GCC中工作:“..\WinThreads.c:18:9:警告:大小写值'4'不在枚举类型'enum e1'[-Wswitch]”这是任何c编译器的通用解决方案
我意识到,如果我们的目标是知道sizeof()
的值,而不是打印它的值,那么我们只需要计算几个编译时sizeof(X)>?
表达式来缩小值
诀窍是当表达式的计算结果为false
(零)或true
(非零)时产生编译时错误
许多标准C结构可以实现我们的目标。我单独描述的重复案例
值技巧就是其中之一。另一种方法是通过测试初始化器中的零除法,编译器在编译时对初始化器求值。例如,要获得X的大小:
struct _X {
int a;
char c;
double d;
float f[30];
} X;
用几行代码编译:
#include <stdio.h>
struct _X {
int a;
char c;
double d;
float f[30];
} X;
int r2=1/(sizeof(X)<170);
int r3=1/(sizeof(X)<100);
int r4=1/(sizeof(X)<80);
int r5=1/(sizeof(X)<60);
int main()
{
return 0;
}
结果
main.c: In function ‘main’:
main.c:14:5: error: duplicate case value
case sizeof( X)>10:
^~~~
main.c:13:5: error: previously used here
case 1==1:
^~~~
main.c:15:5: error: duplicate case value
case sizeof( X)>12:
^~~~
main.c:13:5: error: previously used here
case 1==1:
^~~~
main.c:16:5: error: duplicate case value
case sizeof( X)>14:
^~~~
main.c:13:5: error: previously used here
case 1==1:
^~~~
main.c:17:5: error: duplicate case value
case sizeof( X)>16:
^~~~
main.c:12:5: error: previously used here
case 1==2:
^~~~
main.c:18:5: error: duplicate case value
case sizeof( X)==16:
^~~~
main.c:13:5: error: previously used here
case 1==1:
^~~~
main.c:18:9: warning: division by zero [-Wdiv-by-zero]
int r4=1/(sizeof(X)<136);
^
main.c:18:8: error: initializer element is not constant
int r4=1/(sizeof(X)<136);
^
main.c:19:9: warning: division by zero [-Wdiv-by-zero]
int r5=1/(sizeof(X)!=136);
^
main.c:19:8: error: initializer element is not constant
int r5=1/(sizeof(X)!=136);
^
1>------ Build started: Project: cpptest, Configuration: Release Win32 ------
1> cpptest.cpp
1>cpptest.cpp(11): error C2118: negative subscript
1>cpptest.cpp(12): error C2118: negative subscript
1>cpptest.cpp(13): error C2118: negative subscript
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
结果
main.c: In function ‘main’:
main.c:14:5: error: duplicate case value
case sizeof( X)>10:
^~~~
main.c:13:5: error: previously used here
case 1==1:
^~~~
main.c:15:5: error: duplicate case value
case sizeof( X)>12:
^~~~
main.c:13:5: error: previously used here
case 1==1:
^~~~
main.c:16:5: error: duplicate case value
case sizeof( X)>14:
^~~~
main.c:13:5: error: previously used here
case 1==1:
^~~~
main.c:17:5: error: duplicate case value
case sizeof( X)>16:
^~~~
main.c:12:5: error: previously used here
case 1==2:
^~~~
main.c:18:5: error: duplicate case value
case sizeof( X)==16:
^~~~
main.c:13:5: error: previously used here
case 1==1:
^~~~
main.c:18:9: warning: division by zero [-Wdiv-by-zero]
int r4=1/(sizeof(X)<136);
^
main.c:18:8: error: initializer element is not constant
int r4=1/(sizeof(X)<136);
^
main.c:19:9: warning: division by zero [-Wdiv-by-zero]
int r5=1/(sizeof(X)!=136);
^
main.c:19:8: error: initializer element is not constant
int r5=1/(sizeof(X)!=136);
^
1>------ Build started: Project: cpptest, Configuration: Release Win32 ------
1> cpptest.cpp
1>cpptest.cpp(11): error C2118: negative subscript
1>cpptest.cpp(12): error C2118: negative subscript
1>cpptest.cpp(13): error C2118: negative subscript
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
这意味着sizeof(X)
是对我有效的快速简单的解决方案(GCC):
(char[sizeof(long)])“bla”;
这将导致显示以下错误消息:
struct _X {
int a;
char c;
double d;
float f[30];
} X;
#include <stdio.h>
struct _X {
int a;
char c;
double d;
float f[30];
} X;
int r2=1/(sizeof(X)<170);
int r3=1/(sizeof(X)<100);
int r4=1/(sizeof(X)<80);
int r5=1/(sizeof(X)<60);
int main()
{
return 0;
}
main.c:17:9: warning: division by zero [-Wdiv-by-zero]
int r3=1/(sizeof(X)<100);
^
main.c:17:8: error: initializer element is not constant
int r3=1/(sizeof(X)<100);
^
main.c:18:9: warning: division by zero [-Wdiv-by-zero]
int r4=1/(sizeof(X)<80);
^
main.c:18:8: error: initializer element is not constant
int r4=1/(sizeof(X)<80);
^
main.c:19:9: warning: division by zero [-Wdiv-by-zero]
int r5=1/(sizeof(X)<60);
^
main.c:19:8: error: initializer element is not constant
int r5=1/(sizeof(X)<60);
^
#include <stdio.h>
struct _X {
int a;
char c;
double d;
float f[30];
} X;
int r2=1/(sizeof(X)<140);
int r3=1/(sizeof(X)<137);
int r4=1/(sizeof(X)<136);
int r5=1/(sizeof(X)!=136);
int main()
{
return 0;
}
main.c:18:9: warning: division by zero [-Wdiv-by-zero]
int r4=1/(sizeof(X)<136);
^
main.c:18:8: error: initializer element is not constant
int r4=1/(sizeof(X)<136);
^
main.c:19:9: warning: division by zero [-Wdiv-by-zero]
int r5=1/(sizeof(X)!=136);
^
main.c:19:8: error: initializer element is not constant
int r5=1/(sizeof(X)!=136);
^
#include "stdafx.h"
struct X {
int a;
char b[30];
double d;
float f[20];
};
int a1[sizeof(X)<130?-1:1];
int a2[sizeof(X)<120?1:-1];
int a3[sizeof(X)==128?-1:1];
int _tmain(int argc, _TCHAR* argv[]){
return 0;
}
1>------ Build started: Project: cpptest, Configuration: Release Win32 ------
1> cpptest.cpp
1>cpptest.cpp(11): error C2118: negative subscript
1>cpptest.cpp(12): error C2118: negative subscript
1>cpptest.cpp(13): error C2118: negative subscript
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
//main.cpp
#include <cstddef>
template <std::size_t x>
struct show_size;
void foo()
{
show_size<sizeof(my_type)>();//!!please change `my_type` to your expected
}
int main()
{
return 0;
}
ISO C++ forbids casting to an array type 'char [8]'