在这篇短文中,我将通过三种不同的方法使用指针来完成相同的任务,向您展示指针的用法。我认为对于 C++ 初学者来说,这是一个非常好的方法,因为您可以从不同的角度看待指针,从而更好地理解它们以及如何使用它们。
代码使用三种不同的指针方法来创建一个字符串数组。您可以将其视为稀疏的字符矩阵,或者仅仅是一个字符串数组,例如:
Aa01234
Bb012
Cc0123456
等等。
这三种方法分别是:偏移量、索引和递增。
代码使用 #define 指令,以便能够
轻松编译每种方法。因此,只需注释掉这三行
您就可以看到每种方法是如何工作的。
例如,现在设置为使用递增方法运行。
1 2 3
|
//#define _use_offset_
//#define _use_array_
#define _use_increments_
|
我使用的数据结构是 char**。
这是一个指向字符的指针的指针,
就像 -> (-> 字符)。
我将其初始化为
|
char** array_of_strings = new char*[26];
|
所以基本上它是一个字符串数组,就像
-> ->sssssssssssss
->sssssssssssss
->sssssssssssss
array_of_strings 是主指针 ->,我们通过任一方法来移动它
垂直移动(这样想更好)。目前,
当我们解引用 *array_of_strings 时,我们就得到了另一个指针,即那个
指向实际字符串的指针,即上面的第二个 ->。
所以 array_of_strings++ 会移动到下一个字符串(垂直),而
(*array_of_strings)++ 会指向字符串中的下一个字符(水平)。
第一种方法是使用偏移量。在这种方法中,我们不修改
指针,而是使用某个偏移量来指向数据,
就像 *(pointer+5) = something。因为指针存储的是地址,所以我们可以这样做,
pointer+5 指向距离 pointer 偏移 5 个字节的字节地址。
在数组术语中,这相当于数组方法中的 pointer[5]。在递增术语中,这相当于
++pointer;++pointer;++pointer;++pointer;++pointer,将指针递增 5
次。
第二种方法是最好、最简单的,使用数组索引:
array[i][j]。
第三种方法是递增。在这里,我们需要修改指针,
因为我们使用 ++ 和 -- 运算符来向前或向后移动指针。
所以 p[1]、*(p+1) 和 *++p 是执行相同操作的三种方式:
将指针指向指针后一个字节的位置。
在递增方法中,我使用了两个指针:
array_of_strings 和 new_string。它们都是指针,但它们的
行为不同。array_of_strings 是一个指向指针的指针,
它指向一个指向字节(字符)的指针,而 new_string
指向实际数据,即字符串。当我们执行 array_of_strings++ 时,
我们将 array_of_strings 移动到指向下一个字符串。
Aa01234
*array_of_strings++ -> Bb01234567
当我们执行 *++new_string 时,我们指向字符串中的下一个字符:
Aa01234
^
|
*++new_pointer
请注意,我使用递增运算符放在 *++p 前面,而不是 *p++,因为我想
先递增 p,然后再解引用。如果我执行 *p++,它会处理
Aa012345 或者任何字符串两次。
下面是代码,里面有注释,我认为不难理解。
只需注释掉两个 #define 指令,保留您想尝试的那个
未注释,然后设置断点,看看它是如何工作的。
要运行代码,如果您使用的是
Microsoft Visual Studio,只需创建一个新的 Windows 控制台应用程序。如果您使用的是其他工具,只需将
代码复制粘贴到您的 Main 函数中即可。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103
|
/************************************************************************/
/*
this example shows the equivalence in pointer math between
array p[i]
offset *(p+i)
increment p++ p++ ..... i number of times
example p[3] = *(p+3) = p++ p++ p++
*/
//#define _use_offset_
//#define _use_array_
#define _use_increments_
#ifdef _use_offset_
cout << "using offset\n";
#endif
#ifdef _use_array_
cout << "using array\n";
#endif
#ifdef _use_increments_
cout << "using increments\n";
#endif
int j;
/*
declare and initialize the sparse matrix of characters
or the array of string, whichever fits.
*/
char** array_of_strings = new char*[26];
for (int i = 0; i < 26 ; i++)
{
#ifdef _use_offset_
/*
using offsets
instead of changing the pointer, just use
and offset from it all the time. the i is the
vertical offset into the table of strings
while the j is the horizontal. j = x and y = i
in vector terminology.
*/
*(array_of_strings+i) = new char(toascii(65+i));
*(*(array_of_strings+i)+1) = char(toascii(97+i));
for (j = 2; j < rand() % 16 + 2; j++)
*(*(array_of_strings+i)+j) = char(toascii(48+j-2));
*(*(array_of_strings+i)+j) = '\0';
#endif
#ifdef _use_array_
/*
using arrays
the simplest and prefered way because is more
readable and cleaner. just use array indexes
[y][x] or [i][j]
*/
array_of_strings[i] = new char(toascii(65+i));
array_of_strings[i][1] = char(toascii(97+i));
for (j = 2; j < rand() % 16 + 2; j++)
array_of_strings[i][j] = char(toascii(48+j-2));
array_of_strings[i][j] = '\0';
#endif
#ifdef _use_increments_
/*
use increments
here we change the pointers instead of using offsets
like p+i we actuaqlly increment the pointers p++
two things we need a two pointers the vertical pointer
and the horizontal pointer which actually points to
each string. array_of_strings is the verticaal and
new_string is the horizontal and the one which
points to the string and we use to modify the strings.
before printing out the strings we need to reset
the vertical pointer array_of_strings back to the
to the beginning so we simply subtract 26 from it
because we incremented it 26 times.
*/
char* new_string = *array_of_strings++ = new char(toascii(65+i));
*++new_string = char(toascii(97+i));
for (j = 2; j < rand() % 16 + 2; j++)
*++new_string = char(toascii(48+j-2));
*++new_string = '\0';
#endif
}
#ifdef _use_increments_
array_of_strings = array_of_strings - 26;
#endif
for (int i = 0; i < 26 ; i++)
{
#ifdef _use_offset_
cout << *(array_of_strings+i) << endl;
#endif
#ifdef _use_array_
cout << array_of_strings[i] << endl;
#endif
#ifdef _use_increments_
cout << *array_of_strings++ << endl;
#endif
}
/************************************************************************/
|