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.