在C中使用-block

Mui*_*uis 5 c c99

当有结构数组时,我经常会错过我在VB6中习惯的With-block方法(类似于C#中的Using-block).例如,我的许多代码现在看起来像:

Data.attribute[i].ref->value[i]->member.val1 = 0;
Data.attribute[i].ref->value[i]->member.val2 = 2;
Data.attribute[i].ref->value[i]->member.val3 = 3;
Run Code Online (Sandbox Code Playgroud)

虽然我喜欢做类似的事情:

with Data.attribute[i].ref->value[i]->member
{
    .val1 = 3;
    .val2 = 2;
    .val3 = 3;
}
Run Code Online (Sandbox Code Playgroud)

我知道我可以创建一个临时变量,但是在C中可能会出现上述情况吗?

Sto*_*ica 8

member_t* m = &(Data.attribute[i].ref->value[i]->member);
m->val1 = 3;
m->val2 = 2;
m->val3 = 3;
Run Code Online (Sandbox Code Playgroud)

以上应该可以正常工作以缩短线路.

自从你使用之后c99,你甚至可以在你需要的时候制作那些临时工具.

  • 除了缩短行之外,它还会缓存查找`Data.attribute [i] .ref-> value [i] - > member`所需的所有指针运算,因此只需要执行一次,而不是三次.编译器可能已经完成的微优化,但仍然支持仅使用局部变量的另一个注释.如果你关心范围,你可以将整个块包装在`{...}`中,所以`m`不会比这四行更进一步. (3认同)
  • @Joshua,我会讨厌自己提出建议,但你可以把它包装成一个宏...... (2认同)

ram*_*ion 7

您可以使用宏来对此进行排序,但这并不值得:

int main(){

  WITH(Data.attribute[i].ref->value[i]->member,
    .val1 = 3,
    .val2 = 2,
    .val3 = 3
  );
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

WITH()宏定义为使用参数计数可变参数宏:

#define WITH(prefix, ...) do {\
  MACRO_CONCAT(_WITH,PP_NARG(__VA_ARGS__))(prefix, __VA_ARGS__);\
} while (0)

#define PP_NARG(...) \
           PP_NARG_(__VA_ARGS__,PP_RSEQ_N())
#define PP_NARG_(...) \
           PP_ARG_N(__VA_ARGS__)
#define PP_ARG_N( \
              _1, _2, _3, _4, _5, _6, _7, _8, _9,_10, \
             _11,_12,_13,_14,_15,_16,_17,_18,_19,_20, \
             _21,_22,_23,_24,_25,_26,_27,_28,_29,_30, \
             _31,_32,_33,_34,_35,_36,_37,_38,_39,_40, \
             _41,_42,_43,_44,_45,_46,_47,_48,_49,_50, \
             _51,_52,_53,_54,_55,_56,_57,_58,_59,_60, \
             _61,_62,_63,N,...) N
#define PP_RSEQ_N() \
           63,62,61,60,                   \
         59,58,57,56,55,54,53,52,51,50, \
         49,48,47,46,45,44,43,42,41,40, \
         39,38,37,36,35,34,33,32,31,30, \
         29,28,27,26,25,24,23,22,21,20, \
         19,18,17,16,15,14,13,12,11,10, \
         9,8,7,6,5,4,3,2,1,0

#define _MACRO_CONCAT(a,b)  a ## b
#define MACRO_CONCAT(a,b)  _MACRO_CONCAT(a,b)

