【问题标题】:Understanding strings as pointers in C++将字符串理解为 C++ 中的指针
【发布时间】:2018-03-15 16:49:42
【问题描述】:

我无法将字符串理解为指针。显然,字符串被理解为指向字符串首地址的指针。所以使用“&”运算符我应该收到字符串第一个字符的地址。这是一个小例子:

#include "stdafx.h"
#include <iostream>
using namespace std;

int main(){
    char text[101]; 
    int length;
    cout << "Enter a word: ";
    cin >> text;
    length = strlen(text);
    for (int i = 0; i <= length; i++) {
        cout << " " << &text[i];
    }
    return 0;
}

当输入诸如“Hello”之类的单词时,输出为:“Hello ello llo lo o”。相反,我希望收到“Hello”每个字符的地址。当我使用演员 long(&amp;text[i]) 时,效果很好。但我不明白为什么。如果没有强制转换,显然“&”运算符给出了要打印的字符串的起始地址。使用强制转换它分别给出每个字符的地址。 也许某人。可以向我解释这一点 - 我将非常感激!

【问题讨论】:

    标签: c++ string pointers memory-management memory-address


    【解决方案1】:

    &amp;text[i] 等效于text + i,它使用指针算法将指针沿char[] 数组移动i 个位。效果是在第 (i) 个字符上开始 cout,并调用 &lt;&lt;const char* 的重载。这会输出从起点到 NUL 终止符的所有字符。

    text[i] 然而是一个char 类型,并调用&lt;&lt;char 的重载。输出单个字符。

    在 C++ 中,如果您想要一个字符串,请改用 std::string。如果textstd::string 类型,您仍然可以写cin &gt;&gt; text;!然后,您的代码也不容易溢出您的 char 缓冲区。

    【讨论】:

    • @gsamaras:我目前正在更改一些使用 Boost Spirit 的代码。编译期间有很多空闲时间!
    • @gsamaras - 一个人应该知道最好不要尝试比 Bathsheba 更快地给出答案:P
    • 没有具体要求接受const char * 的流式操作符调用接受char 的重载。这只是一种可能的实现选择。
    【解决方案2】:

    要打印数组元素的地址,您可以这样做:

    cout << " " << (void*)&text[i];
    

    这个:

    cout << " " << &text[i];
    

    等价于:

    cout << " " << text + i;
    

    这意味着你要求打印字符串,从索引i开始。

    【讨论】:

      【解决方案3】:

      如果你有一个存储字符串的字符数组,例如

      char text[] = "Hello";
      

      然后数组被初始化为

      char text[] = { 'H', 'e', 'l', 'l', 'o', '\0' };
      

      在此声明中

      std::cout << text;
      

      const char * 类型重载了 operator &lt;&lt;,数组 text 被隐式转换为指向其第一个元素的指针。

      你可以改写

      std::cout << &text[0];
      

      因为在这两个语句中,表达式text&amp;text[0] 的类型为char *

      const char * 类型重载的运算符从指针处的地址开始输出字符,直到遇到零字符。

      所以用 if 代替语句

      std::cout << &text[0];
      

      你会写

      std::cout << &text[1];
      

      那么唯一改变的是字符串的起始地址,仅此而已。那实际上是您输出的字符串表示为

      { 'e', 'l', 'l', 'o', '\0' }
      

      如果要写

      std::cout << &text[2];
      

      也就是说,如果表达式右侧的指针向右移动了一个位置,则意味着您将处理字符串

      { 'l', 'l', 'o', '\0' }
      

      等等。

      也就是operator &lt;&lt;重载之类的

      template<class traits>
      basic_ostream<char, traits>& operator<<(basic_ostream<char, traits>&,
      const char*);
      

      仅将第二个参数指向的实体输出为字符串。

      如果你想输出指针本身的值而不是指针指向的字符串,你应该使用另一个重载的operator &lt;&lt; 声明

      basic_ostream<charT, traits>& operator<<(const void* p);
      

      Tp 调用它你应该写例如

      std::cout << ( void * )text;
      

      std::cout << ( void * )&text[i];
      

      i 是某个索引。

      您可以使用 C++ 转换来代替 C 转换

      std::cout << static_cast<void *>( &text[i] );
      

      【讨论】:

      • 这是唯一真正解释@Luk怀疑的答案。但是,显然,重要的是先回答。
      • 非常感谢!我是编程新手,我目前想知道一个类型如何void*
      • @Luk 将 void * 视为指向实际类型未知的原始内存的指针。
      猜你喜欢
      • 2014-11-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-01-11
      • 1970-01-01
      • 1970-01-01
      • 2021-06-28
      • 1970-01-01
      相关资源
      最近更新 更多