6

Is there any way to declare variable in if statement (using ANSI C only) ?

Example:

if(int variable = some_function())
{
    return 1;
}
Thomas Dickey
  • 51,086
  • 7
  • 70
  • 105
ARTAGE
  • 379
  • 2
  • 4
  • 14
  • 4
    No. That is not allowed in C. – BLUEPIXY Apr 26 '17 at 19:54
  • 1
    http://stackoverflow.com/questions/8474100/where-you-can-and-cannot-declare-new-variables-in-c – Jorge Cavaiuolo Apr 26 '17 at 19:56
  • 4
    According to the [ANSI C Grammar](https://www.lysator.liu.se/c/ANSI-C-grammar-y.html#expression), the grammar for the if statement is `IF '(' expression ')' statement`. `expression` cannot resolve to `declaration`, so there is no way to put a declaration in an if statement like in your example. – Random Davis Apr 26 '17 at 19:58
  • Declare a variable strictly using a classic declaration of format `type var = value`? No. – sjsam Apr 26 '17 at 20:05
  • @RandomDavis That grammar is not up to date (but that particular production hasn't changed). Note that `IF` in that grammar refers to the `if` keyword (`IF` is an ordinary identifier). The grammar in the ISO C standard is **`if`** **`(`** *expression* **`)`** *statement* or **`if`** **`(`** *expression* **`)`** *statement* **`else`** *statement* – Keith Thompson May 01 '20 at 03:21
  • I never used to appreciate the value of this construct until I realized how repetitive code gets when you are checking an error flag. – Sridhar Sarnobat Mar 09 '22 at 05:12

2 Answers2

10

No, you cannot do that.

What you can do is create a compound statement (anonymous or hanging block) just for the if

    {
        int variable;
        variable = some_function();
        if (variable) return 1;
    }
    /* variable is out of scope here */

Note that for this simple case you can call the function as the condition of the if (no need for an extra variable)

if (some_function()) return 1;
pmg
  • 106,608
  • 13
  • 126
  • 198
  • If you mean anonymous braces, I'm happy about that. I think they're underrated and are a great first step for refactoring. – Sridhar Sarnobat Mar 09 '22 at 05:03
  • 1
    The Standard calls them "compound statements" ([C11 6.8.2](http://port70.net/~nsz/c/c11/n1570.html#6.8.2)) – pmg Mar 09 '22 at 08:18
2

From GCC extension:

A compound statement enclosed in parentheses may appear as an expression in GNU C. This allows you to use loops, switches, and local variables within an expression. Recall that a compound statement is a sequence of statements surrounded by braces; in this construct, parentheses go around the braces. For example:

({ int y = foo (); int z;
   if (y > 0) z = y;
   else z = - y;
   z; })

is a valid (though slightly more complex than necessary) expression for the absolute value of foo ().

The last thing in the compound statement should be an expression followed by a semicolon; the value of this subexpression serves as the value of the entire construct. (If you use some other kind of statement last within the braces, the construct has type void, and thus effectively no value.)...

Simplified examples:

#include <stdio.h>
    
int main()
{
    if (({int a = 1; a;}))
        printf("Hello World: TRUE");
    else
        printf("Hello World: FALSE");

    return 0;
}

// output:
// Hello World: TRUE

#include <stdio.h>

int main()
{
    if (({int a = 0; a;}))
        printf("Hello World: TRUE");
    else
        printf("Hello World: FALSE");

    return 0;
}
// output:
// Hello World: FALSE

Does anyone really use it this way? Yes! As far as I know, Linux kernel simplifies code by means of this extension.

/* SPDX-License-Identifier: GPL-2.0-only */
#define __get_user(x, ptr)                      \
({                                  \
    int __gu_err = 0;                       \
    __get_user_error((x), (ptr), __gu_err);             \
    __gu_err;                           \
})

#define unsafe_op_wrap(op, err) do { if (unlikely(op)) goto err; } while (0)
#define unsafe_get_user(x,p,e) unsafe_op_wrap(__get_user(x,p),e)

https://elixir.bootlin.com/linux/latest/source/include/linux/uaccess.h#L365

axiqia
  • 302
  • 4
  • 13