#define _WITH1(a,b)        a b
#define _WITH2(a,b, bs...) a b ; _WITH1(a, bs)
#define _WITH3(a,b, bs...) a b ; _WITH2(a, bs)
#define _WITH4(a,b, bs...) a b ; _WITH3(a, bs)
#define _WITH5(a,b, bs...) a b ; _WITH4(a, bs)
#define _WITH6(a,b, bs...) a b ; _WITH5(a, bs)
#define _WITH7(a,b, bs...) a b ; _WITH6(a, bs)
#define _WITH8(a,b, bs...) a b ; _WITH7(a, bs)
#define _WITH9(a,b, bs...) a b ; _WITH8(a, bs)
#define _WITH10(a,b, bs...) a b ; _WITH9(a, bs)
#define _WITH11(a,b, bs...) a b ; _WITH10(a, bs)
#define _WITH12(a,b, bs...) a b ; _WITH11(a, bs)
#define _WITH13(a,b, bs...) a b ; _WITH12(a, bs)
#define _WITH14(a,b, bs...) a b ; _WITH13(a, bs)
#define _WITH15(a,b, bs...) a b ; _WITH14(a, bs)
#define _WITH16(a,b, bs...) a b ; _WITH15(a, bs)
#define _WITH17(a,b, bs...) a b ; _WITH16(a, bs)
#define _WITH18(a,b, bs...) a b ; _WITH17(a, bs)
#define _WITH19(a,b, bs...) a b ; _WITH18(a, bs)
#define _WITH20(a,b, bs...) a b ; _WITH19(a, bs)
#define _WITH21(a,b, bs...) a b ; _WITH20(a, bs)
#define _WITH22(a,b, bs...) a b ; _WITH21(a, bs)
#define _WITH23(a,b, bs...) a b ; _WITH22(a, bs)
#define _WITH24(a,b, bs...) a b ; _WITH23(a, bs)
#define _WITH25(a,b, bs...) a b ; _WITH24(a, bs)
#define _WITH26(a,b, bs...) a b ; _WITH25(a, bs)
#define _WITH27(a,b, bs...) a b ; _WITH26(a, bs)
#define _WITH28(a,b, bs...) a b ; _WITH27(a, bs)
#define _WITH29(a,b, bs...) a b ; _WITH28(a, bs)
#define _WITH30(a,b, bs...) a b ; _WITH29(a, bs)
#define _WITH31(a,b, bs...) a b ; _WITH30(a, bs)
#define _WITH32(a,b, bs...) a b ; _WITH31(a, bs)
#define _WITH33(a,b, bs...) a b ; _WITH32(a, bs)
#define _WITH34(a,b, bs...) a b ; _WITH33(a, bs)
#define _WITH35(a,b, bs...) a b ; _WITH34(a, bs)
#define _WITH36(a,b, bs...) a b ; _WITH35(a, bs)
#define _WITH37(a,b, bs...) a b ; _WITH36(a, bs)
#define _WITH38(a,b, bs...) a b ; _WITH37(a, bs)
#define _WITH39(a,b, bs...) a b ; _WITH38(a, bs)
#define _WITH40(a,b, bs...) a b ; _WITH39(a, bs)
#define _WITH41(a,b, bs...) a b ; _WITH40(a, bs)
#define _WITH42(a,b, bs...) a b ; _WITH41(a, bs)
#define _WITH43(a,b, bs...) a b ; _WITH42(a, bs)
#define _WITH44(a,b, bs...) a b ; _WITH43(a, bs)
#define _WITH45(a,b, bs...) a b ; _WITH44(a, bs)
#define _WITH46(a,b, bs...) a b ; _WITH45(a, bs)
#define _WITH47(a,b, bs...) a b ; _WITH46(a, bs)
#define _WITH48(a,b, bs...) a b ; _WITH47(a, bs)
#define _WITH49(a,b, bs...) a b ; _WITH48(a, bs)
#define _WITH50(a,b, bs...) a b ; _WITH49(a, bs)
#define _WITH51(a,b, bs...) a b ; _WITH50(a, bs)
#define _WITH52(a,b, bs...) a b ; _WITH51(a, bs)
#define _WITH53(a,b, bs...) a b ; _WITH52(a, bs)
#define _WITH54(a,b, bs...) a b ; _WITH53(a, bs)
#define _WITH55(a,b, bs...) a b ; _WITH54(a, bs)
#define _WITH56(a,b, bs...) a b ; _WITH55(a, bs)
#define _WITH57(a,b, bs...) a b ; _WITH56(a, bs)
#define _WITH58(a,b, bs...) a b ; _WITH57(a, bs)
#define _WITH59(a,b, bs...) a b ; _WITH58(a, bs)
#define _WITH60(a,b, bs...) a b ; _WITH59(a, bs)
#define _WITH61(a,b, bs...) a b ; _WITH60(a, bs)
#define _WITH62(a,b, bs...) a b ; _WITH61(a, bs)
#define _WITH63(a,b, bs...) a b ; _WITH62(a, bs)
#define _WITH64(a,b, bs...) a b ; _WITH63(a, bs)
Run Code Online (Sandbox Code Playgroud)

使用以下方法查看宏扩展的结果gcc -E:

int main(){

  do { 
    Data.attribute[i].ref->value[i]->member.val1 = 3;
    Data.attribute[i].ref->value[i]->member.val2 = 2; 
    Data.attribute[i].ref->value[i]->member.val3 = 3; 
  } while (0);

  return 0;
}
Run Code Online (Sandbox Code Playgroud)

请注意,如果您愿意指定局部变量的类型(此处假设为),并且正在使用gcc-4.3及更高版本(或clang或其他一些现代编译器),则可以使用宏局部变量Member_t:

#define WITH_LOCAL(type, prefix, ...) _WITH_LOCAL( \
  type, \
  MACRO_CONCAT(__with_local, __COUNTER__), \
  prefix, \
  __VA_ARGS__ \
)
#define _WITH_LOCAL(type, local, prefix, ...) do {\
  type local = prefix;\
  MACRO_CONCAT(_WITH,PP_NARG(__VA_ARGS__))(local, __VA_ARGS__);\
} while(0)

int main(){

  WITH_LOCAL(Member_t *, &(Data.attribute[i].ref->value[i]->member),
    ->val1 = 3,
    ->val2 = 2,
    ->val3 = 3
  );

  return 0;
}
Run Code Online (Sandbox Code Playgroud)

这将扩展到:

int main() {

  do { 
    Member_t * __with_local0 = &(Data.attribute[i].ref->value[i]->member);
    __with_local0->val1 = 3;
    __with_local0->val2 = 2;
    __with_local0->val3 = 3;
  } while(0);

  return 0;
}
Run Code Online (Sandbox Code Playgroud)

  • +1:有趣的游览在宏观hackery.观察:标记粘贴`##`是没有必要的,因为连接的字符串不构成单个标识符的一部分; 简单的邻接`ab`就足够了.根据标准,'_如果结果不是有效的预处理令牌,则行为未定义'._严格来说,您生成的内容不是有效的预处理令牌(它是一系列有效的预处理令牌),所以你'重新走向未定义的行为.你可能会或可能不会逃脱它; 如果你不使用`##`,你很高兴. (2认同)
  • 我已经赞成这个(因为它引起了我的注意:)),但我想指出,使用额外的类型"提示",你可以生成一个使用临时对象的块. (2认同)