1

Currently learning C with 2nd Edition K&R book. I am confused with this example and how the value of my line variable is altered to the string from my getlines function.

int main()
{
  char line[MAXLINE];
  int found = 0;

  while (getlines(line, MAXLINE))
    printf("Test: %s\n", line);
}

int getlines(char s[], int lim)
{
  int c, i;
  i = 0;

  while (--lim > 0 && (c=getchar()) != EOF && c != '\n')
    s[i++] = c;

  if (c == '\n')
    s[i++] = c;
  s[i] = '\0';
  return i;
}

The program outputs "Test: [string from getlines]". If I never assigned "char line" to the return value from getlines and the fact that getlines returns an int, how did the value of "line" get assigned the string that I input into the variable "s"?

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
danx
  • 13
  • 3
  • 3
    While **K & R** is a classic, it is *decades* out of date. See: [**The Definitive C Book Guide and List**](https://stackoverflow.com/questions/562303/the-definitive-c-book-guide-and-list?s=2|7.6007). There have been 3+ revisions to the C standard since **K & R** – David C. Rankin Aug 11 '17 at 04:54
  • 1
    @DavidC.Rankin: There is nothing wrong with learning K&R. It is impressive how much of that flavor of C is directly supported by current compilers. – wallyk Aug 11 '17 at 04:56
  • Note, I didn't say there was anything *wrong* with it, I said it was decades old and outdated. K&R declarations have gone the way of the Dodo.... – David C. Rankin Aug 11 '17 at 04:57
  • @DavidC.Rankin: Hmmm... *decades out of date*: true. *See (another standard)*: suggests disregarding K&R. *3+ revisions since*: also suggests disregarding K&R. Ergo, you imply that K&R is not relevant. That sure seems to mean something like "wrong". – wallyk Aug 11 '17 at 05:03
  • 1
    I guess there is a lack of specificity, I was referring to the original printing prior to any C standard. Point taken. – David C. Rankin Aug 11 '17 at 05:06
  • @wallyk-- I think that there are better books to _learn_ C from the first time now. K & R was still using C89 in the 2nd edition, so no VLAs, no loop-scoped variables, the `register` keyword was more broadly useful, `gets()` was still a part of the language.... – ad absurdum Aug 11 '17 at 05:33
  • @wallyk There is lots of wrong with learning K&R. Just look at the code! Anyone who writes obscure code such as `while (--lim > 0 && (c=getchar()) != EOF && c != '\n')` needs to be slapped. Apart from being a long-winded expression, it violates two good programming practice rules: never mix ++ with other operations in the same expression and never use assignment in expressions. In addition, the code uses lax style without braces, which was the cause of the most expensive SW bug in history ("the Apple goto fail"). K&R is filled to the brim with crappily written code like this. – Lundin Aug 11 '17 at 06:47
  • Sane programmers would rather write something like `c = getchar(); for(size_t i=0; i – Lundin Aug 11 '17 at 06:50
  • In addition, K&R 2nd edition failed to take C89 in account in many places. The book has an extensive errata. Needless to say, there's not a trace of modern programming or later C standards in it. – Lundin Aug 11 '17 at 06:53

4 Answers4

2

You are apparently assuming that the function getlines() returns the string. It does not.

It returns the number of characters which were read into the line. The line[] variable in main is passed as a parameter to getlines which processes that parameter as variable s[]. Notice how it assigns characters to s[i++].

wallyk
  • 56,922
  • 16
  • 83
  • 148
1

getline() populates line when you passed it as an argument. The int returned is the status of the function after execution.

drum
  • 5,416
  • 7
  • 57
  • 91
1

In a C function call, all arguments are passed by value, so the function has a copy of them. Therefore it's never possible that the function changes an argument. Sounds like contradicting what you observe here, but it isn't:

Arrays in C are somewhat special. An array identifier is evaluated to the address of the array's first element (aka: a pointer) in almost any place (exceptions include the sizeof operator). It's impossible to assign an array, and it is impossible to pass an array (as a function argument or as a return value).

Again, this looks contradicting, but there's another rule for function declarations: If a function declaration includes an array type, this is automatically adjusted to the corresponding pointer type. So your function

int getlines(char s[], int lim);

is in fact the following function: *)

int getlines(char *s, int lim);

The effect of adjusting the type in a function declaration and evaluating the identifier of an array as a pointer together is often expressed as the array decays as a pointer. What really gets passed to your function is a pointer, not an array. Indexing that pointer, the code in the function accesses the original array. The pointer is of course passed by value and your function doesn't change this pointer, but it can change what it points to.


*) stylistic note: I prefer to always write the function declarations with pointer types, because this is what the compiler sees anyways, so it avoids confusion. Of course, some argue it's good to write the array type as it documents the intent that this function should be passed a pointer to an array.

0

If I never assigned "char line" to the return value from getlines

Correct, you never assign the return value from getlines to the variable line.

how did the value of "line" get assigned the string that I input into the variable "s"

When you do getlines(line, MAXLINE), the variable line although declared as an array "decays" to a pointer to the first element of the array when being passed. Then, in getlines when you are doing s[i++] = c;, you are actually writing the address (or some number of hops away from that address) that was passed to getlines. Remember that indexing an array s[i++] does an implicit dereference to i hops away from the address contained in s. Then, when you print line in your main function, you find that some information has been placed in the array.

babon
  • 3,615
  • 2
  • 20
  • 20