3

如果我给一个指针加 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,ma string literal”作为输出?由于指针指向char,实际上不应该向指针添加2 (ch + 2*sizeof(char)) 吗?给我输出“那里”?

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

4

4 回答 4

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)。希望这能在一定程度上消除您的困惑。

于 2013-06-07T02:00:22.377 回答
2

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

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

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是指向 int的 10 指针数组,因此该数组的元素具有指向 int 的类型指针。因此,指向该数组元素的指针具有指向 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的指针。由于这些是通过将数组转换为指针获得的,它们中的每一个都指向char 数组的第一个元素:指针ch[0](数组的第一个元素ch)指向数组“Hi”的第一个元素,ch[1]指向“那里”的第一个元素等等。

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

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

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

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

表达式的结果被传递给std::cout::operator<<. 由于表达式的类型是指向 char的指针,cout因此将打印该字符串:数组的第三个元素ch

于 2013-06-07T02:25:29.513 回答
1

Does it have something to do with cout?

No:

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

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

. .

But what can be confusing is that the << operator works differently when given a pointer to a cstring--instead of outputting the address, it outputs the string. Here is an example:

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

const char* pstr = "hello";

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

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

Since the pointer points to char,

1) The literal strings are stored in your array as pointers. That's why the type of the array is pointer.

2) Pointers are adresses in memory, which are just integers.

3) So your array of pointers is really an array of integers.

于 2013-06-07T02:11:01.143 回答
1

在 C 中,字符由 datatype 表示char。它可以保存任何 ASCII 字符,范围从 0 到 255。此外,它使用单个字节大小。

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

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

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

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

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

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

于 2013-06-07T02:19:35.210 回答