通过指针访问字符*

Accessing a char* through a pointer

本文关键字:字符 访问 指针      更新时间:2023-10-16

这是我的问题。

我有一个定期修改字符*的类。

还有另一个类,需要能够读取此值。所以我想将 char* 传递给第二个类的构造函数,以便它可以在需要时检查值。

让我举一个我为另一个参数提供的实现示例,它是布尔类型:

在A类中:

bool f_valid = false; // global
m_eventCatcher.addProxy(porting::shared_ptr<CallbackProxy>(new handleCall(&f_valid))); 

在B类中:

struct handleCall 
{
    bool* m_dataValid;
    handleCall(bool* result) 
    {
        // saving the pointer to the boolean that I want to change
        m_dataValid = result; 
    }
    method()
    {
        if (smth) 
        { 
            (*m_dataValid) = false;
        }
    }
};

到目前为止一切顺利 - 这似乎有效。这两个类都可以更改和访问此布尔值。

现在我需要用 char* 做同样的事情(我不能使用字符串,所以我想这是存储短文本的最佳方式,比如 url 地址?

所以这是我写的:

A类:

const char* f_url = "blah blah"; // global
m_eventCatcher.addProxy(porting::shared_ptr<CallbackProxy>(new handleCall2(&f_url)));

C类:

struct handleCall2 
{
    char ** m_url;
    handleCall2(char** url)
    {
        // saving the pointer to the char*
        m_url= url;
        std::cout << (*m_url) << std::endl; // prints out url fine
    }
    method() 
   {
        std::cout << (*m_url) << std::endl; // by this time the value has been changed by ClassA, and I print out some rubbish - symbols, squares, etc.
    }
};

我想问题是因为字符串变了,它的地址也变了?我真的很困惑 - 有人可以告诉我发生了什么,在这种情况下我该怎么办?

更新:

看起来问题出在我如何修改字符*:

f_url = "new text"; // works fine
f_url = fileUrl.c_str(); // doesn't work! I get rubbish in the value when I try to access it from ClassB
strcpy(m_url, fileUrl.c_str()); // I also removed const from the variable and tried this - got a crash "access violation using location" :(

有没有其他方法可以将字符串的值写入字符 *?

我认为访问char *没有任何问题。

写了一个示例代码,它对我有用。可能是你的是一个不同的问题:

顺便说一句,这是我的代码供您参考:

#include <iostream>
class ClassThatPrints
{
private:
    const char **m_url;
public:
    ClassThatPrints(const char ** url)
    {
        m_url = url;
        std::cout << (*m_url) << std::endl;
    }
    void PrintAfterModify(void)
    {
        std::cout << (*m_url) << std::endl;
    }
};
class ClassThatModifies
{
private:
    const char *m_charPointer;
    ClassThatPrints *m_ClassThatPrints;
public:
    ClassThatModifies()
    {
        m_charPointer = "this is the original string";
        std::cout << "Printing before modification:" << std::endl;
        m_ClassThatPrints = new ClassThatPrints(&m_charPointer);
    }
    ~ClassThatModifies() {
        delete m_ClassThatPrints;
    }
    void ModifyStringAndPrint(void)
    {
        m_charPointer = "this is a modified string";
        std::cout << "Printing after modification:" << std::endl;
        m_ClassThatPrints->PrintAfterModify();
    }
};
int main()
{
    ClassThatModifies objClassThatModifies;
    objClassThatModifies.ModifyStringAndPrint();
}

如果你有这样的东西:

void addHandler() {
    const char* f_url = "blah blah";
    m_eventCatcher.addProxy(porting::shared_ptr<CallbackProxy>(new handleCall2(&f_url)));
}
void doStuff() {
    addHandler();
    m_eventCatcher.callProxy();
}

那么问题是当 addHandler 返回时f_url超出了范围。如果是这种情况,那么您的布尔版本也存在问题,(*m_dataValid) = false;覆盖了一些其他数据。

const char* f_url = "blah blah";

此声明表示您有一个指向常量字符串的指针。所以你不能做

strcpy(f_url, "hello world"); // copy to the preallocated place

但你可以

f_url = "hello world"; // do pointer assignment

如果您有以下情况:

class ClassA {
const char* f_url = "blah blah";
public: 
    void method() {
        f_url = "hello world";
    }
};
class ClassB {
    char** m_url;
public:
    void print() {
        cout << (* m_url); // m_url points to a string, allocated on the stack of ClassA::method()
    }
};

请记住,字符串"hello world"是在ClassA::method()的堆栈上分配的。当ClassA::method()退出时,该指针不再有效。为了解决我接下来提出的问题:

class ClassA {
static const int max_path = 256; 
char f_url[max_path];
public: 
    void method() {
        strcpy(f_url, "hello world");
    }
};
class ClassB {
    char** m_url;
public:
    void print() {
        cout << (* m_url);
    }
};
const char* f_url = "blah blah"; // global

也许你误解了这句话?const 限定符是当你放置它时,指的是它左侧的关键字。它被允许将其作为第一个关键字,但只有这样,它才引用其正确的;)所以你的声明说:(常量字符(*f_url所以它是一个指向常量字符的指针。而且我猜(我不知道你在那个类中修改它的值的方式是什么(你自己得到它,为什么修改常量字符值可能会以垃圾输出结束,不是吗?我建议你想把它声明为

char *const f_url = "blah blah";

这是

字符 (* 康斯特( f_url

所以f_url是一个常量地址值,它指向一个可修改的区域。但即使这样也没有多大意义,因为"blah blah"是常量内存区域的地址,所以你不能修改 ("废话"([计数] = 任何内容;无论如何。

所以你应该只做

char *const f_url = ThisIsACharArray[count];

并访问 char 数组又名字符串关于f_url。

或者更好的方法,正如我猜的那样,只需将常量排除在声明之外,并通过您自己的;)分配可修改的内存

字符串实际上并不存储在 f_url 中。字符串存储在其他地方f_url是指向其他地方的指针。

如果这样做:

    f_url = "new text"; // works fine

编译程序时,它将包含字符串"new text"其中的某处。 f_url将指向这一点 - 程序本身中间的一些内存。


    f_url = fileUrl.c_str(); // doesn't work! I get rubbish in the value when I try to access it from ClassB

fileUrl是一个 std::string。 fileUrl有自己的指向字符串的指针,该字符串c_str返回。由于fileUrl负责管理此字符串,因此当fileUrl超出范围时,内存可能会被重用于其他内容 - 它不知道您仍在使用该内存。


    // I assume you meant f_url here, not m_url
    strcpy(f_url, fileUrl.c_str()); // I also removed const from the variable and tried this - got a crash "access violation using location" :(

这的作用取决于f_url实际指向什么。如果f_url指向程序中间的一些内存(与f_url = "blah blah";一样(,那么这将崩溃。通常,这表示存在错误,因此操作系统将不允许您这样做。

如果允许,可能会发生这种情况:

char *s = "hello world";
strcpy(s, "abracadabra");
printf("hello world"); // prints "abracadabra"


你需要做的是获取自己的内存块来保存字符串,并在完成后释放它:

f_url = new char[fileUrl.length() + 1];
strcpy(f_url, fileUrl.c_str());
// when you don't need the string any more
delete [] f_url;

或:

f_url = strdup(fileUrl.c_str());
// when you don't need the string any more
free(f_url);

或者只是f_url为您处理内存管理的std::string。(这是最简单的解决方案!