Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/57.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 我怎样才能使用;sizeof“;在预处理器宏中?_C_Gcc - Fatal编程技术网

C 我怎样才能使用;sizeof“;在预处理器宏中?

C 我怎样才能使用;sizeof“;在预处理器宏中?,c,gcc,C,Gcc,有没有办法在预处理器宏中使用sizeof 例如,在过去的几年里,我有很多想做的事情,比如: #if sizeof(someThing) != PAGE_SIZE #error Data structure doesn't match page size #endif test.c(42) : error C2034: 'foo_can_not_exceed_16_bytes' : type of bit field too small for number of bits 我在这里检查的确切

有没有办法在预处理器宏中使用
sizeof

例如,在过去的几年里,我有很多想做的事情,比如:

#if sizeof(someThing) != PAGE_SIZE
#error Data structure doesn't match page size
#endif
test.c(42) : error C2034: 'foo_can_not_exceed_16_bytes' : type of bit field too small for number of bits
我在这里检查的确切内容是完全虚构的——重点是,我经常喜欢在编译时检查这些类型(大小或对齐),以防止有人修改数据结构,这可能导致数据结构不对齐或重新调整大小,从而破坏数据结构

不用说-我似乎无法以上述方式使用
sizeof

是否在预处理器宏中使用“
sizeof

否。条件指令采用一组受限的条件表达式
sizeof
是不允许的事情之一

预处理指令在解析源代码之前进行评估(至少在概念上是这样),因此没有任何类型或变量需要得到它们的大小


但是,有一些技术可以在C中获取编译时断言(例如,请参阅)。

预处理器无法使用
sizeof
运算符,但您可以将
sizeof
传输到编译器,并在运行时检查条件:

#define elem_t double

#define compiler_size(x) sizeof(x)

elem_t n;
if (compiler_size(elem_t) == sizeof(int)) {
    printf("%d",(int)n);
} else {
    printf("%lf",(double)n);
}

作为本次讨论的参考,我报告一些编译器在预处理器时间内获得sizeof()ar

JamesMcNellis的回答是正确的,但有些编译器会受到此限制(这可能违反了严格的ansi c)


作为一个例子,我指的是IAR C-compiler(可能是专业微控制器/嵌入式编程的领先者)。

#定义SIZEOF(x)((char*)(&(x)+1)-(char*)&(x))

有几种方法可以做到这一点。 如果
sizeof(someThing)
等于
PAGE_SIZE
,则以下代码片段将不会生成代码;否则,它们将产生编译时错误

