Jimmy
Jimmy

Reputation: 4529

Is this explanation accurate for C code that won't compile?

Alleged interview question and answer here.

Will the following code compile (in C)?

#define X 8;
int main(void)
{
    ++X; // will this line compile?
}`

I am no expert in C, but I know some C++ and thought: of course not, you cannot increment the number 8, it is an rvalue. Of course the preprocessor replaces the X with the 8 before trying to compile, and when it does try to compile, it will fail for that very reason. Then again, I am the one reading interview question websites so then I thought who knows...

Here is the explanation given:

"Strictly speaking, the operand of the prefix (or postfix) increment operator must be a non-modifiable lvalue. Now that we know what an lvalue is, we must ask ourselves if X is an lvalue. X is a macro, which means that it does not identify a place in memory – macros use simple text replacement via the preprocessor. Because macros don’t exist in a region of memory, they are not lvalues. This means that X can not be used as an operand of the prefix increment operator. Thus, the code shown above will not compile."

Is this explanation as bunk as I think it is?

How many errors can you find above? I think maybe that should be the interview question...

And this is just funny:

"Intuitively, you might be able to say that the code above will not compile – without knowing exactly why. However, in an interview situation, you will be expected to provide some reasoning like what’s given above. Simple yes or no answers just won’t cut it in an interview." (!)

Upvotes: 6

Views: 386

Answers (5)

Chris Lutz
Chris Lutz

Reputation: 75409

Is this explanation as bunk as I think it is?

Yes.

"Strictly speaking, the operand of the prefix (or postfix) increment operator must be a non-modifiable lvalue...

What? A non-modifiable lvalue is something like const int n; - you can take its address (via &) but you can't assign to it (via =, +=, or ++). You can't increment something that's not modifiable.

To quote the standard (6.5.3.1 paragraph 1):

The operand of the prefix increment or decrement operator shall have qualified or unqualified real or pointer type and shall be a modifiable lvalue.

Ahem.

X is a macro, which means that it does not identify a place in memory – macros use simple text replacement via the preprocessor.

This is bogus. Macros don't exist in the C language*. They're part of the preprocessor, which has no concept of lvalues, rvalues, expressions, or memory. This particular macro expands to an integer constant, which is an rvalue, but macros themselves have nothing to do with any of the above. See Steve Jessop's answer for a counterexample of a macro being an lvalue.

The correct answer is that the statement expands to ++8, and since 8 is an rvalue it cannot be used as an argument to ++ (in either form), and so it will not compile. Also, depending on whether you intend this code to be compiled as C89 or C99, leaving main without an explicit return value probably gives undefined behavior.

* If this is going to be the accepted answer, I suppose I ought to clarify this bit: the preprocessor is a part of the C programming language. It is specified in the C standard, and a compiler has to implement preprocessing in order to be a C compiler. However, the C "language" (i.e. the syntax, semantics, library, etc.) doesn't interact with the preprocessor - once you get to the stage where you start dealing with lvalues and rvalues, the preprocessor has long since been done and all macros are fully expanded. The macros themselves don't have any place in the syntax, since they aren't part of the "language." There was some debate (in Steve Jessop's answer) about whether the use of the term "language" here is misleading, and I agree with him that it is, I just can't find a better word to use instead.

Upvotes: 5

vine'th
vine'th

Reputation: 5030

It will not compile, since location values are required for the prefix operator. 8 being a constant, it fails. You can read further about L-value here : L-Value and R-Value Expressions

Upvotes: 0

Steve Jessop
Steve Jessop

Reputation: 279265

The explanation given is incorrect:

X is a macro, which means that it does not identify a place in memory – macros use simple text replacement via the preprocessor.

Precisely because macros are just simple text replacement, they can expand to an lvalue, or for that matter anything else. For example:

int x;
#define X x

int main() {
    ++X;
}

is OK. It's true that the macro itself doesn't have a place in memory, but that's irrelevant to whether ++X; is well-formed, since ++X; doesn't mean, "increment the macro X", it means "expand the macro X and then stick ++ on the front, ; on the back, and perform syntactic and semantic analysis on the result".

What the explanation says about "macros", it should say about integer constants. 8 is not an lvalue, and that's what matters here.

With that change, the explanation is OK [Edit - as Chris points out in a comment, it's still not OK, it writes "the operand of the prefix (or postfix) increment operator must be a non-modifiable lvalue": that should read "modifiable"]

Upvotes: 10

hamstergene
hamstergene

Reputation: 24439

The explanation is only correct about that the code will not compile, but it is very wrong in all other aspects.

It completely misses the fact that compiler will not see X, it will see ++8;;, so the whole rant about whether an operator could be applied to X makes no sense. It would be so much better to answer just “No” than giving such an explanation.

Upvotes: 2

Clement Bellot
Clement Bellot

Reputation: 841

It won't compile for the exact same reason that :

8 = 8+1;

won't compile.

You cannot modify (here increment) a constant.

Upvotes: 2

Related Questions