c++ не удается сравнить char
Делаю так:
#define GetGUIVar_ValueRaw(This, index) ((char*)&GetGUIVar_Value(This, index))
#define GetGUIVar_Value(This, index) (*(DWORD*)(((DWORD*)(*(DWORD*)((This)+0x12C)))[(index)]+0x4C))
#define PUT_CONST(String, Endl) CC_PutConst(OutClass, (String), (Endl))
const char* varValue = GetGUIVar_ValueRaw(This, 0);
const char* myStr = "pk_jasslocal0";
PUT_CONST("varValue = ", 0);
PUT_CONST(varValue, 0);
PUT_CONST("", 1);
PUT_CONST("myStr = ", 0);
PUT_CONST(myStr, 0);
PUT_CONST("", 1);
if (varValue == myStr)
{
PUT_CONST("varValue == myStr", 0);
PUT_CONST("", 1);
}
else
{
PUT_CONST("varValue != myStr", 0);
PUT_CONST("", 1);
}
if (varValue == GetGUIVar_ValueRaw(This, 0))
{
PUT_CONST("varValue == GetGUIVar_ValueRaw(This, 0))", 0);
PUT_CONST("", 1);
}
if (myStr == "pk_jasslocal0")
{
PUT_CONST("myStr == pk_jasslocal0", 0);
PUT_CONST("", 1);
}
На выходе получаю текст:
varValue = pk_jasslocal0
myStr = pk_jasslocal0
varValue != myStr
varValue == GetGUIVar_ValueRaw(This, 0))
myStr == pk_jasslocal0
То есть текст идентичен с какой стороны ни посмотри, но сравнение varValue == myStr по каким-то причинам не срабатывает, и когда сравниваю их вне переменных:
if (GetGUIVar_ValueRaw(This, 0) == "pk_jasslocal0")
{
PUT_CONST("varValue == myStr", 0);
PUT_CONST("", 1);
}
Тоже не получается. Я конечно, практически ничего не понимаю в c++, но после lua это выглядит странно. Хотел бы я просто сравнить это как строку, по привычным правилам, но видимо char это совсем другое.
Ответы (1 шт):
Вы сравниваете указатели, а не сами строки.
const char - это просто адрес, где строка хранится в памяти. У тебя два разных места в памяти, в которых текст одинаковый, поэтому так и получается.
varValue == myStr неправильно (у них разные места в памяти).
varValue == GetGUIVar_ValueRaw(This, 0) - правильно, это один и тот же адрес.
myStr == pk_jasslocal0 ну, повезло, компилятор сообразил, что это один и тот же текст, и запихнул его в одно место. Но вообще, так не всегда будет.
Делай сравнение по содержимому:
#include <cstring>
if (varValue && std::strcmp(varValue, "pk_jasslocal0") == 0) {
// равны как строки
}
Или так:
#include <string_view>
using namespace std::literals;
if (std::string_view(varValue) == "pk_jasslocal0"sv) {
// равны
}
Если вдруг строка заканчивается не на ноль, то лучше напрямую сравнивать длину:
// ровно "pk_jasslocal0"
bool eq = std::strncmp(varValue, "pk_jasslocal0", 13) == 0 && varValue[13] == '\0';
Про твои макросы.
#define GetGUIVar_ValueRaw(This, index) ((char*)&GetGUIVar_Value(This, index))
ты берёшь первые 4 байта адреса и делаешь вид, что это текст. Но это сработает, только если сразу за этими 4 байтами (+0x4C) реально начинается текст, и эти 4 байта - его начало. Если же там указатель на текст, то нужно читать сам указатель, а не адрес этих первых 4 байт.
Два корректных варианта:
// Вариант А: по +0x4C лежит сама строка (инлайн-буфер)
inline const char* GetGUIVar_ValueRawA(void* This, size_t index) {
auto base = *reinterpret_cast<std::uintptr_t*>(reinterpret_cast<std::uintptr_t>(This) + 0x12C);
auto arr = reinterpret_cast<std::uintptr_t*>(base);
auto addr = arr[index] + 0x4C;
return reinterpret_cast<const char*>(addr);
}
// Вариант Б: по +0x4C лежит указатель на строку (char*)
inline const char* GetGUIVar_ValueRawB(void* This, size_t index) {
auto base = *reinterpret_cast<std::uintptr_t*>(reinterpret_cast<std::uintptr_t>(This) + 0x12C);
auto arr = reinterpret_cast<std::uintptr_t*>(base);
auto addr = arr[index] + 0x4C;
return *reinterpret_cast<const char* const*>(addr);
}
Забудь про DWORD для вычислений с адресами, а то на 64-битной системе всё сломается. Лучше используй std::uintptr_t.