通过指针访问 char*
Posted
技术标签:
【中文标题】通过指针访问 char*【英文标题】:Accessing a char* through a pointer 【发布时间】:2013-08-09 11:13:45 【问题描述】:这是我的问题。
我有一个定期修改 char* 的类。
还有另一个类,需要能够读取这个值。所以我想将 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.
;
我猜问题是因为字符串变了,它的地址也变了?我真的很困惑 - 谁能告诉我发生了什么,在这种情况下我应该怎么做?
更新:
看起来问题在于我如何修改 char*:
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 * 吗?
【问题讨论】:
哦,还有一件事:std::string
在处理字符串方面比原始指针要好得多。
“现在我需要对char*
做同样的事情(我不能使用字符串,[...])。” .但是,我想知道为什么你不能使用std::string
。
您使用的 C++ 编译器 不是 会向您发出关于发送地址 const char *
并将其存储在 char **
中的警告/错误??跨度>
如果你不能使用std::string
,那么std::vector
呢?是的,一个向量完全能够保存一个字符串,它只是不能轻松地进行“字符串”操作,但仍然可能比原始指针更好。
在 C++ 中,结构是成员默认公开的类。
【参考方案1】:
我认为访问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();
【讨论】:
你是对的 - 这确实有效!我当时做的一切都是正确的,问题一定出在其他地方…… 好吧,但是这段代码与问题中解释的不同。他说他在修改指针的值,你只是在你的“修改方法”中分配了一个新的指针,这是一个很大的不同,你修改是一个合法的操作,同时修改那个地址的字符的值(这就是他的解释听起来对我来说是绝对不正确的。【参考方案2】:如果你有这样的事情:
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 超出范围。
如果是这种情况,那么你的 bool 版本也有问题,(*m_dataValid) = false;
覆盖了其他一些数据。
【讨论】:
不,f_url 和 bool 并没有超出范围——它们是在所有方法之外的类内部定义的。【参考方案3】: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);
;
【讨论】:
我没有使用 strcpy grrr 再次按下输入太早。那么您建议如何将 char[] 发送到 ClassB 以及如何将其存储在 char** 中?... 只需重用您已有的代码。 char[] 与 char* 相同。 当我尝试将 f_url(即 char f_url[256])传递给需要 const char**(新处理程序(&f_url);)的函数时,出现编译错误:'无法转换参数 3 从 'char (*)[256]' 到 'const char **' 如果您不更改 f_url 指针,那么您可以将 char* 传递给 new_handler 构造函数。并将指针作为 m_url 存储在 ClassB 中。【参考方案4】:const char* f_url = "blah blah"; // global
也许你误解了这条线? const 限定符是当你放置它时,指的是它左边的关键字。 允许将其作为第一个关键字,但只有这样,它才指的是它的权利;) 所以你的声明说: (const char) *f_url 所以它是一个指向 const char 的指针。 我猜(我不知道你在那个类中修改它的值的方式是什么)你自己得到它,为什么修改 const char 值可能会以垃圾输出结束,不是吗? 我建议您将其声明为
char *const f_url = "blah blah";
这是
char (* const) f_url
所以 f_url 是一个指向可修改区域的常量地址值。 但即使这样也没有多大意义,因为“blah blah”是一个常量内存区域的地址,所以你不能修改 ("blah blah")[count] = 任何东西; 无论如何。
所以你应该这样做
char *const f_url = ThisIsACharArray[count];
并访问 char 数组,也就是关于 f_url 的字符串。
或者对你来说更好的方法,就像我猜的那样,只是将 const 保留在声明之外并由你自己分配可修改的内存;)
【讨论】:
【参考方案5】:字符串实际上并未存储在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
,它会为您处理内存管理。 (这是最简单的解决方案!)
【讨论】:
以上是关于通过指针访问 char*的主要内容,如果未能解决你的问题,请参考以下文章
尝试从常量 char * 类型的指针复制数据时出现“超出内存访问”错误。为啥?