指针上的For-Loop:是否会移动整个地址范围?

时间:2017-08-18 00:42:27

标签: c++ arrays c++11

我有这段代码:

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-array:

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

因为我目前正在阅读CPP这本书" C ++编程语言 - 第4版"我从那里得到了代码,目前我正试图解决它。

当单步执行时,我注意到for循环以1为增量移动内存地址。这对我来说并不是很令人惊讶,但是出现了以下问题,我还没有找到答案: 这个循环是否会减少整个内存范围,还是整个范围都会移动?

从我的知识开始,你使用"块"整个存储这样一个char数组(或任何类型的数组),我想这是后来因为我没有看到任何减少边界的东西。 但随着那个"知识"我不得不问:这不会导致重大问题,因为理论上可以读取程序不应该访问的部分内存吗?

这是处理(非常)长阵列时必须记住的事情吗?

3 个答案:

答案 0 :(得分:4)

你根本不动任何东西。这就是你的困惑来自哪里。你的代码对于非常长的字符串是完全安全的,不用担心。 (除了count可能会溢出......)。

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

你是对的,你可能会在内存中读到你不拥有的内容,但这是调用者的错误,因为count_x的先决条件要求你传入一个以空字符结尾的字符串,如果你没有嗯,你得到未定义的行为来访问你不拥有的内存。这就是为什么你应该使用std::string而不是char*,这保证是空终止的(如果你使用C ++ 11或更高版本)。

答案 1 :(得分:3)

在C和C ++中,"strings like this"隐式为空终止。这意味着它们的结尾为char,其值为0'\0'(同样的事情)。

所以这个循环:

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

提升p,直至达到*p0的点 - 字符串的结尾。

如果p没有指向以nul结尾的缓冲区或字符串,那么循环确实将在内存超出其启动的内存缓冲区的末尾移动。这种错误很常见并且依赖于字符串nul-terminated结果(间接)导致许多缓冲区溢出,安全漏洞,以及通常崩溃和内存损坏的程序。

为了解决这个问题,C ++提供了另外的方法来存储和交换字符串,包括std::string。虽然它们与之交互的C风格代码很多,但它们并不依赖于正确定位的nul终结符。

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

答案 2 :(得分:0)

(非常)长阵列没问题。因为count_x(),你传递数组的第一个char的地址。因此任何长度的数组都没有开销。你可以使用指向遍历所有数组的索引。看起来像

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;
}