1.C11路 从C11开始,您可以使用(需要
#include详细解释其工作原理

3.质谱特异性 在微软C++编译器上,你可以使用宏(需要<代码>包含< < /代码>),它使用与第2节中描述的技巧类似的技巧。 用法:

下一个宏呢:

/* 
 * Simple compile time assertion.
 * Example: CT_ASSERT(sizeof foo <= 16, foo_can_not_exceed_16_bytes);
 */
#define CT_ASSERT(exp, message_identifier) \
    struct compile_time_assertion { \
        char message_identifier : 8 + !(exp); \
    }

我知道这根线很旧,但是

我的解决方案:

extern char __CHECK__[1/!(<<EXPRESSION THAT SHOULD COME TO ZERO>>)];
外部字符检查[1/!()];
只要该表达式等于零,它就可以编译。如果没有其他变量,它就会在那里爆炸。因为变量是外部变量,所以它不会占用任何空间,并且只要没有人引用它(他们不会引用),它就不会导致链接错误

不像断言宏那样灵活,但我无法在我的GCC版本中编译它,而且我想它会在任何地方编译。

在我的便携式C++代码中()希望对一些结构或类的大小设置一个安全的保护。 我没有找到让预处理器抛出错误的方法(正如这里所述,它不能与sizeof()一起工作),而是在这里找到了导致编译器抛出错误的解决方案。

我必须修改代码,使其在我的编译器(xcode)中抛出错误:


现有答案仅说明了如何根据类型大小实现“编译时断言”的效果。在这种特定情况下,这可能满足OP的需要,但在其他情况下,您确实需要基于类型大小的预处理器条件。以下是如何做到这一点:

自己编写一个小C程序,如:

/* you could call this sizeof_int.c if you like... */
#include <stdio.h>
/* 'int' is just an example, it could be any other type */
int main(void) { printf("%zd", sizeof(int); }
/*如果您愿意,可以将此sizeof_int.c命名为*/
#包括
/*“int”只是一个示例,它可以是任何其他类型*/
int main(void){printf(“%zd”,sizeof(int);}
编译该文件。用您最喜欢的脚本语言编写一个脚本,该脚本运行上述C程序并捕获其输出。使用该输出生成C头文件。例如,如果您使用Ruby,它可能如下所示:

sizeof_int = `./sizeof_int`
File.open('include/sizes.h','w') { |f| f.write(<<HEADER) }
/* COMPUTER-GENERATED, DO NOT EDIT BY HAND! */
#define SIZEOF_INT #{sizeof_int}
/* others can go here... */
HEADER
sizeof_int=`./sizeof_int`

File.open('include/size.h','w'){f | f.write(我知道这是一个迟来的答案,但为了补充Mike的版本,我们使用了一个不分配任何内存的版本。我没有提出原始大小检查,我几年前在互联网上找到了它,不幸的是无法引用作者。另外两个只是相同想法的扩展

因为它们是typedef的,所以没有分配任何内容。由于名称中有uu LINE uu,因此它总是一个不同的名称,因此可以在需要的地方复制和粘贴。这在MS Visual Studio C编译器和GCC Arm编译器中起作用。它在CodeWarrior中不起作用,CW抱怨重新定义,没有使用u LINE u预处理器构造

//Check overall structure size
typedef char p__LINE__[ (sizeof(PARS) == 4184) ? 1 : -1];

//check 8 byte alignment for flash write or similar
typedef char p__LINE__[ ((sizeof(PARS) % 8) == 0) ? 1 : 1];

//check offset in structure to ensure a piece didn't move
typedef char p__LINE__[ (offsetof(PARS, SUB_PARS) == 912) ? 1 : -1];

在C11
\u Static\u assert
中添加了关键字。它的用法如下:

_Static_assert(sizeof(someThing) == PAGE_SIZE, "Data structure doesn't match page size")

尝试上述宏后,此片段似乎产生了所需的结果(
t.h
):

运行
cc-o t.o t.h

#include <sys/cdefs.h>
#define STATIC_ASSERT(condition) typedef char __CONCAT(_static_assert_, __LINE__)[ (condition) ? 1 : -1]
STATIC_ASSERT(sizeof(int) == 4);
STATIC_ASSERT(sizeof(int) == 42);
# 1 "t.h"
...
# 2 "t.h" 2

typedef char _static_assert_3[ (sizeof(int) == 4) ? 1 : -1];
typedef char _static_assert_4[ (sizeof(int) == 42) ? 1 : -1];
% cc -o t.o t.h
t.h:4:1: error: '_static_assert_4' declared as an array with a negative size
STATIC_ASSERT(sizeof(int) == 42);
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
t.h:2:84: note: expanded from macro 'STATIC_ASSERT'
  ...typedef char __CONCAT(_static_assert_, __LINE__)[ (condition) ? 1 : -1]
                                                       ^~~~~~~~~~~~~~~~~~~~
1 error generated.

42毕竟不是所有问题的答案…

为了在编译时对照数据结构的约束检查数据结构的大小,我使用了这个技巧

#if defined(__GNUC__)
{ char c1[sizeof(x)-MAX_SIZEOF_X-1]; } // brakets limit c1's scope
#else
{ char c1[sizeof(x)-MAX_SIZEOF_X]; }   
#endif
如果x的大小大于或等于其限制MAX_SIZEOF_x,则gcc将抱怨“数组大小太大”错误。VC++将发出错误C2148(“数组的总大小不得超过0x7fffffff字节”)或C4266“无法分配大小为0的常量数组”


之所以需要这两个定义,是因为gcc将允许以这种方式定义零大小的数组(sizeof x-n)。

这就是生成系统存在的确切原因。这就是为什么#错误指令应始终位于双引号中(由于“不”而未终止的字符常量)你好,布拉德。请考虑将你接受的答案改为“不要介意”,因为与此同时,目前所接受的答案有点过时了。“博多西森做的。伟大的文章-聪明的解决方案!虽然你必须管理-他们真的把C语法推到了极限,让这个工作!”- OTurns出-作为ARTI
_Static_assert(sizeof(someThing) == PAGE_SIZE, "Data structure doesn't match page size")
#include <sys/cdefs.h>
#define STATIC_ASSERT(condition) typedef char __CONCAT(_static_assert_, __LINE__)[ (condition) ? 1 : -1]
STATIC_ASSERT(sizeof(int) == 4);
STATIC_ASSERT(sizeof(int) == 42);
# 1 "t.h"
...
# 2 "t.h" 2

typedef char _static_assert_3[ (sizeof(int) == 4) ? 1 : -1];
typedef char _static_assert_4[ (sizeof(int) == 42) ? 1 : -1];
% cc -o t.o t.h
t.h:4:1: error: '_static_assert_4' declared as an array with a negative size
STATIC_ASSERT(sizeof(int) == 42);
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
t.h:2:84: note: expanded from macro 'STATIC_ASSERT'
  ...typedef char __CONCAT(_static_assert_, __LINE__)[ (condition) ? 1 : -1]
                                                       ^~~~~~~~~~~~~~~~~~~~
1 error generated.
#if defined(__GNUC__)
{ char c1[sizeof(x)-MAX_SIZEOF_X-1]; } // brakets limit c1's scope
#else
{ char c1[sizeof(x)-MAX_SIZEOF_X]; }   
#endif