【掲示板ご利用上の注意】

 ※題名は具体的に!
 ※学校の課題の丸投げ禁止!
 ※ソースの添付は「HTML変換ツール」で字下げ!
 ※返信の引用は最小限に!
 ※環境(OSとコンパイラ)や症状は具体的に詳しく!
 ※マルチポスト(多重投稿)は慎んで!

 詳しくはこちら



 本当はこんなに大きく書きたくはないのですが、なかなか守っていただけなくて…。
 守ってくださいね。お願いします。(by管理人)

C言語ソース⇒HTML形式ツール   掲示板2こちら


管理者用メニュー    ツリーに戻る    携帯用URL    ホームページ    ログ    タグ一覧

No.20764

C のリンケージについて
投稿者---qux(2005/04/23 19:06:51)


C のリンケージについて質問があります。

内部リンケージを持つ関数を指す、
外部リンケージのポインタの呼び出しについてなのですが、
言葉で説明し辛いのでサンプルを書きました。
// sub.c
static int ret0(void)
{
    return 0;
}
int (*const ret0_funcptr)(void) = ret0;

// sub.h
extern int (*const ret0_funcptr)(void);

// main.c
#include <stdio.h>
#include "sub.h"

int main(void)
{
    printf("%d\n", ret0_funcptr());

    return 0;
}
上記のコードは、win2k, mingw, gcc 3.4.2 で一切のエラーも警告も無くコンパイルでき、
実行して 0 と表示される事は確認出来たのですが、
このようにして、sub.c の static な関数をポインタを介して main.c でも呼ぶコードが、
果たして C において正しいコードなのか(作法としてどうなのか)が分からないのです。

取り合えず自分の中では、
「ret0() は sub.c の内部リンケージにあるので、main.c からは直接呼び出す事は出来ない。
けれど、関数自体はメモリ上に存在しているので、ポインタを介して呼び出す事は出来る」
と結論付けたのですが、この解釈は正しいでしょうか?

正しいコードなのか、そして正しい解釈なのか、
この 2 点どなたか教えてください。お願いします。


この投稿にコメントする

削除パスワード

発言に関する情報 題名 投稿番号 投稿者名 投稿日時
<子記事> Re:C のリンケージについて 20767 ぽへぇ 2005/04/23 19:14:16


No.20767

Re:C のリンケージについて
投稿者---ぽへぇ(2005/04/23 19:14:16)


そもそもなぜ ファイルスコープによってmainから見えない
(見せたくない) static な関数をコールしたいのか、というのを
問うべきだと思います。



この投稿にコメントする

削除パスワード

No.20769

Re:C のリンケージについて
投稿者---qux(2005/04/23 20:28:17)


こんばんは。

>そもそもなぜ ファイルスコープによってmainから見えない
>(見せたくない) static な関数をコールしたいのか
それは、ファイルやメモリへの入出力を一元的に扱うライブラリを書く際、
ファイルやメモリに対する固有の処理を行う関数は、
ライブラリを使うユーザーからは出来るだけ見せないようにして、
且つ外部リンケージを占有しないようにしよう、と考えたからです。

具体的には、こうです。
typedef void (*objClose)(void *stream);
typedef size_t (*objRead)(void *ptr, size_t size, size_t nmemb, void *stream);
typedef size_t (*objWrite)(void *ptr, size_t size, size_t nmemb, void *stream);
// 入出力関係の関数のプロトタイプ宣言が続く... seek, tell, setpos 等々。

// オブジェクトへの入出力の手段を格納する為の構造体
typedef struct obj_io {
    objClose close;
    objRead read;
    objWrite write;
    // 入出力関係の関数ポインタの定義が続く...
} objIO;
とあって、適切に宣言した objIO 型の fileIO, memoryIO のみをユーザーに使わせたいのですが、
mclose(), mread(), mwrite() といった具体的にメモリへの入出力等を行う関数を、
ユーザーに直接使わせる必要は無いので、それらを内部リンケージに閉じ込め、
memoryIO に格納した関数ポインタを介して使わせようと思っているのです。

ちなみに、ライブラリはこのようにして使おうと思っています。
void output_helloworld(void *stream, objIO *obj_io)
{
    const char msg[] = "hello, world";
    obj_io->write(msg, 1, sizeof msg, stream);
}
>というのを問うべきだと思います。
普通なら、こんな実装はしないでしょうか?


この投稿にコメントする

削除パスワード

No.20771

Re:C のリンケージについて
投稿者---ぽへぇ(2005/04/23 21:38:00)


どうもです。

> objIO 型の fileIO, memoryIO のみをユーザーに使わせたいのですが、
>mclose(), mread(), mwrite() といった具体的にメモリへの入出力等を行う関数を、
>ユーザーに直接使わせる必要は無いので、

こういう意図があって objIO 型にまとめるのはアリですし、

>普通なら、こんな実装はしないでしょうか?
普通だと思います。


この投稿にコメントする

削除パスワード

No.20778

Re:C のリンケージについて
投稿者---qux(2005/04/24 06:13:08)


すみません、返信遅れました。

>こういう意図があって objIO 型にまとめるのはアリですし、
>>普通なら、こんな実装はしないでしょうか?
>普通だと思います。
そうですか、良かった。
こんな回りくどい事をするのはどうかな?と、
自分でも思っていて不安だったので安心出来ました。
どうも有難うございました。


この投稿にコメントする

削除パスワード

管理者用メニュー    ツリーに戻る    携帯用URL    ホームページ    ログ    タグ一覧