Thread: stdin "incompatible pointer type" as FILE*

  1. #1
    Registered User
    Join Date
    Aug 2008
    Posts
    129

    stdin "incompatible pointer type" as FILE*

    Lesson 9 in the C tutorial says the declaration of fgets calls for a FILE* but will take stdin. But when I try this with my own function (which I'm trying to generalize) I get a warning:
    Code:
    warning: passing argument 1 of ‘readLine’ from incompatible pointer type
    Why? Here's the code:
    Code:
    #include <stdio.h>
    #include <string.h>
    
    void readLine(char* string, FILE* stream){
        int i;
        fgets(string, strlen(string), stream);
        for(i = 0; i < strlen(string); i++){
            if(string[i] == '\n'){
                string[i] = '\0';
                return;
            }
        }
        return;
    }
    
    int main(){
        char* input[256];
        printf("Please enter a number: ");
        readLine(input, stdin);
        printf("You entered &#37;s.\n", input);
        return 0;
    }

  2. #2
    * noops's Avatar
    Join Date
    Jun 2008
    Posts
    108
    It's actually 'input' that it is complaining about.

  3. #3
    Jack of many languages Dino's Avatar
    Join Date
    Nov 2007
    Location
    Chappell Hill, Texas
    Posts
    2,337
    This
    Code:
     char* input[256];
    should be this:
    Code:
     char input[256];
    Mainframe assembler programmer by trade. C coder when I can.

  4. #4
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    Quote Originally Posted by Jesdisciple View Post
    Code:
    warning: passing argument 1 of ‘readLine’ from incompatible pointer type
    For future reference, the warnings from your compiler are not in C-array-index-style (so when it says argument 1, it really means the first argument, and not the second).

  5. #5
    FOSS Enthusiast
    Join Date
    Jun 2008
    Posts
    64
    Quote Originally Posted by Jesdisciple View Post
    Lesson 9 in the C tutorial says the declaration of fgets calls for a FILE* but will take stdin. But when I try this with my own function (which I'm trying to generalize) I get a warning:
    Code:
    warning: passing argument 1 of ‘readLine’ from incompatible pointer type
    Why? Here's the code:
    Code:
    #include <stdio.h>
    #include <string.h>
    
    void readLine(char* string, FILE* stream){
        int i;
        fgets(string, strlen(string), stream);
        for(i = 0; i < strlen(string); i++){
            if(string[i] == '\n'){
                string[i] = '\0';
                return;
            }
        }
        return;
    }
    
    int main(){
        char* input[256];
        printf("Please enter a number: ");
        readLine(input, stdin);
        printf("You entered %s.\n", input);
        return 0;
    }
    as already pointed out, the problem is in line 1 of your main() function. What you have there is actually a multidimensional array, which conflicts with your declaration of the readLine() function.
    Also be aware that your readline function should actually be
    Code:
    void readLine(const char *string, FILE *stream)
    {
        /* ... */
    }
    Well, it's actually not necessary, but the first argument is a pointer, which will be read-only. So any attempt to modify it should cause an Segmentation Fault. the const makes that variable constant, so that you can't modify it. Your implementation is fine too, but it might become a hard-to-find problem in your code, if you acidentially write to that char *string and your not aware of the read-only condition.

  6. #6
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Quote Originally Posted by mkruk View Post
    Also be aware that your readline function should actually be
    Code:
    void readLine(const char *string, FILE *stream)
    {
        /* ... */
    }
    Well, it's actually not necessary, but the first argument is a pointer, which will be read-only. So any attempt to modify it should cause an Segmentation Fault. the const makes that variable constant, so that you can't modify it. Your implementation is fine too, but it might become a hard-to-find problem in your code, if you acidentially write to that char *string and your not aware of the read-only condition.
    This is wholly incorrect. In the usage we have here, the pointer is the address of the input buffer, which MUST NOT be const for the purpose of this function. Further, it is absolutely nothing wrong with passing a char array to a function as a char * - no const needed.

    If you REALLY feel a desperate need to do so, you COULD do:
    Code:
    void readLine(char * const string, FILE *stream)
    {
        /* ... */
    }
    This tells the compiler that the address that string points to should not change - but since the address is a copy of the original address, there's really no point in doing so.

    However, there is a small bug here:
    Code:
    fgets(string, strlen(string), stream);
    strlen for an uninitialized string on the stack will be undefined. It may be zero, it may be hundreds of thousands, and it may even crash the system - if there isn't a zero before the end (bottom) of the stack, you'd have a crash. This may be unlikely. However, I can almost guarantee that the length here is incorrect in relation to the actual size of the string. The best option would be to pass the actual size (from sizeof(input)) along the other arguments to the readLine function.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  7. #7
    Registered User
    Join Date
    Aug 2008
    Posts
    129
    Quote Originally Posted by tabstop View Post
    For future reference, the warnings from your compiler are not in C-array-index-style (so when it says argument 1, it really means the first argument, and not the second).
    Oh, thanks. That threw me for a loop (no pun intended).

    Umm, I'll just leave the write permission as it is until I've had more experience.

    Quote Originally Posted by matsp View Post
    However, there is a small bug here:
    Code:
    fgets(string, strlen(string), stream);
    strlen for an uninitialized string on the stack will be undefined. It may be zero, it may be hundreds of thousands, and it may even crash the system - if there isn't a zero before the end (bottom) of the stack, you'd have a crash. This may be unlikely. However, I can almost guarantee that the length here is incorrect in relation to the actual size of the string. The best option would be to pass the actual size (from sizeof(input)) along the other arguments to the readLine function.
    I've changed my declaration for input to
    Code:
    char input[256];
    And I wonder why I can't retrieve the length I applied to it? Since C (as I understand it) is supposed to be a bare language with the mechanics showing and ready to be used, both beautiful and ugly, I would think this would be an externally accessible datum...

  8. #8
    Registered User
    Join Date
    Dec 2007
    Posts
    2,675
    Quote Originally Posted by Jesdisciple View Post
    I've changed my declaration for input to
    Code:
    char input[256];
    And I wonder why I can't retrieve the length I applied to it? Since C (as I understand it) is supposed to be a bare language with the mechanics showing and ready to be used, both beautiful and ugly, I would think this would be an externally accessible datum...
    When you've declared a character array as you have, there's no real guarantee as to what's contained within the array. A character array is an array or bytes, and can contain pretty much anything in C. You make it special, i.e. a "string", through the use of a null terminator. Therefore, strlen requires the presence of a null terminator to determine the length of the string. With an array, you can, however, use sizeof(input) to get the available size.

  9. #9
    Jack of many languages Dino's Avatar
    Join Date
    Nov 2007
    Location
    Chappell Hill, Texas
    Posts
    2,337
    And you can initialize it to have a zero length as well, like this:
    Code:
    char string[256] = { 0 } ;
    Also, the nature of fgets() is to return only a single newline character as the last character, maybe. Therefore, looping through the whole string to replace every occurence of newline with a zero is a waste.

    So, you can just check your last character:
    Code:
    char * last_char_in_string = &string[strlen(string)-1] ;      // get address of last character
    if (*last_char_in_string == '\n') *last_char_in_string = 0 ;  // reset newline to zero
    Mainframe assembler programmer by trade. C coder when I can.

  10. #10
    Registered User
    Join Date
    Aug 2008
    Posts
    129
    Yes, that works much better.

    Thanks a bunch!

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 0
    Last Post: 03-20-2008, 07:59 AM
  2. What is a virtual function pointer?
    By ting in forum C++ Programming
    Replies: 4
    Last Post: 03-05-2008, 02:36 AM
  3. scope of a pointer?
    By Syneris in forum C++ Programming
    Replies: 6
    Last Post: 12-29-2005, 09:40 PM
  4. pointers
    By InvariantLoop in forum C Programming
    Replies: 13
    Last Post: 02-04-2005, 09:32 AM
  5. Struct *** initialization
    By Saravanan in forum C Programming
    Replies: 20
    Last Post: 10-09-2003, 12:04 PM