Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to implement custom versions of the getline function in stdio.h (CLANG, OS X) (ANSWER: Change POSIX standard used to compile) [closed]

Good evening,

I am working through the exercises in Kernighan's and Ritchie's classic "The C Programming Language".

In several places the exercises have you creating your own version of a function that duplicates the name of of a function in the standard library. Instead of creating an alternate name for my version, I would really like to tell the compiler that I would rather use my version of the function then the standard library function.

To get specific, if I try to compile a solution to exercise 1-18 which removes trailing blanks and tabs from each line of input I use a function 'getline' to read in the line from stdin. Unfortunately, this generates a compiler error because getline is defined in stdio.h.

I have tried using #undef, but couldn't seem to get that to work.

I have searched for other prior similar questions and found [this one][1]; however, it seems to require hacking the standard library header which I would rather not do.

Thank you for your help in advance.

Here is the code (stripped of my comments for shortness):

#include <stdio.h>
#include <stdlib.h>

#define MAXLINE 1000

static size_t getline(char s[], size_t lim) {

    char   c;
    size_t i = 0;

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

    return i;
}

int main(void) {

    char   line[MAXLINE] = "";
    size_t len = 0;

    while ((len = getline(line, MAXLINE)) > 0)
        if (len > MAXLINE)
            printf("%s", line);

    exit(EXIT_SUCCESS);
}

And, the error I get is:

cc -std=c99 -Wall -g -I. -c -o obj/cleantrailsnblanks.o cleantrailsnblanks.c
cleantrailsnblanks.c:14:15: error: static declaration of 'getline' follows non-static declaration
static size_t getline(char s[], size_t lim) {
              ^
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk/usr/include/stdio.h:442:9: note: previous declaration is here
ssize_t getline(char ** __restrict, size_t * __restrict, FILE * __restrict) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_3);
        ^
cleantrailsnblanks.c:35:40: error: too few arguments to function call, expected 3, have 2
    while ((len = getline(line, MAXLINE)) > 0)
                  ~~~~~~~              ^
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk/usr/include/stdio.h:442:1: note: 'getline' declared here
ssize_t getline(char ** __restrict, size_t * __restrict, FILE * __restrict) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_3);
^
2 errors generated.
make: *** [obj/cleantrailsnblanks.o] Error 1

UPDATE 1

After I dropped 'static' from my definition, the error changes to:

cc -std=c99 -Wall -g -I. -c -o obj/cleantrailsnblanks.o cleantrailsnblanks.c
cleantrailsnblanks.c:14:8: error: conflicting types for 'getline'
size_t getline(char s[], size_t lim) {
       ^
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk/usr/include/stdio.h:442:9: note: previous declaration is here
ssize_t getline(char ** __restrict, size_t * __restrict, FILE * __restrict) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_3);
        ^
cleantrailsnblanks.c:35:40: error: too few arguments to function call, expected 3, have 2
while ((len = getline(line, MAXLINE)) > 0)
              ~~~~~~~              ^
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk/usr/include/stdio.h:442:1: note: 'getline' declared here
ssize_t getline(char ** __restrict, size_t * __restrict, FILE * __restrict) __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_4_3);
^
2 errors generated.
make: *** [obj/cleantrailsnblanks.o] Error 1

ANSWER

Refer to this discussion: Why do I get a "conflicting types for getline" error when compiling the longest line example in chapter 1 of K&R2?

The solution is to add these two lines prior to including stdio.h:

#undef _POSIX_C_SOURCE
#define _POSIX_C_SOURCE 200112L
#include <stdio.h>

This sets the compiles the code using the POSIX.1-2001 standard as opposed to the POSIX.1-2008 standard in which the GNU getline() extension was added to the standard.

like image 643
ptdecker Avatar asked Nov 21 '22 05:11

ptdecker


1 Answers

Refer to these two discussions (the second is the most relevant):

  • Why do I get a "conflicting types for getline" error when compiling the longest line example in chapter 1 of K&R2?
  • Can an ANSI C-compliant implementation include additional functions in its standard library?

The solution is to add these two lines prior to including stdio.h:

#undef _POSIX_C_SOURCE
#define _POSIX_C_SOURCE 200112L
#include <stdio.h>

This sets the compiles the code using the POSIX.1-2001 standard as opposed to the POSIX.1-2008 standard in which the GNU getline() extension was added to the standard.

like image 191
ptdecker Avatar answered Dec 31 '22 15:12

ptdecker