首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >_Alignas(N),[[gnu::联立(N)]和__attribute__((对齐(N)在声明中的位置

_Alignas(N),[[gnu::联立(N)]和__attribute__((对齐(N)在声明中的位置
EN

Stack Overflow用户
提问于 2021-04-26 18:17:07
回答 1查看 319关注 0票数 0

以下工会(不含AAA或BBB):

代码语言:javascript
复制
union AAA bpf_attr {
        struct {    /* Used by BPF_MAP_CREATE */
                uint32_t    map_type;
                uint32_t    key_size;    /* size of key in bytes */
                uint32_t    value_size;  /* size of value in bytes */
                uint32_t    max_entries; /* maximum number of entries
                                            in a map */
        };

        struct {    /* Used by BPF_MAP_*_ELEM and BPF_MAP_GET_NEXT_KEY commands */
                uint32_t            map_fd;
                uint64_t alignas(8) key;
                union {
                        uint64_t alignas(8) value;
                        uint64_t alignas(8) next_key;
                };
                uint64_t            flags;
        };

        struct {    /* Used by BPF_PROG_LOAD */
                uint32_t            prog_type;
                uint32_t            insn_cnt;
                uint64_t alignas(8) insns;     /* 'const struct bpf_insn *' */
                uint64_t alignas(8) license;   /* 'const char *' */
                uint32_t            log_level; /* verbosity level of verifier */
                uint32_t            log_size;  /* size of user buffer */
                uint64_t alignas(8) log_buf;   /* user supplied 'char *'
                                                  buffer */
                uint32_t            kern_version;
                                               /* checked when prog_type=kprobe
                                                  (since Linux 4.1) */
        };
} BBB;

如果我把_Alignas(8)放在AAABBB上有什么区别(如果有效的话还有其他位置)?标准似乎没有具体说明。前者之间有什么区别吗?还是对[[gnu::aligned(8)]]做同样的事情?GCC确实指出了一些不同之处,但我不明白其中的文字:

中,属性说明符跟随结束大括号,它们被认为与定义的结构、联合或枚举类型有关,而不是与类型说明符出现在其中的任何封闭声明有关,并且定义的类型直到属性说明符之后才完成。

编辑:

经过一些测试后,似乎(但一点也不确定):

代码语言:javascript
复制
union alignas(N) u {
        ...
} v;

上述规定不合法。

代码语言:javascript
复制
union u {
        ...
} alignas(N) v;

以上仅仅是合法的,因为有一个变量声明。它应相当于:

代码语言:javascript
复制
union u {
        ...
};
union u alignas(N) v;

代码语言:javascript
复制
union [[gnu::aligned(8)]] u {
        ...
};

以上似乎是合法的,不需要变量声明。

代码语言:javascript
复制
union u {
        ...
} [[gnu::aligned(8)]] v;

上面的内容似乎被忽略了(有警告),但是我不明白为什么;文本说它是允许的,即使它不是首选的版本。

还有一件奇怪的事情:如果使用C2x语法而不是使用__attribute__((aligned(8))),最后一个表单不会触发警告,顺便说一句,__attribute__((aligned(8)))是Linux在其源代码中使用的表单。

我可以测试更多的组合,但这是一个指数问题,理论上的答案似乎更合适。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-05-04 10:13:00

根据标准和GNU文档,我不知道理论上的答案是什么,因为它们不是很详细,但是这里有一个广泛的实验答案。

为了我的实验,我写了以下文件:

align.c

代码语言:javascript
复制
#include <stdalign.h>
#include <stdio.h>

struct s {
    int a;
    long b;
    char c;
} s_, s__;

__attribute__((aligned(16))) struct t {
    int a;
    long b;
    char c;
} t_, t__;

alignas(16) struct tt {
    int a;
    long b;
    char c;
} tt_, tt__;

[[gnu::aligned(16)]] struct ttt {
    int a;
    long b;
    char c;
} ttt_, ttt__;

struct __attribute__((aligned(16))) u {
    int a;
    long b;
    char c;
} u_, u__;
/*  error: expected ‘{’ before ‘_Alignas’
struct alignas(16) uu {
    int a;
    long b;
    char c;
} uu_, uu__;
*/
struct [[gnu::aligned(16)]] uuu {
    int a;
    long b;
    char c;
} uuu_, uuu__;
/*  error: expected identifier or ‘(’ before ‘{’ token
struct v __attribute__((aligned(16))) {
    int a;
    long b;
    char c;
} v_, v_;
*/
/*  error: expected identifier or ‘(’ before ‘{’ token
struct vv alignas(16) {
    int a;
    long b;
    char c;
} vv_, vv__;
*/
//  warning: ignoring attributes applied to ‘struct vvv’ after definition [-Wattributes]
/*  error: expected identifier or ‘(’ before ‘{’ token
struct vvv [[gnu::aligned(16)]] {
    int a;
    long b;
    char c;
} vvv_, vvv__;
*/
struct w {
    int a;
    long b;
    char c;
} __attribute__((aligned(16))) w_, w__;

struct ww {
    int a;
    long b;
    char c;
} alignas(16) ww_, ww__;
//  warning: ignoring attributes applied to ‘struct www’ after definition [-Wattributes]
struct www {
    int a;
    long b;
    char c;
} [[gnu::aligned(16)]] www_, www__;

struct x {
    int a;
    long b;
    char c;
} x_ __attribute__((aligned(16))), x__;
/*  error: expected ‘;’ before ‘_Alignas’
struct xx {
    int a;
    long b;
    char c;
} xx_ alignas(16), xx__;
*/
struct xxx {
    int a;
    long b;
    char c;
} xxx_ [[gnu::aligned(16)]], xxx__;

struct y {
    int a;
    long b;
    char c;
} y_, __attribute__((aligned(16))) y__;
/*  error: expected identifier or ‘(’ before ‘_Alignas’
struct yy {
    int a;
    long b;
    char c;
} yy_, alignas(16) yy__;
*/
/*  error: expected identifier or ‘(’ before ‘[’ token
struct yyy {
    int a;
    long b;
    char c;
} yyy_, [[gnu::aligned(16)]] yyy__;
*/
struct z {
    int a;
    long b;
    char c;
} z_, z__ __attribute__((aligned(16)));
/*  error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘_Alignas’
struct zz {
    int a;
    long b;
    char c;
} zz_, zz__ alignas(16);
*/
struct zzz {
    int a;
    long b;
    char c;
} zzz_, zzz__ [[gnu::aligned(16)]];


int main(void)
{
    printf("s:   %2zu;  s_:   %2zu; s__:     %2zu\n\n", alignof(struct s), alignof(s_), alignof(s__));
    printf("t:   %2zu;  t_:   %2zu; t__:     %2zu\n", alignof(struct t), alignof(t_), alignof(t__));
    printf("tt:  %2zu;  tt_:  %2zu; tt__:    %2zu\n", alignof(struct tt), alignof(tt_), alignof(tt__));
    printf("ttt: %2zu;  ttt_: %2zu; ttt__:   %2zu\n\n", alignof(struct ttt), alignof(ttt_), alignof(ttt__));
    printf("u:   %2zu;  u_:   %2zu; u__:     %2zu\n", alignof(struct u), alignof(u_), alignof(u__));
    puts("uu:   -");//  printf("uu:  %2zu;  uu_:  %2zu; uu__:    %2zu\n", alignof(struct uu), alignof(uu_), alignof(uu__));
    printf("uuu: %2zu;  uuu_: %2zu; uuu__:   %2zu\n\n", alignof(struct uuu), alignof(uuu_), alignof(uuu__));
    puts("v:    -");//  printf("v:   %2zu;  v_:   %2zu; v__:     %2zu\n", alignof(struct v), alignof(v_), alignof(v__));
    puts("vv:   -");//  printf("vv:  %2zu;  vv_:  %2zu; vv__:    %2zu\n", alignof(struct vv), alignof(vv_), alignof(vv__));
    puts("vvv:  -\n");//    printf("vvv: %2zu;  vvv_: %2zu; vvv__:   %2zu\n", alignof(struct vvv), alignof(vvv_), alignof(vvv__));
    printf("w:   %2zu;  w_:   %2zu; w__:     %2zu\n", alignof(struct w), alignof(w_), alignof(w__));
    printf("ww:  %2zu;  ww_:  %2zu; ww__:    %2zu\n", alignof(struct ww), alignof(ww_), alignof(ww__));
    printf("www: %2zu;  www_: %2zu; www__:   %2zu\n\n", alignof(struct www), alignof(www_), alignof(www__));
    printf("x:   %2zu;  x_:   %2zu; x__:     %2zu\n", alignof(struct x), alignof(x_), alignof(x__));
    puts("xx:   -");//  printf("xx:  %2zu;  xx_:  %2zu; xx__:    %2zu\n", alignof(struct xx), alignof(xx_), alignof(xx__));
    printf("xxx: %2zu;  xxx_: %2zu; xxx__:   %2zu\n\n", alignof(struct xxx), alignof(xxx_), alignof(xxx__));
    printf("y:   %2zu;  y_:   %2zu; y__:     %2zu\n", alignof(struct y), alignof(y_), alignof(y__));
    puts("yy:   -");//  printf("yy:  %2zu;  yy_:  %2zu; yy__:    %2zu\n", alignof(struct yy), alignof(yy_), alignof(yy__));
    puts("yyy:  -\n");//    printf("yyy: %2zu;  yyy_: %2zu; yyy__:   %2zu\n\n", alignof(struct yyy), alignof(yyy_), alignof(yyy__));
    printf("z:   %2zu;  z_:   %2zu; z__:     %2zu\n", alignof(struct z), alignof(z_), alignof(z__));
    puts("zz:   -");//  printf("zz:  %2zu;  zz_:  %2zu; zz__:    %2zu\n", alignof(struct zz), alignof(zz_), alignof(zz__));
    printf("zzz: %2zu;  zzz_: %2zu; zzz__:   %2zu\n", alignof(struct zzz), alignof(zzz_), alignof(zzz__));

    return 0;
}

cc -Wall -Wextra align.c -o align给出了我上面评论的警告和错误。我不得不注释掉一些代码以使其编译。

代码语言:javascript
复制
$ ./align
s:    8;    s_:    8;   s__:      8

t:    8;    t_:   16;   t__:     16
tt:   8;    tt_:  16;   tt__:    16
ttt:  8;    ttt_: 16;   ttt__:   16

u:   16;    u_:   16;   u__:     16
uu:   -
uuu: 16;    uuu_: 16;   uuu__:   16

v:    -
vv:   -
vvv:  -

w:   16;    w_:   16;   w__:     16
ww:   8;    ww_:  16;   ww__:    16
www:  8;    www_: 16;   www__:   16

x:    8;    x_:   16;   x__:      8
xx:   -
xxx:  8;    xxx_: 16;   xxx__:    8

y:    8;    y_:    8;   y__:     16
yy:   -
yyy:  -

z:    8;    z_:    8;   z__:     16
zz:   -
zzz:  8;    zzz_:  8;   zzz__:   16

结论:

如果对齐属性位于struct关键字之前,它将应用于任何声明的变量,但不适用于类型本身。

如果属性介于struct关键字和struct标记之间,则它同时适用于声明的类型和任何变量。对于没有编译的C11 alignas(),这是无效的。

属性不能就在{之前。

如果属性位于}之后,则If的工作方式就好像在struct关键字之前一样(仅适用于声明的任何变量),但旧的GNU语法除外,后者也适用于类型本身。

如果该属性位于声明变量的后面,则它仅适用于它。对于没有编译的C11 alignas(),这是无效的。

如果属性位于一个声明的变量(不是第一个变量)之前( }和属性之间至少有一个逗号),那么它只适用于它旁边的变量。这只对旧的GNU语法有效;其他的则不编译。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/67271825

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档