0

I was implementing a C function to do manipulations of strings.

At the end I had to return pointer to static string but before that the first element of the string had to be set to '\0'

char *funct(...)
{
    static char string[30];
    .
    . //do some manipulations and possibly return here
    .
    string[0] = '\0';
    return string;
}

Everything works absolutely fine to this point, but then I wanted to merge the last two lines :

char *funct(...)
{
    static char string[30];
    .
    . //do some manipulations and possibly return here
    .
    return &(string[0] = '\0');
}

Then I got the error "lvalue required as unary ‘&’ operand". I presume that's so because the compiler threats everithing within the brackets as a number, not a variable and as we all know you can't have address of just a number ( "return &('\0');" is wrong).

My question is absolutely inessential but still I'm eager to know if you can trick the compiler(gcc in my case) to treat the content in the brackets as a variable and not a number

Thanks in advance :)

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
  • 4
    The result of the expression `string[0] = '\0'` is `'\0'`. You can't take address of a value. Don't save lines. – Eugene Sh. Sep 25 '19 at 14:14
  • 2
    Please don't merge the last two lines. Keep the code readable and sane. "Code golfing" has no place in professional programming. – Lundin Sep 25 '19 at 14:14
  • No, because the evaluation of `string[0] = '\0'` is not stored at an address. – Weather Vane Sep 25 '19 at 14:14

3 Answers3

3

Everything works absolutely fine to this point

Yep, code looks fine so far.

but then I wanted to merge the last two lines

Why? That's pointless.

Then I got the error "lvalue required as unary ‘&’ operand". I presume that's so because the compiler threats everithing within the brackets as a number

No, it is because the compiler treates everything within the brackets as the result of the = operator. In order to take the address of something, it must be a lvalue - an addressable memory location where a variable is allocated.

Some operators in C return a result which is a lvalue, some don't. The = operator does not. From the standard:

An assignment operator stores a value in the object designated by the left operand. An assignment expression has the value of the left operand after the assignment, but is not an lvalue.

So you shouldn't do this. Keep the code as it was and don't change anything:

string[0] = '\0';
return string;

...but still I'm eager to know if you can trick the compiler

Eh, well C allows all manner of crazy stuff. But that doesn't mean that you should do it. Some examples of code you should not write:

// BAD, OBFUSCATED CODE, DON'T USE THESE

return *string = '\0', string;

return &string[*string = '\0'];

return &(0<:string:>=0)<:string:>;
Lundin
  • 195,001
  • 40
  • 254
  • 396
  • Wow almost everyday I am amazed at C, today is no exception. Could you explain the last return statement("return &(0<:string:>=0)<:string:>;") - I have never seen anything like this(it's kinda like inline if without half of the arguments) – Hristo Mitrev Sep 25 '19 at 14:43
  • Ah.. these are the [digraphs](https://developerinsider.co/what-is-digraphs-trigraphs-and-tokens-c-cpp-programming-language/) got confused at first too.. – Eugene Sh. Sep 25 '19 at 14:48
  • @HristoMitrev It's a purposely obfuscated line with the intention of writing silly code. ["Solution"](https://godbolt.org/z/RjSBD3). Basically you have to be aware of [this old trick](https://stackoverflow.com/questions/381542/with-arrays-why-is-it-the-case-that-a5-5a). – Lundin Sep 25 '19 at 14:50
1

If you want such a compound return statement then just use the comma operator

return string[0] = '\0', &string[0];

Or (that is the same)

return string[0] = '\0', string;

Or you can enclose the expression in parentheses.

return ( string[0] = '\0', string );
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
1

If you want to merge those two lines, consider writing a function with a meaningful name, instead of obfuscating your code (or try to somehow "trick" the compiler)

char *cleared(char *str)
{
    *str = '\0';
    return str;
}

So that you could use it like

char *funct(/*...*/)
{
    static char string[30];
    /*
        do some manipulations and possibly return here
    */
    return cleared(string);
}
Bob__
  • 12,361
  • 3
  • 28
  • 42