指针上的 For 循环:它会移动整个地址范围吗?

For-Loop on Pointer: Does it move the whole address range?

本文关键字:地址 范围 移动 For 循环 指针      更新时间:2023-10-16

我有这段代码:

int count_x(char* p, char x)
{
if (p == nullptr) return 0;
int count = 0;
for (; *p != 0; p++)
{
if (*p == x)
count++;
}
return count;
}

在本例中,输入是字符数组:

char v[] = { "Ich habe einen Beispielsatz erstellt!"};

由于我目前正在通过"C++编程语言 - 第 4 版"一书研究 CPP,我从那里获得了代码,目前正在尝试弄清楚。

在单步执行时,我注意到 for 循环以 1 为增量移动内存地址。这对我来说并不奇怪,但是出现了以下问题,我还找不到答案: 此循环是减小了整体内存范围还是移动了整个范围?

据我所知,您整体使用"块"来存储这样的字符数组(或任何类型的数组(,我想是后者,因为我没有看到任何减少边界的东西。 但是有了这些"知识",我不得不问:这是否会导致重大问题,因为理论上可以读取程序不应该访问的部分内存?

这是我在处理(非常(长数组时必须记住的事情吗?

你根本没有移动任何东西。这就是你的困惑的来源。您的代码对于非常非常长的字符串是完全安全的,别担心。(除此之外,count可能会溢出...

你是对的,p在循环的每次迭代中都会递增,但这并不意味着任何东西都被移动了。您只是在修改指针的值p(和count(。就是这样。实际上,您正在遍历RAM。

但是,您可能会在内存中读取您不拥有的内存,但这是调用方的错误,因为count_x的前提条件要求您传入以 null 结尾的字符串,如果您不这样做,那么,您将获得访问您不拥有的内存的未定义行为。这就是为什么你应该使用std::string而不是char*,这保证以 null 结尾(如果您使用 C++11 或更高版本(。

在 C 和 C++ 中,"strings like this"是隐式以 nul 结尾的。 这意味着它们以值为0''(同一件事(的char结尾。

所以这个循环:

for (; *p != 0; p++)

p前进,直到到达*p0的点 - 字符串的末尾。

如果p不指向以 nul 结尾的缓冲区或字符串,则循环确实会在内存上移动到它启动的内存缓冲区的末尾之外。这种错误很常见,并且依赖于字符串被 nul 终止会导致(间接(大量缓冲区溢出、安全漏洞以及通常崩溃和内存损坏的程序。

为了解决这个问题,C++提供了存储字符字符串和与之交互的替代方法,包括std::string. 这些不依赖于正确定位的 nul 终止符来工作,尽管它们可能与之交互的许多 C 样式代码。

在 C++17 中,字符串视图提供了一种非拥有的低成本方法来引用没有 NUL 终止符的有界大小字符串。

(非常(长的数组没有问题。因为 count_x((,所以你传递数组第一个字符的地址。因此,任何长度的数组都没有开销。您可以在所有数组上遍历带有点的索引。肖

unsigned int count_x(char* p, char x)
{
if (p == nullptr) return 0;
unsigned int count = 0;
for (unsigned int i=0; i<strlen(p); i++)
{
if (p[i] == x)
count++;
}
return count;
}