2014-01-14 32 views
5

我有一些关于反转空终止的C字符串的概念性问题,并澄清了有关指针性质的问题。反转' 0'结尾的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 */ 
     } 
    } 
} 
+2

如果你真的在传递''opal'''这将是未定义的行为,因为你不允许修改字符串。 –

+0

@ShafikYaghmour你会通过什么? – Opal

+0

char数组,char arr [] =“opal”;'。 –

回答

8

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

/*不*海峡=蛋白石或不*海峡= O,因为指针str是char类型? */

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

/*是什么字符*结束与char *端之间的区别?并且*结束现在指向蛋白石?*/

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

char* a, b; 

,因为这相当于

char *a, b; 

,而不是它变得棘手,因为你可能会认为

char *a, *b; 

这就是为什么它是清洁写char *end;

end指向opal - *end'o'

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

是 - 你没有获得通过一个空指针

要测试你没有获得通过长度为0的字符串测试,你就必须测试*str(测试后str不为空,否则你会得到 “大胆看* NULL”)

而(STR <末){/ *为什么不*海峡< *结束分割错误?这是问,而升? */

测试指针 - 一个正在走向最后,另一个正在后退。当你在中间相遇时,你停下来;否则你做交换两次,不会有实际效果...

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

你首先*end值复制到*str,那么你递增str指针。如果你输入++str,你首先增加,然后使用它。这就意味着你把l代替p而不是o

编辑您的代码一个批判(超出你问的问题,并响应从@chux评论):当你测试if(str){}你真的需要一个else return;声明,因为你实际做end--;然后用*end。敢肯定,0xFFFFFFFFFFFFFFFF几乎都是无效的地址...

如果你实际上是if(*str!='\0')正在测试,那么你应该还只是返回(空字符串是“不可逆的” - 或者更确切地说,它不需要什么被认为是相反的)。顺便说一下,我更喜欢使条件明确(就像我刚才那样);它不仅更清楚地显示你的意图,而且编译器可能实际上抱怨,如果你做了if(str!='\0')if(*str != NULL),因为你正在比较的类型是不兼容的。这意味着您将拥有更健壮,更具可读性且更可能按照您的意图完成工作的代码。

+1

如果可以,我会再次给你+1个关于最后一段中显式测试的意见。 –

+0

@JonathanLeffler--我很可能在去年的某个时候通过阅读你的答案/评论来了解这种方法的重要性。是的,我主要是在这里学习,尽管我试图回答问题。谢谢你的称赞! – Floris

2

不* STR =蛋白石或不* STR = O由于指针str是类型char?

str是指针的opal第一元件,即,它是指向第一个字母o。因此,*s表示您提及s(第一个地址),因此它是'o'

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

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

如果str不为空?

是。

结束指针指向到L现在

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

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

*str++装置后的值解除引用str指向str将递增。 ++str只需预增加str即可。
*str++ =在递增str之前将值赋给解除引用的变量。

+0

Woooooo!为什么要投票? – haccks

+0

我没有投票,别人必须拥有。我只是编辑了这个问题来通过'char arr [] =“opal”;' – Opal

+0

@Opal;现在编辑。 – haccks

2

does * str = opal或does * str = o因为指针str是char类型吗?

*str取消引用指针,这是char*类型的,所以你得到的类型是charchar将是str指向的值,它将是'o'

是什么字符*结束与char *端之间的区别?

什么都没有。

,是*端指向现在欧泊?

是啊,很近。 end指向与str完全相同的地址,这是您的字符串的开始。 *end是一种字符类型,不是指针。它的值将是'o'

STR如果不是null?

更正,对指针进行布尔测试是标准测试。如果指针不为空,它将评估为“真”值,否则评估为“假”。请注意,这与零值不同。 C标准允许任何值表示空地址。

为什么不* str < *结束?这是问,而升?

不,这是比较实际的内存地址。它说要循环,而str指向比end更早的部分。你会注意到在循环中,str增加,并且end减少。所以最终他们会通过彼此或相同的字符(,即字符串的中间)相遇。

是什么*海峡++和++海峡之间的区别? * str ++ = l?

str++首先被施加,其递增str并返回其先前的值,则*一元运算符derferences在那个旧位置得到的字符。是的,第一次来自end'l'将被分配到字符串的开始处(其中str用于在它被递增之前指向)。 tmp用于携带旧字符并将其分配给end。这是一个标准的“交换”操作。

1

确实*str = opal或确实*str = 'o'由于指针str是类型char

这是两个。我知道这是令人困惑的,但是这里是发生了什么:在C中,可以用两种方式来解释指针 - 无论是字面上的,也就是作为指向单个项目的指针(在这种情况下为char),或者作为指向开头的指针相同类型的项目序列。在后面的情况下,序列的末尾将被定义。有三种方法可以知道序列的结束位置 - 通过明确了解长度,了解结束指针或在序列末尾放置“终止符”项。在C字符串的情况下,使用称为“空终止符”的特殊字符'\0'来终止序列。

char* endchar *end有什么区别?并且是*end现在指向蛋白石?

绝对没有区别 - 它们都指向相同的地方。星号的放置无关紧要。

if str is not null?现在

正确

end指针指向'l'

绝对!

为什么不是*str < *end?这是要求while o < l

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

tmp = o

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

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

++str表达递增指针的值,并计算结果为增量后的指针的值; *str++表达式递增指针的值,并且评估为指针之前指向的字符的值。

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

及以下,关于价值,都是如此:

  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'

关于NULL,当指针是未初始化的,即,没有指向有效的内存,它应该分配的NULL的值,这在大多数情况下是地址0考虑以下几点:

char *str = NULL; 
reverse(str); 

当以下表达式求值:

if(str) 

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

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

--end; 

会导致不确定的行为。

+1

这并不包括问题中的所有问题。 –

+0

@JonathanLeffler你是对的,但如果你能理解这一点,其他问题的答案就会变得明显。 –

+0

@Awwww。不,但同意Jonathan Leffler:D – haccks