char 和 char*(指针)

Posted

技术标签:

【中文标题】char 和 char*(指针)【英文标题】:char and char* (pointer) 【发布时间】:2012-10-04 08:02:00 【问题描述】:

我想了解指针是如何工作的,所以我创建了这个小程序。首先,我创建了一个指向 char 的 p 指针。

第一个问题到此为止。如果我创建一个指针,它的值是一个内存地址(如果我将它指向一个非指针对象),但这次在我的示例中是“哈哈”。为什么它在 char* 中以这种方式工作?以及如何使用 cin >> p 为其增加价值?

我的第二个问题是,我创建了一个 q char,它在我创建它时具有 *p 指针的值。但是它的值和地址也是“h”,但为什么呢?一定是这个char对象的内存地址!这是毫无意义的 :D (mingw - gcc)

#include <iostream>

int main() 

 /* char *p;
    cin >> p;                      //forexample: haha */

    char * p = "haha";
    char q = *p;
    std::cout << "&q = " << &q << std::endl;   //&q = h
    std::cout << "q  = " <<  q << std::endl;   //q = h

    return 0;

更多:如果我先用 char a[100] 分配内存;字符 *p=a;然后&q = h»ŢĹ,所以“h”有些乱。但它应该是一个内存地址!我的问题是,为什么不解决呢?

【问题讨论】:

那不安全。 p 没有任何内存可供您输入。 【参考方案1】:

char* p; 视为内存中的地址。你没有初始化这个指针,所以它不指向任何东西,你不能使用它。

始终保持安全: 要么将指针初始化为零:

char *p = 0; // nullptr in C++11

或初始化为一些自动的

void foo() 
  char a[100];
  char *p = a;

或全局内存:

char a[100];
void foo() 
  char *p = a;

或获取动态内存:

char* p = new char [100];

然后你可以使用p(如果不是NULL)来读取数据并从p中读取...


感谢您对operator &gt;&gt; (std::istream&amp;, char* p) 的误解。该操作员期望 p 指向一些内存(自动、全局、动态 - 无论如何) - 它不会自行分配内存。它只是从输入流中读取字符直到空白并将其复制到p 指向的内存中 - 但p 必须已经指向一些内存。


用于获取char q;的地址。当然你可以取q的地址:&amp;q,它的类型是char* p。但是&amp;qp不同,这个q=*p只是将p指向的第一个字符复制到q,它不能改变q的地址——它的地址是不可改变的。对于cout &lt;&lt; &amp;q - operator &lt;&lt; (ostream&amp;, char* p) 期望 p 指向以 NULL 结尾的字符串 - 并且 &amp;q 指向包含 "H" 的内存,但没有人知道这个字符之后的内容 - 所以你会在屏幕上看到一些垃圾。使用cout &lt;&lt; q 打印单个字符。

【讨论】:

那么,你说cin不分配内存,那我的“哈哈”呢?指针如何包含整个字符串? q 是一个简单的 char 变量,所以它可以包含 p 的任何字符,而且我没有分配我的“哈哈”文本,所以这就是为什么我的“h”没有内存地址?很清楚,但是我有一个问题:当我将字符复制到 q (char q = *p) 时,它实际上并不是在复制,它只是指向未分配的数据?所以问题无处不在,我的哈哈文本没有分配,所以我不能从中获得任何地址? ok,我用int创建了一个程序,int已经分配好了,我可以cout了p = a; cin >> (char *)p; cout )p); " 因为您没有为p 分配任何值,甚至0 - 然后它指向某个随机地址。您将“哈哈”复制到程序中的一些随机存储器中——它可能导致任何事情,这是未定义的行为——它甚至可能导致向你的老板发送一封电子邮件,说你有更好的工作——但这​​种随机存储器也可能发生未使用 - 因此您的程序似乎工作正常。 最后一个例子:int a[10]; - 假设a的内存地址是0x123。 int p = a; - 你将地址转换为 int - 所以 p == 0x123 作为值。 (char*)p 反向转换 - 所以你的程序认为 0x123 是 char 数组的开始。所以int[10]等价于char[10*sizeof(int)]...所以你有记忆,一切正常。 是的,但在我的示例中 p 等于内存地址。我用 a[100] 创建了你的例子,p 是“哈哈”,不等于内存地址,但应该是!【参考方案2】:

你应该有类似的东西:

#include <iostream>
using namespace std;

在程序的顶部。或者可以省略using 并参考std::cinstd::cout

int main() 
    char *p;

p 是一个指针,但你还没有初始化它,所以它可以指向任何地方,也可以不指向任何地方。你需要初始化它,例如:

p = new char[100];

...

    cin >> p;                      //forexample: haha

这没关系如果你已经初始化p 指向某个地方——除了如果你输入太多数据,你可能会溢出它指向的缓冲区。对于这样一个简单的测试程序来说没问题,但在实践中,您需要采取措施来避免它。

    char q = *p;
    cout << "&q = " << &q << endl; //&q = h

&amp;q 的类型为char*,是一个指向char 的指针。将char* 值发送到cout 不会打印指针的值(内存地址);它打印它指向的字符串。 (虽然我自己运行它时得到了一些奇怪的结果;我可能会遗漏一些东西。)如果您想查看指针值,请将其转换为 void*

