This is working for me...
std::string GetProgramDataPath() {
CHAR path[MAX_PATH];
HRESULT hr = SHGetFolderPathA(nullptr, CSIDL_COMMON_APPDATA, nullptr, 0, path); // path accepted as LPSTR parameter?
if (SUCCEEDED(hr)) {
return std::string(path); // then automatically cast to const char*?
}
else {
return std::string();
}
}
...but I don't know why. I try to pass LPSTR
, but I get:
Error C4700 "uninitialized local variable 'path' used"
I look up how to initialize LPSTR
and come up with this:
std::string GetProgramDataPath() {
LPSTR path = new CHAR[MAX_PATH];
HRESULT hr = SHGetFolderPathA(nullptr, CSIDL_COMMON_APPDATA, nullptr, 0, path);
if (SUCCEEDED(hr)) {
std::string strPath(path);
delete[] path;
return std::string(strPath);
}
else {
delete[] path;
return std::string();
}
}
Is this the 'correct' code? With new
and delete
it seems wrong. Am I doing something unsafe by just using CHAR[]
? How come it works instead of LPSTR
? I believe it has something to do with the "equivalence of pointers and arrays" in C, but it seems there are some automatic conversions from CHAR[]
to LPSTR
to const char *
in this code I don't understand.
CodePudding user response:
Instead of managing the memory your self with new
and delete
I'd use a std::string
instead and let it manage the memory.
static std::string GetProgramDataPath()
{
std::string buffer(MAX_PATH, '\0');
const HRESULT result = SHGetFolderPathA
(
nullptr,
CSIDL_COMMON_APPDATA,
nullptr,
0,
buffer.data()
);
if (SUCCEEDED(result))
{
// Cut off the trailing null terminating characters.
// Doing this will allow you to append to the string
// in the position that you'd expect.
if (const auto pos{ buffer.find_first_of('\0') }; pos != std::string::npos)
buffer.resize(pos);
// Here is how you can append to the string further.
buffer.append(R"(\Some\Other\Directory)");
return buffer;
}
buffer.clear();
return buffer;
}
CodePudding user response:
This is working for me...but I don't know why.
LPSTR
is just an alias for CHAR*
(aka char*
):
typedef CHAR *LPSTR;
In certain contexts, a fixed-sized CHAR[]
(aka char[]
) array will decay into a CHAR*
(aka char*
) pointer to its 1st element, such as when passing the array by value in a function parameter, as you are doing.
I try to pass
LPSTR
, but I getError C4700 "uninitialized local variable 'path' used"
.
Because LPSTR
is just a pointer, and you likely did not point it at anything meaningful.
Is this the 'correct' code?
Technically yes, that will work (though return std::string(strPath)
should be return strPath
instead). However, you should consider using std::string
or std::vector<char>
instead to manage memory for you, don't use new[]
/delete[]
directly, eg:
std::string GetProgramDataPath() {
std::vector<char> path(MAX_PATH);
HRESULT hr = SHGetFolderPathA(nullptr, CSIDL_COMMON_APPDATA, nullptr, 0, path.data());
if (SUCCEEDED(hr)) {
return std::string(path.data());
}
return std::string();
}
Am I doing something unsafe by just using
CHAR[]
?
No.
How come it works instead of
LPSTR
?
Because CHAR[]
decays into the same type that LPSTR
is an alias of.
it seems there are some automatic conversions from
CHAR[]
toLPSTR
toconst char *
in this code.
Correct.