开发者

C - Off by one error

开发者 https://www.devze.com 2023-02-25 07:36 出处:网络
in the following simple reverse function I\'m always off by one, meaning the first character passed in is never printed last like it should be:

in the following simple reverse function I'm always off by one, meaning the first character passed in is never printed last like it should be:

  void reverse(char * c)
{
    if(*c != '\0')
    {
        reverse(++c);
        printf("%c", *c);
    }
    else {
        return;
    }
}

yet when I change the call to reverse to be c+1, everything works fine. Any ideas as to why, the unary pre-increment operator should be doing exactly the same as c + 1. I know a recursive function isn't the best performing way to go about this problem but I'm jus开发者_开发知识库t experimenting at the moment. Thanks!


Because c+1 does not change c whereas ++c does.

Think about this when c is pointing to address 1234:

reverse(++c);      // c is now 1235 and you pass that.
printf("%c", *c);  // so we print the second character at 1235.

With the c+1 version:

reverse(c+1);      // c is still 1234 but you pass 1235.
printf("%c", *c);  // so we print the first character at 1234.

For what it's worth, your reverse function is needlessly complicated.The else return is redundant and I personally prefer recursion calls that check terminating conditions first since I've often found these are usually easier for compilers to do tail-end recursion optimisations on.

The following complete test program shows you the way I'd do it:

#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;
}

Running this with testprog hello goodbye gives you:

olleh
eybdoog


No the unary pre-increment is not the same like addition by one.

f(++c) is equivalent to

c = c + 1
f(c);

whereas f(c+1) is equivalent to

auto d = c + 1;
f(d);

And just for completeness: f(c++) is the same like

f(c);
c = c+1;

However sequence points matter, e.g. if(c++ > 0 && c++ < 10) would evaluate like

auto a = c;
c = c + 1;

auto b = c;
c = c + 1;

if(a > 0 || b < 10) { /* ... */ }

and consequently preincrement

c = c + 1;
auto a = c;

c = c + 1;
auto b = c;

if(a > 0 || b < 10) { /* ... */ }


Calling with c + 1 won't change the value of c in the local context (the one used when printing *c), but using ++c in the call will.


No, it doesn't do the same thing.

It increments it then sends it to your function.


when you put c+1, it doesn't change the value of c, but ++c does change the value of c.. as an example for difference between pre and post increment operators:

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.


FIXED: You shouldn't use increment operator. Operator+ would be better.:

reverse(c + 1);
printf("%c", *c);
0

精彩评论

暂无评论...
验证码 换一张
取 消