count << "&q = " << (void*)&q << endl;

(或者您可以使用特定于 C++ 的强制转换之一;我不确定哪个最好。)

    cout << "q = " << q << endl;   //q = h

这里q 只是一个char,所以这会将其值打印为一个字符:h

    return 0;

【讨论】:

是的,在我的代码中,我采用了前两行,但很明显,所以我没有放在这里。我明白了,但是 cout 【参考方案3】:

首先要学习并永远记住指针是确保为它们分配内存,否则您的程序将无法正常运行。

您的代码实际上应该修改如下以分配内存,以便“cin”可以将用户输入写入分配的内存:

int main() 
    char *p = new char[1024];      // allocate memory so cin
    cin >> p;                      //forexample: haha
    char q = *p;
    cout << "&q = " << &q << endl; 
    cout << "q = " << q << endl;   
    return 0;

现在,字符指针是一个变量,指向内存中保存一组字符的位置(不一定是一个字符,可能不止一个字符,也可能没有,如特殊值 null 的情况),而字符变量实际上是持有一个字符(不是一组字符)。

处理指针时的基本运算符是 &(address of) 和 *(value at)。 & 检索变量的地址,所以如果我们有 [char q;] 那么 [&q] 将是一个字符指针。另一方面,* 检索给定指针的值,所以如果我们有 [char *p;] 那么 [*p] 将是内存中 p 指向的字符。

现在回到你的例子,cmets inline 用于说明

int main() 
    // allocate a place of 1024 character in memory
    // and let p points to that place
    char *p = new char[1024];      

    // call cin to read input from the user and save
    // it in memory at the location pointed to by p
    // NOTE: cin would put an extra NULL character 
    // at the end to terminate the string
    cin >> p;                      //forexample: haha

    // Now p would be pointing to a piece of memory like this
    // [h] [a] [h] [a] [\0]

    // use the value at operator to de-reference the pointer
    // p, the result would be a single character which 
    // will be the first character in memory p is pointing at
    char q = *p;

    // printing the value of (the address of q)
    // Note you have a problem here as cout will
    // be handling the memory starting at the address 
    // of q as a string while it is not, so you
    // will get a string starting with "h" and followed
    // by whatever is there in memory by the time of execution
    cout << "&q = " << &q << endl;

    // printing the value of the character q
    cout << "q = " << q << endl; 
    return 0;

希望对你有帮助

【讨论】:

是的,很明显,如果我将位置分配给 p,那么它会将“h 和一些混乱”写入 &q,但如果我不分配位置给 p,那么它只会写入“h”,和 *p 有什么区别。所以 q=&q? :D 但我认为 PiotrNycz 是对的,这是因为“哈哈”没有分配,所以它没有内存地址,所以 &q(即 p)不能指向任何地方,但是为什么它在“h”之后停止了“然后呢? @Iburidu 您的机器/编译器上发生的特定情况不是一般情况。在未分配的内存空间中存储数据的结果是不可预测的。在您的情况下,内存已经充满了零,因此打印以 &q 开头的字符串只是偶然正确打印出“h”,仅此而已。 好的,我是通过添加char a[100]分配的;诠释* p = a;但是为什么 p == "haha",如果它应该是内存地址 (&a[0])? @Iburidu 数组在 C++ 中被实现为指针,因此大多数时候您可以互换使用数组和指针。例如: int *p = new int[100];那么你可以做 p[0]=1; p[1]=50; ...等 @Iburidu 回到你的例子:cout 将打印出字符串“haha”,因为它会注意到你正在尝试打印一个 char* ...如果你想打印地址,你可以转换它到(void *) 或使用声明printf("%p", p);【参考方案4】:

字符串 literate 将存储在 .rdata 部分中,该部分将是只读的,因此使用 std cin 读取它会导致程序崩溃

第二件事,当你写这个时:

char *p = "some text";

然后指针 p 指向一个已分配和只读的内存,因为 rdata 部分肯定会由 windows 加载程序分配和准备,但正如我所说的 .rdata 不能修改

那么当你写这个时:

char q = *p;

您只需将 q 分配给 p 中的第一个字符,因为 * 返回指针当前指向的值,所以如果您尝试这样做:

++p;
q = *p;

q 将持有 'a' 而不是 'h' 因为指针是一个指向从第一个字符开始的一些字符的地址,因此增加一个它将使指针指向第二个字符并且 q 将保持这个值

【讨论】:

【参考方案5】:

更好的方法是:

    int arraySize;
    cin>>arraySize;
    char *a=new char[arraySize];
    cin >> a;

【讨论】:

以上是关于char 和 char*(指针)的主要内容,如果未能解决你的问题,请参考以下文章

char 和 char*(指针)

数组名相当于一个指针,哪数组指针char *p[],不就变成一个二级指针?

指向 char 指针数组的指针与指向 char 指针的指针(或 char** argv 与 char* (*argv)[])

swig char ** 作为指向 char * 的指针

请问C语言 char类型的指针要怎么赋值?

c语言char和int可以互相赋值,但指针不能赋值,char *和int *不能直接赋值,为啥呢?谢谢