反转'\ 0'终止的C字符串?

时间:2014-01-14 01:34:14

标签: c pointers reverse dereference

我有一些关于反转空终止C字符串的概念性问题,以及关于指针性质的澄清问题。

输入可能是

char arr[] = "opal";

和代码:

void reverse(char *str) {  /* does *str = opal or does *str = o since the pointer str is type char? */

    char* end  = str; /* what is the difference between char* end and char *end? and is *end pointing to opal now? */

    char tmp;

    if (str) {  /* if str isn't null? */
        while (*end) 
            ++end; 
    }
    --end; /* end pointer points to l now */

    while (str < end) {     /* why not *str < *end? is this asking while o < l? */
        tmp = *str; /* tmp = o */

        *str++ = *end; /* what is the difference between *str++ and ++str? does *str++ = l? */
        *end-- = tmp; /* *end points to o */
        }
    }
}

5 个答案:

答案 0 :(得分:9)

很多问题......试图捕捉每个问题的答案:

  
    

/ *做* str = opal或者* str = o,因为指针str是char类型? * /

  

*str'o',因为它指向第一个字符

  
    

/ * char * end和char * end有什么区别?现在是*结束指向蛋白石? * /

  

char *endchar* end之间没有区别。当你写

时会变得更加棘手
char* a, b;

因为这相当于

char *a, b;

而不是,你可能会认为

char *a, *b;

这就是为什么写char *end;更清晰。

end现在指向opal - *end'o'

  
    

if(str){/ *如果str不为空? * /

  

是 - 测试你没有通过NULL指针

为了测试你没有传递一个长度为0的字符串,你必须测试*str(在测试str不是NULL之后,否则你会得到一个“daring to”的分段错误看看* NULL“)

  
    

while(str&lt; end){/ *为什么不* str&lt; *结束?这是在问o&lt; L· * /

  

测试指针 - 一个正在向末端移动,另一个正在向后移动。当你在中间相遇时,你会停下来;否则你做两次交换,并且没有净效果......

  
 *str++ = *end; /* what is the difference between *str++ and ++str? does *str++ = l? */
  

首先将*end的值复制到*str,然后递增str指针。如果你放++str,先增加,然后再使用它。这意味着您将l代替p而不是代替o

编辑对您的代码进行一次批评(超出您提出的问题,并回复@chux的评论):当您测试if(str){}时,您确实需要{{1} }}语句,因为您实际执行else return;然后使用end--;。很确定*end几乎总是无效的地址......

如果您实际上正在测试0xFFFFFFFFFFFFFFFF,那么您仍然应该返回(空字符串是“不可逆转的” - 或者更确切地说,它不需要被视为反转)。

顺便说一句,我更喜欢明确表达这个条件(就像我刚才那样);它不仅更清楚地表明您的意图,而且如果您执行if(*str!='\0')if(str!='\0'),编译器可能会抱怨,因为您要比较的类型不兼容。这意味着您将拥有更强大,更易读且更有可能实现预期目标的代码。

答案 1 :(得分:2)

  

是* str = opal还是* str = o因为指针str是char类型?

str是指向opal的第一个元素的指针,即它是指向第一个字母o的指针。因此,*s表示您取消引用s(第一个地址),因此它是'o'

  

char * end和char * end有什么区别?现在是*结束指向蛋白石?

没有区别。不,它是end指向opal,即它现在的第一个元素。

  

如果str不为null?

是。

  

结束指针指向l now

是。它现在指向该词的最后一个字母。

  

* str ++和++ str有什么区别? * str ++ = l?

*str++表示str在取消引用str指向的值后会递增。 ++str只是str的预增量 *str++ =在递增str之前将值分配给解除引用的变量。

答案 2 :(得分:2)

  

确实* str = opal或者* str = o,因为指针str是char?

类型

*str取消引用类型为char*的指针,因此您获得的类型为charchar将是str指向的值,'o'

  

char * end和char * end之间有什么区别?

没有

  

现在是*结束指向蛋白石吗?

是的,好吧,关闭。 end指向与str完全相同的地址,这是您的字符串的开头。 *end是字符类型,而不是指针。其值为'o'

  

如果str不为空?

正确,对指针进行布尔测试是标准测试。如果指针不为null,则计算为“true”值,否则为“false”。请注意,这与零值不同。 C标准允许任何值表示空地址。

  

为什么不* str&lt; *结束?这是在问o&lt;升?

不,它正在比较实际的内存地址。它表示循环,而str指向字符串的早期部分而不是end。您会注意到,在循环过程中,str会增加,end会减少。所以最终他们会相互传递或者以相同的角色相遇(中间的字符串)。

  

* str ++和++ str有什么区别? * str ++ = l?

首先应用

str++,它会递增str并返回其先前的值,然后是*一元运算符,以便在该旧位置给出字符。是的,第一次,来自'l'的{​​{1}}将被分配到字符串的开头(end用于在增加之前指向它)。 str用于携带旧字符并将其分配给tmp。这是标准的“交换”操作。

答案 3 :(得分:2)

假设reverse被调用如下:

char str[] = "opal";
reverse(str);

并且被分配给内存,例如,像这样:

Memory Address:   100   101   102   103   104
Memory Value:    ['o'] ['p'] ['a'] ['l'] ['\0']

关于地址,以下内容属实:

  1. str + 0 == &str[0] == 100
  2. str + 1 == &str[1] == 101
  3. str + 2 == &str[2] == 102
  4. str + 3 == &str[3] == 103
  5. str + 4 == &str[4] == 104
  6. 以下关于值的说法是正确的:

    1. *(str + 0) == str[0] == 'o'
    2. *(str + 1) == str[1] == 'p'
    3. *(str + 2) == str[2] == 'a'
    4. *(str + 3) == str[3] == 'l'
    5. *(str + 4) == str[4] == '\0'
    6. 关于NULL,当指针未初始化时,即未指向有效内存时,应为其分配NULL的值,在大多数情况下,该值为地址0.考虑以下内容:

      char *str = NULL;
      reverse(str);
      

      评估以下表达式时:

      if(str)
      

      它将评估为FALSE。在reverse内,它应该(您应该立即修复)return因为使用地址为NULL的指针会导致未确定的行为,例如分段错误。

      当地址为str时,将end的地址分配给NULL,然后将其递减:

      --end;
      

      会导致行为不确定。

答案 4 :(得分:1)

  

*str = opal还是*str = 'o',因为指针str的类型为char

两者都是。我知道这很令人困惑,但这是正在发生的事情:在C中,指针可以用两种方式解释 - 字面上,即作为指向单个项目的指针(在这种情况下为char)或作为指针一系列相同类型的项目的开头。在后一种情况下,将定义序列的结尾。有三种方法可以知道序列的结束位置 - 明确知道长度,知道结束指针,或者在序列的末尾放置一个“终止符”项。对于C字符串,使用名为“null terminator”的特殊字符'\0'来终止序列。

  

char* endchar *end之间有什么区别?现在是*end指向蛋白石吗?

绝对没有区别 - 他们都指向同一个地方。星号的位置无关紧要。

  

如果str不是null

正确

  

end指针指向'l'现在

绝对!

  

为什么不*str < *end?这问while o < l

您正在比较内存中的位置,而不是它们指向的字符。这要求指针不要相互“交叉”,因为这两个指针从字符串的两端走向中心。

  

tmp = o

在第一次迭代中,它是。在第二次迭代中,它指向'p'

  

*str++++str之间有什么区别?是*str++ = 'l'

++str表达式增加指针的值,并在增量后计算指针的值; *str++表达式增加指针的值,并计算指针增量之前指向的字符的值。