简体   繁体   中英

Why does this code compile in Visual Studio 2003?

This might be a noobish question.

While migrating a project from Visual Studio 2003 to 2017 I noticed the code would error out in line 85 with 'undefined identifier'. This makes sense to me because nCurrPel doesn't seem to exist within that scope.

However, the exact same code appears to compile just fine in Visual Studio 2003. What's going on here?

Full code below, refer to commented section:

LTBOOL CompressLMData(const int *pData, int width, int height, int *pOutBuffer, int &outLen)
{
    if((pData == NULL) || (pOutBuffer == NULL))
    {
        ASSERT(FALSE);
        return FALSE;
    }

    if((width > LIGHTMAP_MAX_PIXELS_I) || (height > LIGHTMAP_MAX_PIXELS_I))
    {
        ASSERT(FALSE);
        return FALSE;
    }

    int nBufferLen = width * height * 3;
    int nSpanLen = 0;
    int* pOutPos = pOutBuffer;

    for(int nCurrPel = 0; nCurrPel < nBufferLen; nCurrPel += 3)
    {
        int nRunLen = 1;
        for(int nRunPel = nCurrPel + 3; nRunPel < nBufferLen; nRunPel += 3, nRunLen++)
        {
            if(nRunLen > 127)
            {
                break;
            }

            if( (pData[nCurrPel + 0] != pData[nRunPel + 0]) ||
                (pData[nCurrPel + 1] != pData[nRunPel + 1]) ||
                (pData[nCurrPel + 2] != pData[nRunPel + 2]) )
            {
                break;
            }
        }

        if(nRunLen >= 2)
        {
            if(nSpanLen > 0)
            {
                OutputSpan(false, nSpanLen, &pData[nCurrPel - nSpanLen * 3], pOutPos);
            }

            OutputSpan(true, nRunLen, &pData[nCurrPel], pOutPos);
            nSpanLen = 0;
            nCurrPel += (nRunLen - 1) * 3;
        }
        else
        {
            nSpanLen++;
            if(nSpanLen > 127)
            {
                OutputSpan(false, nSpanLen, &pData[nCurrPel - (nSpanLen - 1) * 3], pOutPos);
                nSpanLen = 0;
            }
        }       
    }

    //How does this work? nCurrPel is not defined
    if(nSpanLen > 0)
    {
        OutputSpan(false, nSpanLen, &pData[nCurrPel - nSpanLen * 3], pOutPos);
    }

    outLen = (int)(pOutPos - pOutBuffer);
    ASSERT( (outLen >= 4 * (width * height / 128)) &&
            (outLen <= (width * height * 3 + (width * height + 127) / 128)) );

    return LTTRUE;
}

It's to do with the scope of the for loop.

The Microsoft Visual C++ compiler before version 8 (2005, 2003, 2002, 6.0, etc) "hoisted" the scope of variables declared inside the for statement to the parent scope. After Visual Studio 2008 (version 9) the compiler conforms to the C++ specification which requires those variables to be scoped only to the for statement and its body.

Non-compliant C++ that's accepted by Visual C++ 2003 and 2005:

cout << bar << endl; // error: `bar` isn't defined yet

for( int bar = 0; bar < 10; bar++ ) // `bar` is defined here and it can be used within the `for( ... )` statement parenthesis.
{
    cout << bar << endl; // this 
}

cout << bar << endl; // the life of `bar` extends after its `for` statement to the end of the parent scope

Since Visual C++ 2008 the life of bar is restricted to the for statement parenthesis and the statement body and not to the parent scope:

cout << bar << endl; // error: `bar` isn't in-scope yet

for( int bar = 0; bar < 10; bar++ ) // `bar` is defined here and it can be used within the `for( ... )` statement parenthesis.
{
    cout << bar << endl; // OK
}

cout << bar << endl; // error: `bar` is not in scope

To fix this, you can either manually declare and initialize the for loop variables in the parent scope or use a separate variable to hold the last value, like so:

Approach 1: Declaration moved to parent scope:

int bar = 0;
for( ; bar < 10; bar++ )
{
     cout << bar << endl;
}

cout << bar << endl;

Approach 2: Separate variable declared in parent scope:

int last_bar = 0; // Set an initial value in case the for loop body is never evaluated.
for( int bar = 0; bar < 10; bar++ )
{
    cout << bar << endl;

    last_bar = bar;
}

cout << last_bar << endl;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM