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.

→ Ссылка