指针上的 For 循环:它会移动整个地址范围吗?
For-Loop on Pointer: Does it move the whole address range?
我有这段代码:
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
前进,直到到达*p
0
的点 - 字符串的末尾。
如果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;
}
- 将数组的地址分配给变量并删除
- 为什么在全局范围内使用"extern int a"似乎不行?
- 空基优化子对象的地址
- C++ 指针的内存地址和指向数组的内存地址如何相同?
- 指向地址的指针似乎调整在范围之外
- 在 gcc/clang (C++) 中获取函数范围之外的标签地址
- 如何找到在本地范围内声明的变量的地址?
- 指针上的 For 循环:它会移动整个地址范围吗?
- 如何使用C或C 查找给定的IPv6地址是否属于CIDR范围
- 如何刷新CPU缓存中的地址范围?
- 变量循环范围会导致返回局部变量的地址引用
- C 线程堆栈地址范围
- IP 地址重叠/在 CIDR 范围内
- 本地变量的地址不在smaps显示的堆栈地址范围内
- x86-64上检查指针范围是否跨越N字节对齐地址的最快方法
- 从堆栈地址形成指针范围是未定义的行为吗
- 为什么运行得很好?(范围外变量的访问地址)
- 什么原因导致std::sort()访问超出范围的地址
- 是否有一种方法可以获得堆上可用的内存地址范围
- CUDA 运行时错误:未指定的启动失败 & 超出范围的共享或本地地址