【问题标题】:C++ pointer to char arithmetic指向 char 算术的 C++ 指针
【发布时间】:2013-06-03 05:29:47
【问题描述】:

如果我给一个指针加1,实际加的值是指针指向的类型的大小吗?例如:

int* num[5];
cout << *num << ", " << *(num + 2) << endl; 

这将打印存储在 num[1] 和 num[2] 的值, 所以 num + 2 实际上是 num + 2*sizeof(int) 如果我没记错的话。

现在,如果我将一个指向 char 的指针数组初始化为字符串字面量,就像这样:

char* ch[5] = 
{
     "Hi",
     "There",
     "I,m a string literal"
};

这是可以做到的,因为像“hi”这样的字符串文字表示它的第一个字符的地址,在本例中是“h”。现在我的问题是我怎样才能写出类似的东西:

cout << *(ch + 2);

并得到“I,m a string literal”作为输出? 由于指针指向 char,实际上不应该向指针添加 2 (ch + 2*sizeof(char)) 吗?给我输出“那里”?

和cout有关系吗? cout 是否搜索指向值的内存以查看它是否找到 '\0' 将指向值的内容识别为字符串,然后修改指针算术?但是,将 1 添加到指向字符串的 char 的指针将意味着每次添加不同数量的字节(而不是 char 的大小),因为字符串可以是任意大小。还是我完全错了?对不起,我是 C++ 新手,并且是普通编程。

【问题讨论】:

  • num + 2 实际上是“num + sizeof(int)*2”,或者更准确地说是 (int*) ((char*)num + sizeof(int)*2)

标签: c++ arrays pointers


【解决方案1】:

和cout有关系吗?

没有:

const char* cstrings[5] = 
{
    "Hi",
    "There",
    "I,m a string literal"
};

const char** x = cstrings + 2;
cout << *x << endl;

。 .

但可能令人困惑的是,当给定一个指向 cstring 的指针时,

int x = 10;
int* pint = &x;

const char* pstr = "hello";

cout << pint << endl << pstr << endl;

--output:--
0x7fff5fbff85c  //hexidecimal string representation of an integer
hello

由于指针指向char,

1) 文字字符串作为指针存储在您的数组中。所以数组的类型是指针。

2) 指针是内存中的地址,只是整数。

3) 所以你的指针数组实际上是一个整数数组。

【讨论】:

  • 数组是一个或多个特定类型对象的连续块。
  • 好的,数组名是什么?
  • 数组名是用于在源代码中标识数组的字符序列。您要说的是数组可以隐式转换为指针。不要再说它们是指针,因为它们不是。你让初学者感到困惑。
  • @Lucas Mezalira,请注意
【解决方案2】:

“如果我给一个指针加1,实际加的值就是指针指向右边的类型的大小?”

在 C++ 标准中不能保证指针是指针指向的某个内存的字节数。如果将整数 n 添加到指针,则结果是指向该数组中下一个元素 nth 的指针:

int iarr[10];
int* pi = iarr;  // pi points to iarr[0]
int* pi2 = pi+2; // pi2 points to iarr[2]

当你看的时候你会得到什么,例如。 int repr = (int)pi; 未由 C++ 标准定义。

在最流行的平台/实现上会发生什么

(int)pi2 == ((int)pi) + 2*sizeof(int)

当你有指针数组时,会发生完全相同的事情:

int* piarr[10];
int** ppi = piarr;     // ppi points to iarr[0]
int** ppi2 = piarr+2;  // ppi2 points to iarr[2]

注意 piarr 的类型是 10 的数组 指向 int 的指针,因此该数组的元素类型为 指向 int 的指针。因此,指向该数组元素的指针的类型为 pointer to pointer to int


char* ch[5] 是一个 由 5 个指向 char 的指针组成的数组

"Hello" 等是(窄)字符串文字。 (窄)字符串字面量是一个由 n const char 组成的 数组,其中 n 是字符串的长度加 1(用于终止 \0 字符)。数组可以隐式转换为指向数组第一个元素的指针,这就是这里发生的情况:

char* ch[5] = 
{
     "Hi",
     "There",
     "I,m a string literal"
};

数组ch 包含三个指向字符的指针。由于这些是通过将数组转换为指针获得的,它们中的每一个都指向 char 数组的第一个元素:指针ch[0](数组ch的第一个元素)指向数组“Hi”的第一个元素,ch[1] 指向“There”的第一个元素,依此类推。

