missing closing parenthesis at end of #pragma

简介:

环境为Tornado2.2,VxWorks5.5

编译出现警告如下:

warning: missing closing parenthesis at end of #pragma

warning: Unrecognised value for #pragma pack directive.

warning: malformed `#pragma pack'

 
有问题的代码如下:

#ifndef _CFE_

#pragma pack(1)

#endif
 

typedefstruct _ROBO_PORT_CTRL_STRUC

{
     unsigned  char    rx_disable;
     unsigned  short    tx_disable;
} ROBO_PORT_CTRL_STRUC;
 

#ifndef _CFE_

#pragma pack()

#endif
 

问题出在编译的预处理指令#pragma上,在C语言中,预处理指令#pragma pack(n)是负责确定结构类型数据结构体内各个变量在内存中地址对齐方式的,第一、如果n大于等于结构体中长度最大的变量所占用的字节数,那么偏移量必须满足默认的对齐方式,第二、如果n小于该变量的类型所占用的字节数,那么偏移量为n的倍数,不用满足默认的对齐方式。结构的总大小也有个约束条件,分下面两种情况:如果n大于所有成员变量类型所占用的字节数,那么结构的总大小必须为占用空间最大的变量占用的空间数的倍数;否则必须为n的倍数。更加详细的内容请自己Google之。

对于本例来说,如果设置了#pragma pack(1),则:

sizeof(ROBO_PORT_CTRL_STRUC) = 3
 

如果没有设置#pragma pack(1),则:

sizeof(ROBO_PORT_CTRL_STRUC) = 4
 
一般情况下使用编译器缺省的对齐方式即可,但是总有些例外情况需要设置#pragma pack()参数,但是设置完了以后,想要恢复到原来缺省的对齐方式怎么办?因为Tornado实际上使用的是GCC编译器,因此查找了一下GCC的帮助,原文如下(中文是我自己的翻译):

1、#pragma pack(n) simply sets the new alignment.

#pragma pack(n),就是设置新的对齐方式为n

2、#pragma pack() sets the alignment to the one that was in effect when compilation started (see also command-line option -fpack-struct[=n] see Code Gen Options).

#pragma pack(),将对齐方式恢复为原来的初始值(可以参见命令行编译选项-fpack-struct[=n])

3、#pragma pack(push[,n]) pushes the current alignment setting on an internal stack and then optionally sets the new alignment.

#pragma pack(push[,n]),将当前的对齐方式存入内部堆栈,然后设置新的对齐方式为n

4、#pragma pack(pop) restores the alignment setting to the one saved at the top of the internal stack (and removes that stack entry). Note that #pragma pack([n]) does not influence this internal stack; thus it is possible to have #pragma pack(push) followed by multiple #pragma pack(n) instances and finalized by a single #pragma pack(pop).

#pragma pack(pop),恢复堆栈内保存的对齐方式,需要注意的是,单独使用#pragma pack([n])指令它只设置新的对齐方式,而不会把当前对齐方式放入堆栈。可以用#pragma pack(push)指令将当前的对齐方式入栈,然后再使用#pragma pack([n])指令设置新的对齐方式,最后使用#pragma pack(pop)恢复原来的设置。

 
从上面的说明可以总结出如下的几种配对使用方式,并附上在Tornado2.2,VxWorks5.5的环境下的编译结果:
 
使用方法
编译结果
1
#pragma pack(push)
#pragma pack(1)
……
#pragma pack(pop)
有警告,发生在#pragma pack(pop)那一行,内容如下:

missing closing parenthesis at end of #pragma

Extraneous characters at end of #pragma pack

Unrecognised value for #pragma pack directive.

malformed `#pragma pack'
2
#pragma pack(push,1)
……
#pragma pack(pop)
有警告,发生在#pragma pack(push,1)和#pragma pack(pop)这两行,内容同上
3
#pragma pack(push)
#pragma pack(1)
……
#pragma pack()
有警告,发生在#pragma pack()那一行,内容同上
4
#pragma pack(push,1)
……
#pragma pack()
有警告,发生在#pragma pack(push,1)和#pragma pack()这两行,内容同上
 
上表的运行结果说明如下:
 
使用方法
运行结果说明
1
#pragma pack(push)
#pragma pack(1)
……
#pragma pack(pop)
#pragma pack(1)指令起作用,后续结构体定义按照新的对齐方式进行对齐,而#pragma pack(pop)不起作用,后续的结构体依然按照#pragma pack(1)的方式对齐
2
#pragma pack(push,1)
……
#pragma pack(pop)
#pragma pack(push,1)不起作用,依然按照缺省方式对齐。
3
#pragma pack(push)
#pragma pack(1)
……
#pragma pack()
#pragma pack(1)指令起作用,后续结构体定义按照新的对齐方式进行对齐,而#pragma pack()不起作用,后续的结构体依然按照#pragma pack(1)的方式对齐
4
#pragma pack(push,1)
……
#pragma pack()
#pragma pack(push,1)不起作用,依然按照缺省方式对齐。
 
从上面两张表可以看出,不管是哪种组合方式,都有编译警告,而且都没有真正达到设置和恢复对齐方式的目的,但是这也就是网上所能找到的最多的解决方案了。 

经过多次试验和研究,终于发现使用#pragma pack(0)就没有编译错误,而且可以实现恢复缺省的对齐方式。

最后声明,本解决方案是在Tornado2.2 + VxWorks5.5下编译测试通过,其它环境没有测试,上述结果仅供参考。






本文转自 tywali 51CTO博客,原文链接:http://blog.51cto.com/lancelot/832909,如需转载请自行联系原作者
目录
相关文章
|
7月前
|
编译器 C语言
成功解决“Run-Time Check Failure #2 - Stack around the variable ‘arr‘ was corrupted.“问题
成功解决“Run-Time Check Failure #2 - Stack around the variable ‘arr‘ was corrupted.“问题
345 1
|
7月前
|
Unix Linux Shell
syntax error: unexpected end of file
syntax error: unexpected end of file
36 0
Newline required at end of file but not found.
Newline required at end of file but not found.
199 0
Newline required at end of file but not found.
|
程序员 Go API
译|Don’t just check errors, handle them gracefully(一)
译|Don’t just check errors, handle them gracefully
84 0
|
Java Go API
译|Don’t just check errors, handle them gracefully(二)
译|Don’t just check errors, handle them gracefully(二)
102 0
成功解决absl.flags._exceptions.UnrecognizedFlagError: Unknown command line flag 'data_format'
成功解决absl.flags._exceptions.UnrecognizedFlagError: Unknown command line flag 'data_format'
error: static assertion failed: Signal and slot arguments are not compatible.
error: static assertion failed: Signal and slot arguments are not compatible.
error: static assertion failed: Signal and slot arguments are not compatible.
syntax error, expect {, actual [, pos 0 at
syntax error, expect {, actual [, pos 0 at
224 0
|
编译器
warning C4995: strcat name was marked as #pragma deprecated
warning C4995: strcat name was marked as #pragma deprecated
102 0
|
C语言
[Error] ‘for‘ loop initial declarations are only allowed in C99 mode
[Error] ‘for‘ loop initial declarations are only allowed in C99 mode
337 0
[Error] ‘for‘ loop initial declarations are only allowed in C99 mode