2016-05-27 4 views
4

こんばんは、stdio.hでgetline関数のカスタムバージョン(CLANG、OSのX)を実装する方法(ANSWER:コンパイルに使用変更POSIX標準)

私はカーニハンの中に演習を通して働いているとリッチーの古典を"Cプログラミング言語"

いくつかの場所で、演習では、標準ライブラリの関数の名前を複製する独自のバージョンの関数を作成します。私のバージョンの代替名を作成するのではなく、実際に私のバージョンの関数と標準ライブラリ関数を使用することをコンパイラーに伝えたいと思います。

具体的には、1-18行目の行末の空白とタブを入力行から削除するソリューションをコンパイルしようとすると、関数getlineを使ってstdinから行を読み込みます。残念ながら、getlineはstdio.hで定義されているため、コンパイラエラーが発生します。

私は#undefを使ってみましたが、うまく動作していないようです。

これまでに同様の質問がありましたが、[this one] [1]が見つかりました。しかし、それは私がむしろしない標準ライブラリのヘッダーをハッキングする必要があるようです。

ありがとうございます。

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

そして、私が手にエラーがある:

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

私が落とした後、ここで

は(息切れのために私のコメントを剥奪)のコードです私の定義から「静的」、エラーは次のように変わります:

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

この議論を参照してください。Why do I get a "conflicting types for getline" error when compiling the longest line example in chapter 1 of K&R2?

溶液前stdio.hのを含めてこれらの2行を追加することである。

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

これは、使用してコンパイルにコードを設定しますGNU getline()拡張が標準に追加されたPOSIX.1-2008標準とは対照的に、POSIX.1-2001標準です。

+1

'static'修飾子を削除します。 –

+1

関数の宣言が標準関数と同じであることを確認してください。だから '静的'を取り除く。 – Barmar

+0

これは、エラーメッセージによって提供されるガイダンスであり、それでも動作しないので、あまりにもそれを試みました。私はその結果で私の質問を更新します。 – ptdecker

答えて

0

これら二つの議論(第が最も適切である)を参照してください溶液前stdio.hのを含めてこれらの2行を追加することである

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

これは、 GNU getline()拡張が標準に追加されたPOSIX.1-2008標準とは対照的に、POSIX.1-2001標準を採用しています。

-1

どのように使用するかによって異なります。

ただ1つの.cファイルであれば、メソッド名を別のものに変更してから、すべての呼び出しを新しい名前に変更するか、ファイルの先頭に#define realName overrideNameを追加してください。

これがより一般的な場合、または単体テストの模擬用の場合は、オーバーライドされたgetlineメソッドを独自の.cファイルに置き換えます。それをコンパイルして.soとし、アプリを起動するときに他のライブラリの前に.soファイルをオーバーライドしていることをシステムに伝えます。

0

あなたの運動は、ダイナミック注入共有ライブラリを学びたいと思っています。

あなたは3環境変数を設定する必要がありますOS X上gcc -shared -o libname.so filename.c

のように(staticなし)あなたのファイルをコンパイルします。

  • setenv DYLD_LIBRARY_PATH .

  • setenv DYLD_INSERT_LIBRARIES libname.so

  • setenv DYLD_FORCE_FLAT_NAMESPACE 1

いくつかの他の情報:http://www.cprogramming.com/tutorial/shared-libraries-linux-gcc.html

EDIT

は私が作成したファイルgetuid.c

id

$> id 
uid=501(yourname) gid(staff) groups ... 

の結果を変更することで、あなたにexempleをお見せしましょうgcc -shared -o myuid.so getuid.c

コンパイルあなたはnm myuid.soを書くことができますし、内部関数を参照してください。その後、

は、ご使用の環境変数は、それはだ

setenv DYLD_LIBRARY_PATH . 
setenv DYLD_INSERT_LIBRARIES libname.so 
setenv DYLD_FORCE_FLAT_NAMESPACE 1 

を設定exportと可能性があり、自分の殻に依存。

そしてid結果は次のようになります。K & Rは今(非常に)古い本です

$> id 
uid=0(yourname) gid(staff) groups ... 
0

は、アカウントにそれを取る必要があります。手動で言うように(実際には)getlineを宣言/定義してください。あなたがOSX上にあるとして、マニュアルは言う:

SYNOPSIS

#include <stdio.h> 

ssize_t 
getline(char ** restrict linep, size_t * restrict linecapp, FILE * restrict stream); 

使用そのプロトタイプ。

実際に元のプロトタイプを使用する場合は、運動を少し変更して、mygetlineという名前に変更することもできます。

関連する問題