旧编译器的基于范围的循环到旧样式

Ranged based loop to old style for old compilers

最近我在尝试使用此代码从字符串生成 MD5。

string SecureInfrastructure::Generate_MD5_FromString(const string &data)
{
    unsigned char result[MD5_DIGEST_LENGTH];
    MD5((unsigned char*)data.c_str(), data.size(), result);

    std::ostringstream sout;
    sout<<std::hex<<std::setfill('0');
    for(long long c: result)
    {
        sout<<std::setw(2)<<(long long)c;
    }
    return sout.str();
}

但是,我使用的编译器不支持基于范围的 for 循环,我尝试使用下面的代码将此代码转换为传统的 for(...;...;...) 循环。

string SecureInfrastructure::Generate_MD5_FromString(const string &data)
{
    unsigned char result[MD5_DIGEST_LENGTH];
    MD5((unsigned char*)data.c_str(), data.size(), result);

    std::ostringstream sout;
    sout<<std::hex<<std::setfill('0');
    for(long long c; c<sizeof(result); c++) // long long c: result
    {
        sout<<std::setw(2)<<(long long)c;
    }
    return sout.str();
}

什么时候,我测试它不起作用,因为我得到一个空字符串。我很难找到错误所在。我应该如何用传统的for循环重新实现第一段代码?

这里使用c未初始化,开始单步执行。这会导致未定义的行为:

for(long long c; c<sizeof(result); c++) 

应该这样做:

for(size_t i = 0; i < MD5_DIGEST_LENGTH; ++i) {
    sout << std::setw(2) << (unsigned) result[i];
}

当你有

for(long long c: result)
{
    sout<<std::setw(2)<<(long long)c;
}

for(long long c: result) 说:对于 result 中的每个元素,将其分配给名为 c 的类型 long long 的变量。然后循环体使用 c。要在常规 for 循环中获得相同的行为,您需要做相同的事情。告诉编译器遍历你需要的所有元素

for(size_t i = 0; i < MD5_DIGEST_LENGTH; i++)

您可以直接在循环中使用该元素,而不是创建变量。那看起来像

sout<<std::setw(2)<<(long long)result[index_of_element];

将它们结合起来得到

for(size_t i = 0; i < MD5_DIGEST_LENGTH; i++)
{
    sout<<std::setw(2)<<(long long)result[i];
}

问题是你没有初始化 c 并且你也没有在任何地方引用结果数组

for(long long c = 0; /*Initialize*/ c<sizeof(result); c++) // long long c: result
{
  //use result[c]
}

使用 MD5_DIGEST_LENGTH 而不是 sizeof(result)。而且 "c" 我认为没有初始值 0。