web-dev-qa-db-ja.com

K&R2の第1章にある最長の行の例をコンパイルすると、「getlineの競合する型」エラーが発生するのはなぜですか?

これは、「Cプログラミング言語」のセクション1.9から直接実行しようとしているプログラムです。

#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;
    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;
}

Ubuntu 11.10を使用してプログラムをコンパイルしようとすると、次のエラーが発生します。

cc     Word.c   -o Word
word.c:4:5: error: conflicting types for ‘getline’
/usr/include/stdio.h:671:20: note: previous declaration of ‘getline’ was here
Word.c:26:5: error: conflicting types for ‘getline’
/usr/include/stdio.h:671:20: note: previous declaration of ‘getline’ was here
make: *** [Word] Error 1

本の印刷物に問題がないことを確認するために、この一連の回答を、本(http://users.powernet.co.uk/eton/kandr2/krx1。 html)そして、そのリンクから演習18、19、20、21などを実行しようとすると、同様のエラーが発生します。プログラムを実行して出力がどのように表示されるかを確認できない場合は、理解するのが非常に困難です。この問題は、1つのプログラムで文字配列と関数呼び出しを導入したときに始まりました。この問題についてのアドバイスをいただければ幸いです。

35
Salar

問題は、getline()が標準ライブラリ関数であることです。 (stdio.hで定義)関数が同じ名前を持っているため、関数と競合しています。

解決策は、単に名前を変更することです。

35
Mysticial

競合する関数 getline() はGNU/POSIX拡張です。

K&Rは、彼らの本 (c.f。) で特にANSI Cを扱っていると述べており、この関数は提供されていません。

著者は、ANSI標準C言語プログラミングの完全なガイドを提示します。

Gccを「K&R互換モード」に設定するには、コンパイルにANSIまたはISOモードを指定できます。これらは、拡張機能を無効にすることを目的としています(例:関数getline())。これにより、最終的にはK&Rが提供する他の例を編集する必要もなくなります。

たとえば、次のコードは問題なくコンパイルされます。

_$ gcc test.c -ansi
$ gcc test.c -std=c89
_

(_-Wall_を使用したmain()の暗黙のデフォルトの戻り値の型について不平を言うことを除きます。)

明らかに一部のシステムでは、これらのモードはここに示すように機能しない可能性があります( Mac OSの一部のバージョンは、すべての拡張機能を正しく無効にできません )。私は自分のマシンでこれをうまくテストしました:

_$ gcc --version
gcc (GCC) 4.7.2 20121109 (Red Hat 4.7.2-8)
Copyright (C) 2012 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
_
36
moooeeeep

これは、_stdio.h_にgetline()関数があるためです。

したがって、これを機能させる簡単な方法は、関数の名前をmy_getline()に変更することです。

getline()getdelim()は、元々GNU拡張でした。それらは_POSIX.1-2008_で標準化されました。

_/usr/include/stdio.h:671:20: note: previous declaration of ‘getline’ was here_

それはあなたにヒントを与えるはずです。コードのgetline()関数を別の名前に変更してみてください。

また、このようにmain()を宣言するのは古いスタイルです。戻り値の型と引数が宣言されていない関数は、デフォルトで、不特定の数の引数を受け入れ、intを返します。これはmain()の場合とほぼ同じです。intを返しますが、2つの引数があります。次のように宣言することをお勧めします。

_int main(int argc, char **argv)
_

または:

_int main(int argc, char *argv[])
_
3
fge

Getlineは既に存在するため、名前を変更する必要があります。

2
BlackBear

getlinestdio.hで宣言されたPOSIX関数になりました

getline関数の名前を別の名前に変更すると、コンパイルされます。

2
ouah

これは、「stdio.h」ファイルで定義されているgetlineという関数です。したがって、プロトタイプの競合です。関数の名前を「my_getline」またはその他の名前に変更します。すべて問題ありません。

1
Mithrandir