C-由一个错误关闭
在以下简单的反转函数中,我总是以1为关,这意味着传入的第一个字符永远不会像应该的那样打印到最后:C-由一个错误关闭,c,C,在以下简单的反转函数中,我总是以1为关,这意味着传入的第一个字符永远不会像应该的那样打印到最后: void reverse(char * c) { if(*c != '\0') { reverse(++c); printf("%c", *c); } else { return; } } 然而,当我将调用更改为reverse为c+1时,一切都正常。任何关于为什么的想法,一元预增量运算符应该与c+1完全相同
void reverse(char * c)
{
if(*c != '\0')
{
reverse(++c);
printf("%c", *c);
}
else {
return;
}
}
然而,当我将调用更改为reverse为c+1时,一切都正常。任何关于为什么的想法,一元预增量运算符应该与c+1完全相同。我知道递归函数不是解决这个问题的最佳方法,但我现在只是在试验。谢谢 因为
c+1
不会改变c
,而++c
会改变
当c
指向地址1234
时,请考虑这一点:
reverse(++c); // c is now 1235 and you pass that.
printf("%c", *c); // so we print the second character at 1235.
对于c+1
版本:
reverse(c+1); // c is still 1234 but you pass 1235.
printf("%c", *c); // so we print the first character at 1234.
值得一提的是,您的
reverse
函数是不必要的复杂。else return
是冗余的,我个人更喜欢先检查终止条件的递归调用,因为我经常发现编译器通常更容易对其进行尾部递归优化
以下完整的测试程序向您展示了我的方法:
#include <stdio.h>
void reverse (char *c) {
if (*c == '\0') return;
reverse (c + 1);
putchar (*c);
}
int main (int argc, char *argv[]) {
int i;
for (i = 1; i < argc; i++) {
reverse (argv[i]);
putchar ('\n');
}
return 0;
}
因为
c+1
不会改变c
,而++c
会改变
当c
指向地址1234
时,请考虑这一点:
reverse(++c); // c is now 1235 and you pass that.
printf("%c", *c); // so we print the second character at 1235.
对于c+1
版本:
reverse(c+1); // c is still 1234 but you pass 1235.
printf("%c", *c); // so we print the first character at 1234.
值得一提的是,您的
reverse
函数是不必要的复杂。else return
是冗余的,我个人更喜欢先检查终止条件的递归调用,因为我经常发现编译器通常更容易对其进行尾部递归优化
以下完整的测试程序向您展示了我的方法:
#include <stdio.h>
void reverse (char *c) {
if (*c == '\0') return;
reverse (c + 1);
putchar (*c);
}
int main (int argc, char *argv[]) {
int i;
for (i = 1; i < argc; i++) {
reverse (argv[i]);
putchar ('\n');
}
return 0;
}
使用
c+1
调用不会更改本地上下文中c
的值(打印*c
时使用的值),但在调用中使用++c
会更改c+1
调用不会更改本地上下文中c
的值(打印*c
时使用的值),但是在调用中使用++c
将是有效的。修复了该问题:您不应该使用增量运算符。操作员+会更好
reverse(c + 1);
printf("%c", *c);
已修复:不应使用增量运算符。操作员+会更好
reverse(c + 1);
printf("%c", *c);
不,它不会做同样的事情
它将其递增,然后将其发送到您的函数 不,它不会做同样的事情
它将其递增,然后将其发送到您的函数 不,一元预增量与一元相加不同
f(++c)
相当于
c = c + 1
f(c);
auto d = c + 1;
f(d);
而f(c+1)
相当于
c = c + 1
f(c);
auto d = c + 1;
f(d);
为了完整起见:f(c++)
与
f(c);
c = c+1;
P>但是序列点是重要的,如<代码>(C++ > 0和C+++< 10)< /> >将像一样评价。
auto a = c;
c = c + 1;
auto b = c;
c = c + 1;
if(a > 0 || b < 10) { /* ... */ }
自动a=c;
c=c+1;
自动b=c;
c=c+1;
如果(a>0 | | b<10){/*…*/}
并因此预增量
c = c + 1;
auto a = c;
c = c + 1;
auto b = c;
if(a > 0 || b < 10) { /* ... */ }
c=c+1;
自动a=c;
c=c+1;
自动b=c;
如果(a>0 | | b<10){/*…*/}
否一元预增量与一元相加不同
f(++c)
相当于
c = c + 1
f(c);
auto d = c + 1;
f(d);
而f(c+1)
相当于
c = c + 1
f(c);
auto d = c + 1;
f(d);
为了完整起见:f(c++)
与
f(c);
c = c+1;
P>但是序列点是重要的,如<代码>(C++ > 0和C+++< 10)< /> >将像一样评价。
auto a = c;
c = c + 1;
auto b = c;
c = c + 1;
if(a > 0 || b < 10) { /* ... */ }
自动a=c;
c=c+1;
自动b=c;
c=c+1;
如果(a>0 | | b<10){/*…*/}
并因此预增量
c = c + 1;
auto a = c;
c = c + 1;
auto b = c;
if(a > 0 || b < 10) { /* ... */ }
c=c+1;
自动a=c;
c=c+1;
自动b=c;
如果(a>0 | | b<10){/*…*/}
当您放置c+1
时,它不会更改c
的值,但++c
会更改c
的值。。作为增量前后运算符之间差异的示例:
int a = 1;
int b = ++a;
// Now a is 2 and b is also 2.
int a = 1;
int b = a++;
// Now a is 2 but b is 1.
当您放置
c+1
时,它不会更改c
的值,但++c
会更改c
的值。。作为增量前后运算符之间差异的示例:
int a = 1;
int b = ++a;
// Now a is 2 and b is also 2.
int a = 1;
int b = a++;
// Now a is 2 but b is 1.
我想是这样的,但接下来可以论证的就是按原始顺序打印字符串。这会使它反转的原因是,它到达末尾,然后从每个函数返回,并在运行过程中打印出来。我认为,但可以说,这样做的全部工作就是按原始顺序打印字符串。这将使其反转的原因是,它到达末尾,然后从每个函数打印出来返回。使用
char
而不是auto
,将其从伪C转换为C。顺便说一下f(C++,C++)
是未定义的行为,用于在没有序列点的情况下修改C
两次,auto a=c
与int a=c
相同,而与c
的类型无关。Yay implicit int.@Zack:我知道这一点,但是我想避免使用特定类型来保持对变量名的关注,但要明确这是在局部范围内。使用char
而不是auto
,将其从伪C转换为C。顺便说一下f(C++,C++)
是未定义的行为,用于在没有序列点的情况下修改c
两次。在c中,auto a=c
与int a=c
相同,无论c
的类型如何。Yay implicit int.@Zack:我知道这一点,但我想避免使用特定类型来保持对变量名的关注,但要明确这是在局部范围内。