c++stringlpstr

C++ - Using GetPrivateProfileString without buffer


I'm using GetPrivateProfileStringA to read some things from a .ini file. I have some other class where I save things along with a string array. I have to use it like this to get a proper string into the ControlAlt array:

char buffer[24];
GetPrivateProfileStringA("CONTROLS",
    "ShiftUpAlt",
    "LeftThumb",
    buffer,
    (DWORD)24,
    "./Gears.ini");
scriptControl->ControlAlt[ScriptControls::ControlType::ShiftUp] = buffer;

I've tried putting it in directly, like so:

GetPrivateProfileStringA("CONTROLS",
    "ShiftUpAlt",
    "LeftThumb",
    (LPSTR)scriptControl->ControlAlt[ScriptControls::ControlType::ShiftUp],
    (DWORD)24,
    "./Gears.ini");

But then the value in ControlAlt is an LPSTR, which gives complications later when comparing it against a proper string. Is there a way to not use a buffer for this?

ControlAlt is defined as std::string ControlAlt[SIZEOF_ControlType];


Solution

  • GetPrivateProfileStringA requires a buffer to write a classic C-style '\0'-terminated string into, and a std::string is not such a buffer, although as you observe, a C-style string can be converted to a std::string.

    More specifically, GetPrivateProfileStringA expects a char * (LPSTR in Windows API terms) pointing to a writable buffer and that buffer's length. std::string does not provide this - at best, it provides the c_str() accessor which returns const char * (LPCSTR in Windows API terms) - a pointer to a read-only buffer. The const-ness of the buffer data is a pretty good indication that modifying it is a bad idea and will more than likely lead to undefined behavior.

    C++ '98 says: "A program shall not alter any of the characters in this sequence." However, implementations conforming to newer standards may well be more willing to put up with monkey business: resize() to make the buffer large enough, then use &foo[0] to get a char * that isn't const (or just const_cast away the protection on data()), let GetPrivateProfileStringA write to the buffer, then truncate the std::string at the '\0' wherever it landed. This still doesn't let you pass in a std::string directly to a function expecting a buffer pointer, though, because they are not the same thing - it just gives you a chance to avoid copying the string one extra time from the buffer.