请注意,还涉及从const charchar 的转换,这种转换已被弃用,应该避免。更好的形式是:

char const* ch[5] = 
{
     "Hi",
     "There",
     "I,m a string literal"
};

表达式*(ch + 2)解释如下:

  • ch 命名该数组(见上文)
  • ch + 2ch3 个指向 char 的指针的数组 隐式转换为 指向 char 的指针,一个指向数组 ch 的第一个元素的指针。因此,这个表达式的类型是指向char的指针
  • ch + 2 使上一步的指针现在指向第二个下一个元素;它指向ch 的第一个元素,所以它现在指向数组ch 的第三个元素。
  • *(ch + 2) 最后,* 取消引用指针并“获取”指向的对象。 ch + 2 创建的指针指向数组ch 的第三个元素,因此,该表达式解析为数组ch 的第三个元素。现在表达式的类型是指向字符的指针

表达式的结果被传递给std::cout::operator&lt;&lt;。由于表达式的类型是指向字符的指针cout 将打印该字符串:数组ch 的第三个元素。

【讨论】:

    【解决方案3】:

    在 C 中,字符由数据类型 char 表示。它可以容纳任何 ASCII 字符,范围从 0 到 255。而且它使用单个字节的大小。

    然而,字符串由char* 表示,从技术上讲,它是一个字符数组。有区别。 charchar* 不同。前者存储单个字符,后者存储对应字符串偏移量的内存方向。

    现在,在您的示例中,ch 不是char*,而是char**。也就是说,它是 一个字符数组的数组,或者更好的说法是一个字符串数组。如果我们取消引用ch 一次,如*ch,我们将得到第一个字符串:Hi。如果我们取消引用它两次,如**ch,我们将得到第一个字符串的第一个字符:H。所以,我们可以开始使用指针算法了!

    cout &lt;&lt; *(ch + 2) 将输出I,m a string literal

    cout &lt;&lt; **(ch + 1) 将输出T(第二个字符串的第一个字符)

    cout &lt;&lt; *(*ch + 1) 将输出i(第一个字符串的第二个字符)

    继续使用这些示例,以更好地了解字符和字符串的输出方式!都是关于指针算术的!

    【讨论】:

      【解决方案4】:

      该数组不是存储chars,而是存储char *s。因此说ch + 2 将等同于ch + 2*sizeof(char *)。然后你取消引用它,它指向"I'm a string literal"

      您最初的示例显示了混乱:

      int* num[5];
      cout << *num << ", " << *(num + 2) << endl; 
      

      这是一个指向 int 的指针数组。因此,*(num + 2) 将是 *(num + 2*sizeof(int *))不是 2*sizeof(int)。让我们用一个小程序来演示一下:

      #include <iostream>
      
      int main()
      {
          int *num[3];
          int x, y, z;
          x = 1;
          y = 2;
          z = 3;
      
          num[0] = &x;
          num[1] = &y;
          num[2] = &z;
      
          std::cout << *(num + 2) << "\n";
      }
      

      这将打印出一个内存地址(如0x22ff28),因为它保存的是指针,而不是值。

      在 C 和 C++ 中,数组和指针非常相似(许多书籍声称它们完全一样。这并不完全正确,但在很多情况下确实如此)。

      您的第一个示例应该是int num[5]。那么*(num + 2)(相当于num[2])将相当于*(num + 2*sizeof(int)。希望这能在一定程度上消除您的困惑。

      【讨论】:

      • 我忘记将 sizeof(char) 乘以 2,谢谢。但是,你为什么写 2*sizeof(char *) 而不是 2*sizeof(char) ?向指针添加 1 是否意味着将指向值的大小(在本例中为 sizeof(char) )添加到指针?然后 sizeof(ch + 1) 将指向“i”。和 sizeof(ch + 2) 会指向'T'对吗?
      • 是的,但在这种情况下,“指向”的值是char *。让我编辑我的帖子,我刚刚意识到您对最初的示例感到困惑。
      猜你喜欢
      • 2021-11-26
      • 2016-10-21
      • 1970-01-01
      • 2011-08-31
      • 1970-01-01
      • 2012-03-19
      • 2021-01-26
      • 2012-07-27
      相关资源
      最近更新 更多