Thread: K&R example

  1. #1
    Registered User
    Join Date
    Sep 2009
    Posts
    2

    K&R example

    Hey all,

    I am reading K&R second edition and am kind of befuddled by one of their examples (a simple program to find and output the longest line). At the begining of main() i placed a line comment () just previous to the section that i find challenging. It seems that by calling function getline() the value of the character array line[] is defined. That value is then used after the function is called. This doesn't make sense to me. After the function is called the values of its parameters should no longer be there, since we are out of scope????

    Here is the example:

    Code:
    #include <stdio.h>
    #define MAXLINE 1000
    
    int getline(char line[], int maxline);
    
    void copy(char to[], char from[]);
    
    main()
    {
      int len;
      int max;
      char line[MAXLINE];
      char longest[MAXLINE];
    
      max=0;
      
      //the parameter line[], is defined by calling the fcn??? aren't we out of scope?
    
      while ((len= getline(line,MAXLINE)) > 0 )
        
        if (len > max)
          {
    	max=len;
    	copy(longest,line);
          }
    
      if (max > 0)
        printf("%s", longest);
      return 0;
    }
    
    
    
    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;
    }
    
    void copy(char to[], char from[])
    {
      int i;
      
      i=0;
      while ((to[i] = from [i]) != '\0')
        ++i;
    }

  2. #2
    Registered User
    Join Date
    Aug 2009
    Posts
    198
    Reading chapter 5 of K&R can help.

    Hint:

    ptr[] == *ptr
    ptr[0] == *ptr
    ptr[1] == *(ptr+1)
    Last edited by MTK; 09-20-2009 at 10:33 AM.

  3. #3
    Registered User
    Join Date
    Apr 2009
    Posts
    187
    your just passing address and by passing addresses its like using orginal address coz remeber an array of char is just ptrs of characters ..

  4. #4
    Registered User
    Join Date
    Sep 2007
    Posts
    1,012
    The object "line" is created in your main function. I'm not certain, but you're thinking that line is being defined when you call getline()? This is not the case at all.

    line exists in main(), and so will exist until your program returns from main (which means until your program exits in this case). One thing that K&R might not make clear (my copy is elsewhere at the moment) is that when you pass an array to a function, you're not actually passing the array; rather, you're passing a pointer to it. If you haven't yet learned what this means, it basically means when you modify the array inside of getline(), the array in main() will be updated. All you're doing, really, is telling getline() where your "line" array can be found; you're not passing (or modifying) a copy of the array. This is similar to pass-by-reference that other languages have, if you're familiar with that concept.

    Arrays in C can be tricky, because they act like pointers in many cases (although they are definitely not pointers). This is one of those times where they seem to be the same thing, though.

  5. #5
    Registered User
    Join Date
    Aug 2009
    Posts
    198
    I thought that they *are* pointers, pointing to a block of memory allocated on the stack instead of with malloc().

    Though 2D arrays are not an array of pointers to arrays, they are like a normal array, using the equation index = x + (y * width).
    Last edited by MTK; 09-20-2009 at 12:46 PM.

  6. #6
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    Quote Originally Posted by MTK View Post
    I thought that they *are* pointers, pointing to a block of memory allocated on the stack instead of with malloc().

    Though 2D arrays are not an array of pointers to arrays, they are like a normal array, using the equation index = x + (y * width).
    Nope. An array is a block of contiguous memory, yes. And as you point out, with extra dimensions it's not even close to the same thing. But in all cases, if you use the array name by itself (including a sub-array) it is converted to a pointer (to the first element). So if you had
    Code:
    int bigarray[3][4][5];
    then bigarray, by itself, would be treated as a pointer to int[4][5], and bigarray[2] by itself would be treated as a pointer to int[5] (pointing to the bigarray[2][0][0] element).

  7. #7
    Registered User
    Join Date
    Aug 2009
    Posts
    198
    So you are saying that an array is a special data type, and that it is converted to a pionter when you read it?

    How come [0] can also be used for dereferencing pointers?

  8. #8
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by MTK
    So you are saying that an array is a special data type, and that it is converted to a pionter when you read it?
    In most contexts, yes. One case where conversion to a pointer to the array's first element does not happen is when an array is used with the sizeof operator.

    Quote Originally Posted by MTK
    How come [0] can also be used for dereferencing pointers?
    Because p[0] for some pointer (or array) p is equivalent to *(p + 0).
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  9. #9
    Registered User
    Join Date
    Aug 2009
    Posts
    198
    Quote Originally Posted by laserlight View Post
    Because p[0] for some pointer (or array) p is equivalent to *(p + 0).
    Doesn't that directly show that an "array variable" is a pointer to the start of the array?

  10. #10
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    Quote Originally Posted by MTK View Post
    So you are saying that an array is a special data type, and that it is converted to a pionter when you read it?
    An array is a separate data type, yes. (Fancy word: It's called a derived data type, because you have to have some other data type to have an array of.)
    Quote Originally Posted by MTK View Post
    How come [0] can also be used for dereferencing pointers?
    For one, they had to give the equivalence of arrays and pointers in bracket notation because of the fact that arrays are passed by pointer. For two, the parsing rules state that in something like array[5], array is still technically used by itself (as the left side of the bracket "operator"), so it gets converted to a pointer there too.

  11. #11
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    Quote Originally Posted by MTK View Post
    Doesn't that directly show that an "array variable" is a pointer to the start of the array?
    No? It is a different type, and as you yourself even pointed out, that makes a lot of difference in two-dimensional variables (there's no way to get from int[5][5] to int **) and in the size.

  12. #12
    Registered User
    Join Date
    Aug 2009
    Posts
    198
    How come you can pass an array as a pointer?

    I thought that [][] is just a separate operator, and that the compiler knows the width of the 2D array.

  13. #13
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    Quote Originally Posted by MTK View Post
    How come you can pass an array as a pointer?

    I thought that [][] is just a separate operator, and that the compiler knows the width of the 2D array.
    Because back in the day (and for that matter even now) passing, say, a 10000 element array on the stack would make people turn green and nauseous. And since having arrays not as strictly typed in C as in say Pascal (i.e., we can write a function that takes "an array of char" and don't need separate functions for "an array of 5 char", "an array of 6 char" etc.) was considered a good thing, pass by pointer was the design choice used.

    The compiler does know the latter dimensions of a multi-dimensional array (they're part of the type), but each [] is done in turn, left to right. (I almost posted that bit of the standard last time, maybe I'll do it this time:
    Quote Originally Posted by C99, 6.5.2.1
    Successive subscript operators designate an element of a multidimensional array object.
    If E is an n-dimensional array (n ≥ 2) with dimensions i x j x . . . x k, then E (used as
    other than an lvalue) is converted to a pointer to an (n - 1)-dimensional array with
    dimensions j x . . . x k. If the unary * operator is applied to this pointer explicitly, or
    implicitly as a result of subscripting, the result is the pointed-to (n - 1)-dimensional array,
    which itself is converted into a pointer if used as other than an lvalue. It follows from this
    that arrays are stored in row-major order (last subscript varies fastest).
    This also implies that multi-dimensional arrays are stored in one big block, as pointed out there at the end.)

  14. #14
    Registered User
    Join Date
    Apr 2009
    Posts
    187
    Quote Originally Posted by MTK View Post
    How come you can pass an array as a pointer?

    I thought that [][] is just a separate operator, and that the compiler knows the width of the 2D array.
    acctually you can display it in pointer notation aswell but its complex you can do anything with index that can ptr notation do but easier way
    Code:
    #include <stdio.h>
    int main(void)
    {
        int arr[2][2]={  {0,3} , {0,2}   };
        printf("%d",*(*(arr+1)+1));//display the 2nd member of 2nd array
        return 0;
    }

  15. #15
    Registered User
    Join Date
    Sep 2009
    Posts
    2
    The object "line" is created in your main function. I'm not certain, but you're thinking that line is being defined when you call getline()? This is not the case at all.

    line exists in main(), and so will exist until your program returns from main (which means until your program exits in this case). One thing that K&R might not make clear (my copy is elsewhere at the moment) is that when you pass an array to a function, you're not actually passing the array; rather, you're passing a pointer to it. If you haven't yet learned what this means, it basically means when you modify the array inside of getline(), the array in main() will be updated. All you're doing, really, is telling getline() where your "line" array can be found; you're not passing (or modifying) a copy of the array. This is similar to pass-by-reference that other languages have, if you're familiar with that concept.

    Arrays in C can be tricky, because they act like pointers in many cases (although they are definitely not pointers). This is one of those times where they seem to be the same thing, though.
    thanks for that answer cas!!

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Problem with read().(from K&R)
    By chakra in forum C Programming
    Replies: 1
    Last Post: 05-10-2008, 11:00 AM
  2. K&R solution?
    By deadhippo in forum C Programming
    Replies: 12
    Last Post: 05-09-2008, 06:36 AM
  3. K&R book help
    By HLA91 in forum C Programming
    Replies: 4
    Last Post: 04-17-2008, 03:12 PM
  4. Help with K&R Book Exercise
    By Alejandrito in forum C Programming
    Replies: 5
    Last Post: 03-11-2008, 01:24 PM
  5. Line Counting Help (K&R)
    By smittles2003 in forum C Programming
    Replies: 9
    Last Post: 01-05-2007, 04:00 PM