那么就解释一下吧:
// prob.1
f(i)
{
// 逻辑条件表达式 a && b 在 a 为真时才去检验b的值。
// 这里在 i 为真的时候,才去执行后面的部分。为真也就是不为 0
i && (f(i/10),printf("%d\n",i));
// 而后半部分是一个逗号表达式。以这种形式出现 a,b
// 从左往右依次执行。逗号表达式的返回值为最右侧的值 b
// 不过这里对这个值并不关心。
// 这里出现了递归,把i的值除10,其实就是十进制数中去掉个位数字
// 这里的调用次序是先递归,后输出,
// 所以可以得到短的数字在前面,而整个数字在后面的效果
// i 值的判断其实是对递归调用的限制,由于递归时每次都除 10,
// 可以预见最终这个整型参数将为 0,从而结束递归。
}
main()
{
f(12345); // 这里直接给最大的那个值。
}
// prob.2
f(i)
{
// 这里要注意 && 与逗号两个运算符的优先级,&&高,所以不必加括号
printf("%d\n",i), i>1&&f(i/10);
// 同样是递归,这时是先输出数据再递归调用,所以得到长的数字在前面
// 与上面类似 i>1 用来做为递归调用的限制条件。
// 不同的是这里在i为 1 时就要结束递归,否则将输出0
// 这里其实有个问题,如果需要输出的是 23456 这个数,那么将得到一个多余的0
// 也就是与 1 比大小恰好是这个题的特例,正确的想法应该是
// i 这个数是否为 2 位数,也就是写成 i>9
}
main()
{
f(12345);
}
// prob.3
f(char*s)
{
// 仍然是递归,所不同的是参数是一个字符串
printf(s), *s&&f(s+2);
// 这里要特别小心,字符串是连续存储的一串字符,末尾有一个 '\0' 也就是数字 0。
// 由于 s 每次加 2 做 *s 这个判断有一定的危险,
// 假如串的内容不是奇数个字符,那么在最后一次 s+2 时直接越过了
// 字符串的末尾 '\0',然后程序将继续递归直到偶然地遇到一个0。
// 安全的做法是在字符串末尾多加1个'\0'
}
main()
{
f("* * * * * * *\n"); // 这里恰好是奇数个字符.不然得这么写"* * * *\n\0"
// 除了天然的一个结束标志,还有你人为的一个字符。保证了 s+2 不可能一口气跳过这个'\0'区域
}