HackerYoung
HackerYoung

Reputation: 158

Does anyone think there is something wrong in The C Programming Language 2E Page29?

I am currently studying the well-known book for C - The C Programming Language, 2Ed. And when I trying the code in P.29, I think there is something wrong in the getline function:

int getline(char s[], int lim) {
    int c, i;

    for (i=0; i<lim-1 && (c=getchar()) != EOF && c!='\n'; i++)
        s[i] = c;
    if (c == '\n') {
        s[i] = c;
        i++;
    }

    s[i] = '\0';
    return i;
}

What if when the for loop ended, i == lim-1 and c == '\n'? In this case, I think the array would be out of boundary, since s[lim] would be set to '\0'.

Does anyone think this is wrong? Thanks for your help.

Upvotes: 5

Views: 168

Answers (5)

Vaughn Cato
Vaughn Cato

Reputation: 64308

It isn't possible for i to be lim-1 and c to be '\n' at the same time. If i==lim-1, then i<lim-1 will be false, so it will never read the next character. If c was '\n', then the loop would have terminated before i got to be lim-1.

The loop is equivalent to this:

i=0;
while (i<lim-1) {
    c = getchar();
    if (c==EOF) break;
    if (c=='\n') break;
    s[i] = c;
    i++;
}

Upvotes: 0

Bill Lynch
Bill Lynch

Reputation: 81936

So, let's look at some cases:

If lim == 0:, then this will do undefined behavior. There's two places this will happen:

  • We will execute no iterations of the for loop, giving i == 0 and c == undefined.
  • We then access c at (c == '\n'). It has no defined value yet, so it's undefined behavior.
  • We then cause undefined behavior again by overflowing s with: s[i] = '\0';

What if lim == 1:

  • The for loop will not be run, because the condition is not met.
  • We will hit undefined behavior just like in lim == 0 because c has no value.
  • The last line will work fine.

What if lim == 2, and the input string is "ab":

  • The for loop will grab 'a', and place it into s.
  • The for loop will exit on the next iteration, with the value of c still being 'a'.
  • The if conditional fails.
  • The adding of the null character works fine.
  • So s == "a\0"

What if lim == 2 and the input string is "a\n" (Which is the case you're worried about):

  • The for loop will grab 'a', and place it into s.
  • The for loop will exit on the next iteration, with the value of c still being 'a'.
  • The if conditional fails.
  • The adding of the null character works fine.
  • So s == "a\0"

Upvotes: 2

chux
chux

Reputation: 153517

I think you are correct. - but in a different way. There may have been is a problem. Should the limit be reached i==lim-1, and c had the value \n from the previous loop - but this can not happen as the previous loop c!='\n' would have exited.

This is a problem with lim <=1. The for loop exits, and c is not intiialized yet, thus undefined behavior with if (c == '\n'). Could be fixed with

int c = 0;

As mentioned by others, there is an additional problem with lim = 0 and s[i] = '\0';

Upvotes: 0

haccks
haccks

Reputation: 106022

Loop will continue until the condition i < lim-1 is true.When i == lim - 1, condition for loop becomes false and loop will terminate, and last element of array will stored in s[lim -2].It will not go out of boundary.

Upvotes: 0

caf
caf

Reputation: 239051

The && operator has "early-out" semantics. This means that if i == lim-1, the rest of the condition is not executed - in particular, c = getchar() will not be called.

This means that in this case, c will have its value from the last iteration of the loop - and since the loop condition includes c != '\n', this value can't be '\n' (or the loop would have exited last time around).

This is true as long as lim is greater than 1, which must be a precondition of the function (because calling the function with lim less than or equal to 1 would cause the uninitialised value of c to be read).

Upvotes: 4

Related Questions