15

strdup()私が OS X でよく使っていた関数が、ANSI C の一部ではなく、POSIX の一部であることに最近気付きました。すべてのコードを書き直したくないので、独自のstrdup()関数を作成するだけだと思います。それほど難しいことではありませmalloc()strcpy()。とにかく、私は関数を持っていますが、この関数を書いて自分のコードにリンクし、それが libc に既に存在する場合はどうすればよいでしょうか? リンカまたはコンパイラを使用すると、基本的に独自のバージョンの関数を定義できますか? または別の名前を付ける必要がありますか? 同じ名前を再利用する方法があれば、非常に便利ですstrcpy()。ユーザーの libc に存在する場合はそれを使用できますが、libc に存在しない場合は、代わりに私のバージョンを使用できます。コードはほとんどありません。可能な限り変更します。

短いバージョン:

a) 組み込み関数と同じ名前で独自の関数を作成するとどうなりますか?

strdup()b)すべてのコードを not use に書き換えずに、プラットフォームで悪いことが起こらないようにするにはどうすればよいstrdup()ですか? これは少し面倒です。

4

7 に答える 7

20

通常、#if特定のコンパイラの下では、必要な関数を定義するために an を使用するだけです。組み込みライブラリで strdup が定義されていない場合は、自分で定義しても問題ありません (将来定義される場合を除いて、それを削除する必要があります)。

// Only define strdup for platforms that are missing it..
#if COMPILER_XYZ || COMPILER_ABC
char *strdup(const char *)
{
   // ....
}
#endif
于 2009-01-27T05:19:56.807 に答える
6

このようなマクロを使用することもできます。この方法では古い名前を使用できますが、リンカーには別の名前が表示されます。

char *my_strdup(const char *s) {
    char *p = malloc(strlen(s) + 1);
    if(p) { strcpy(p, s); }
    return p;
}

/* this goes in whatever header defines my_strdup */
char *my_strdup(const char *s);
#define strdup(x) my_strdup(x)
于 2009-01-27T05:52:26.570 に答える
6

Rob Kennedy が指摘したように、この関数が存在するかどうかをビルド スクリプト内でテストするのが最善の方法です。autoconfig を使えばかなり簡単ですが、おそらく他のクロスプラットフォーム ビルド スクリプト ツールでも同様です。

次に、ヘッダー ファイルに次のように配置します。


#ifndef HAVE_STRDUP
# ifdef HAVE__STRDUP
#  define strdup _strdup
# else
#  define strdup my_strdup
# endif
#endif

ターゲット プラットフォームに strdup が既に存在する場合は、libc バージョンが使用されます。そうでない場合は、カスタムの my_strdup 関数が使用されます。

編集:なぜそれが優れているのか説明を追加する必要がありました。

まず、コンパイラは libc 内の関数の存在とは無関係です。たとえば、関数を取り上げますstrlcpy。どちらもデフォルトで gcc を使用していますが、FreeBSD には存在しますが、Linux (glibc) には存在しません。または、誰かがあなたのコードを clang でコンパイルしようとするとどうなりますか?

2番目のプラットフォームチェック(標準的な方法があるかどうかはわかりません)は、正しいプリプロセッサ条件をサポートするすべてのプラットフォームに対して明示的に追加した場合にのみ機能します。したがって、OSX と Win32 でアプリケーションをコンパイルする方法をマスターし、Linux でコンパイルしたいと仮定すると、すべてのプリプロセッサ条件を調べて、それらが Linux で機能するかどうかを確認する必要があります。もしかしたら、FreeBSD や OpenBSD などもサポートしたいですか? また同じ作業。ビルド スクリプトでテストを行うと、追加作業なしでコンパイルできる場合があります。

于 2009-01-27T08:30:52.930 に答える
4

a) 組み込み関数と同じ名前で独自の関数を作成するとどうなりますか?

インクルードするヘッダー ファイルに既に存在する関数を再定義することはできません。これにより、コンパイル エラーが発生します。

b) strdup() を使用しないようにすべてのコードを書き直すことなく、strdup() を持たないプラットフォームで悪いことが起こるのを避けるにはどうすればよいですか?

独自のラッパー関数を strdup に作成し、すべての呼び出しを新しいラッパー関数を使用するように置き換えることをお勧めします。例えば:

char *StringDuplicate(const char *s1)
{
#ifdef POSIX
    return strdup(s1);
#else
    /* Insert your own code here */
#endif
}

すべての呼び出しを strdup から StringDuplicate() に変更することは、単純な検索と置換操作であり、実行可能なアプローチになります。プラットフォーム固有のロジックは、コードベース全体に分散するのではなく、1 つの場所に保持されます。

于 2009-01-27T05:23:50.263 に答える
3

また、str[az] で始まる識別子 (関数を含む) の作成を避けることも検討する必要があります。これは予約されていませんが、C 標準 (ISO/IEC 9899:1999) セクション 7.26.11 (将来のライブラリの方向性) には、「str、mem、または wcs で始まる関数名と、小文字を宣言に追加することができる」と記載されています。ヘッダーに。」

于 2009-01-27T07:19:40.060 に答える
2

参考までに: strdup() を定義していない環境を個人的に見たことはありません。

于 2009-01-27T05:39:06.457 に答える
-3

他の誰かがこれを読んだ場合: プラットフォームの strdup() が利用可能であっても使用しないでください。また、それを使用するためだけに autoconf/automake で時間/労力を無駄にしないでください。真剣に、これはどれほど難しいか:

char* mystrdup(const char* str)
{
 return strcpy(malloc( strlen(str) + 1),str);
}

これは本当に#ifdefsを正当化しますか? コンパイラチェック?接吻

于 2010-07-13T11:12:11.767 に答える