指向 char 算术的 C++ 指针

Posted

技术标签:

【中文标题】指向 char 算术的 C++ 指针【英文标题】:C++ pointer to char arithmetic 【发布时间】: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) 【参考方案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 *。让我编辑我的帖子,我刚刚意识到您对最初的示例感到困惑。

以上是关于指向 char 算术的 C++ 指针的主要内容,如果未能解决你的问题,请参考以下文章

简单的指针算术问题

超出有效内存范围的指针算术会产生啥危害?

C 指针的算术运算

C 指针的算术运算

40篇学完C语言——(第七篇)地址算术运算

使用指针算术修改字符串文字或字符数组[重复]