C指针算术[英] C pointer arithmetics

本文是小编为大家收集整理的关于C指针算术的处理方法,想解了C指针算术的问题怎么解决?C指针算术问题的解决办法?那么可以参考本文帮助大家快速定位并解决问题。

问题描述

这是我不理解的代码,它只是反转字符串.

#include <stdio.h>

void strrev(char *p)
{
  char *q = p;
  while(q && *q) ++q;
  for(--q; p < q; ++p, --q)
    *p = *p ^ *q,
    *q = *p ^ *q,
    *p = *p ^ *q;
}

int main(int argc, char **argv)
{
  do {
    printf("%s ",  argv[argc-1]); strrev(argv[argc-1]);
    printf("%s\n", argv[argc-1]);
  } while(--argc);

  return 0;
}

我唯一不明白的代码是:while(q && *q) ++q;,它用于查找eos. 它与while(*q) ++q;不一样,因为q永远不会是0?代码的作者如何确保q或*q将为0?

此代码来自此问题:您如何在C或C ++中反转字符串?

推荐答案

大卫·赫弗南(David Heffernan)的评论是正确的.该代码令人震惊.

您要问的代码的要点是如果是null,则跳过删除q.因此,《代码》的作者认为q可能是无效的.在什么情况下,q无效?最明显的是:如果p为null.

所以让我们看看代码在p为null时的作用.

void strrev(char *p) // Assumption: p is null
{
  char *q = p; // now q is null
  while(q && *q) ++q; // The loop is skipped, so q and p are both still null.
  for(--q; 

因此,我们要做的第一件事是减少Q,这是无效的.这可能会缠绕,因此我们将获得包含最大可能的指针.

的Q
    p < q; 

由于null比Null以外的所有内容都小,并且Q不再为空,因此这是正确的.我们输入循环...

    ++p, --q)
    *p = *p ^ *q,

并立即取消null.

    *q = *p ^ *q,
    *p = *p ^ *q;
}

顺便说一句,在覆盖率上,我们将其称为"正向null缺陷" - 即,代码路径表示值可能为null的模式,然后在同一代码路径上假定该值它不是零.这是非常普遍的.

好的,因此如果将null作为参数,则此代码将完全断开.还有其他方法被打破吗?如果我们给它一个空字符串会怎样?

void strrev(char *p) // Assumption: *p is 0
{
  char *q = p; // *q is 0
  while(q && *q) ++q; // The second condition is not met so the body is skipped.
  for(--q; // q now points *before valid memory*.
       p < q  // And we compare an invalid pointer to a valid one.

我们是否有C中的保证,说当您从指针中减去有效内存时,然后将该指针比较到另一个指针时,比较是明智的?因为这使我非常危险.我不太了解C标准,无法说出这是否是不确定的行为.

此外,此代码使用可怕的"与XOR交换两个字符"的技巧. 为什么有人会这样做?它会生成更大,较慢的机器代码,并且很难阅读,理解和维护.如果您想交换两件事,交换它们.

它还使用逗号操作员将多个语句放入单个语句中,以避免for身体周围的牙套的恐怖.这种奇怪的目的是什么?代码的目的不是要显示您认识多少运算符,它首先是与代码的读者通信.

该功能还修改了其形式参数,这很难调试.

其他推荐答案

代码

while(q && *q)

的速记
while(q != NULL && *q != '\0')

因此,您正在测试q(在等于p的开始时)不是零.这意味着用null参数调用的函数不会在循环时不会崩溃. (但是它仍将在第二个循环中崩溃).

其他推荐答案

它与while(*q) ++q;不一样,因为q永远不会是0?

while(q && *q)用于确保q不是NULL和*q不是NUL.如果q不指向NULL,则使用while(*q)也是合法的.

void string_rev(char *p)
{
   char *q = p;

   if(q == NULL)
       return;

   while(*q) ++q;
   for(--q; p < q; ++p, --q)
       *p = *p ^ *q,
       *q = *p ^ *q,
       *p = *p ^ *q;

}  

代码的作者如何确保q或*q将是0?

while(q && *q),q如果p指向NULL,则可以是NULL指针,然后在输入环形主体之前终止循环.否则,整个操作都不能是NULL指针.现在,循环终止取决于*q.一旦q到达字符串的末端,*q变成0并终止.

本文地址:https://www.itbaoku.cn/post/359390.html