在 C 函数的参数中声明变量

zmc*_*ord 5 c variables declaration function invocation

我有一个奇怪的愿望;我不知道是否有任何编译器或语言扩展允许这样做。

我希望能够在函数调用中声明变量,如下所示:

int test(int *out_p) {
    *out_p = 5;
    return 1;
}

int main()
{
    if (int ret = test(int &var)) { // int var declared inside function invocation
        fprintf(stderr, "var = %d\n", var); // var in scope here
    }
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

因为 var 的作用域遵循 ret 的作用域。另一个例子(来自我现在正在进行的一个项目),我有

cmd_s = readline();
int x, y, dX, dY, symA, symB;
if (sscanf(cmd_s, "placeDomino:%d %d atX:%d y:%d dX:%d dY:%d",
                           &symA, &symB, &x,  &y,   &dX,  &dY) == 6) {
    do_complicated_stuff(symA, symB, x, y, dX, dY);
} else if (sscanf(cmd_s, "placeAtX:%d y:%d dX:%d dY:%d", &x, &y, &dX, &dY) == 4) {
    do_stuff(x, y, dX, dY);
    /* symA, symB are in scope but uninitialized :-( so I can accidentally
     * use their values and the compiler will let me */
}
Run Code Online (Sandbox Code Playgroud)

我更愿意写

cmd_s = readline();
if (sscanf(cmd_s, "placeDomino:%d %d atX:%d y:%d dX:%d dY:%d",
                    int &symA, int &symB, int &x, int &y, int &dX, int &dY) == 6) {
    do_complicated_stuff(symA, symB, x, y, dX, dY);
} else if (sscanf(cmd_s, "placeAtX:%d y:%d dX:%d dY:%d", int &x, int &y, int &dX, int &dY) == 4) {
    do_stuff(x, y, dX, dY);
    /* Now symA, symB are out of scope here and I can't
     * accidentally use their uninitialized values */
}
Run Code Online (Sandbox Code Playgroud)

我的问题是,有编译器支持这个吗?如果我以正确的方式摩擦它,gcc 是否支持它?是否有包含此内容的 C 或 C++(草案)规范?

编辑:刚刚意识到在我的第一个代码示例中,我的 int ret 声明在 C99 中也不好;我想我被 for 循环宠坏了。我也想要这个功能;想象

while(int condition = check_condition()) {
    switch(condition) {
        ...
    }
}
Run Code Online (Sandbox Code Playgroud)

或类似的东西。

Jen*_*edt 5

除了块作用域声明之外,在 C99 中基本上还有两种声明变量的方法,这些变量根据定义仅限于它们出现的语句:

  • 复合文字的形式为(type name){ initializers }并声明一个位于当前块中的局部变量。例如,对于函数调用,您可以使用test(&(int){ 0 }).
  • forfor作用域变量仅具有语句本身以及依赖的语句或块的作用域。

你的if表达式带有局部变量,你可以做一些奇怪的事情,比如

for (bool cntrl = true; cntrl; cntrl = false)
   for (int ret = something; cntrl && test(&ret); cntrl = false) {
      // use ret inside here
   }
Run Code Online (Sandbox Code Playgroud)

小心,这样的东西很快就会变得不可读。另一方面,优化器非常有效地将此类代码简化为必要的代码,并且很容易发现该代码块test的内侧for仅被评估一次。


Joh*_*han 0

使用空范围,如下所示:

int test(int *out_p) {
    *out_p = 5;
    return 1;
}

int main()
{
    {
        int var, ret;
        if (ret = test(&var)) {
            fprintf(stderr, "var = %d\n", var); // var in scope here
        }
    }
    // var not in scope
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

  • 这不是 C,“if”子句必须是表达式,不能是声明 (3认同)