質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Linux

Linuxは、Unixをベースにして開発されたオペレーティングシステムです。日本では「リナックス」と呼ばれています。 主にWebサーバやDNSサーバ、イントラネットなどのサーバ用OSとして利用されています。 上位500のスーパーコンピュータの90%以上はLinuxを使用しています。 携帯端末用のプラットフォームAndroidは、Linuxカーネル上に構築されています。

Q&A

解決済

2回答

805閲覧

C言語の拡張した書き方?

strike1217

総合スコア651

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Linux

Linuxは、Unixをベースにして開発されたオペレーティングシステムです。日本では「リナックス」と呼ばれています。 主にWebサーバやDNSサーバ、イントラネットなどのサーバ用OSとして利用されています。 上位500のスーパーコンピュータの90%以上はLinuxを使用しています。 携帯端末用のプラットフォームAndroidは、Linuxカーネル上に構築されています。

0グッド

3クリップ

投稿2017/07/19 02:57

編集2017/07/19 04:55

Linuxカーネルのソースコードを眺めているをよく出てくる書き方があります

1, これは・・・名前にシャープを付けているんでしょうか?
関数の方にも使用できるんですか?

C

1#define SYS_ify(syscall_name) __NR_##syscall_name 2 3LOAD_ARGS_TYPES_##nr (args)

2, プリプロセッサの[!]はC言語の[!]と同じ意味です??

C

1#if !defined __NR_pread && defined __NR_pread64

**3, **インラインアセンブリではなく、アセンブリ言語をC言語と混合して使用している?
そんなこと可能なんですか?
後ろのバックスラッシュが気になりますね。

# define PSEUDO(name, syscall_name, args) \ .text; \ ENTRY (name) \ DO_CALL (syscall_name, args); \ cmpq $-4095, %rax; \ jae SYSCALL_ERROR_LABEL

4, 中括弧を大括弧で囲んでいる?
これは・・・関数の定義ですか?それともマクロですか? 融合しているような・・・
よく見ると可変長関数ですかね? 関数内部では可変長用の処理が行われていないような・・・

# define INLINE_SYSCALL_TYPES(name, nr, args...) \ ({ \ unsigned long int resultvar = INTERNAL_SYSCALL_TYPES (name, , nr, args); \ if (__glibc_unlikely (INTERNAL_SYSCALL_ERROR_P (resultvar, ))) \ { \ __set_errno (INTERNAL_SYSCALL_ERRNO (resultvar, )); \ resultvar = (unsigned long int) -1; \ } \ (long int) resultvar; })

5, 関数の中に関数を定義 & 呼び出しているんでしょうか??
list_for_each_entry()の箇所ですね。
(ちょっと長いので省略しています。)

int search_binary_handler(struct linux_binprm *bprm) { bool need_retry = IS_ENABLED(CONFIG_MODULES); struct linux_binfmt *fmt; int retval; /* This allows 4 levels of binfmt rewrites before failing hard. */ if (bprm->recursion_depth > 5) return -ELOOP; retval = security_bprm_check(bprm); if (retval) return retval; retval = -ENOENT; retry: read_lock(&binfmt_lock); list_for_each_entry(fmt, &formats, lh) { if (!try_module_get(fmt->module)) continue; read_unlock(&binfmt_lock); bprm->recursion_depth++; retval = fmt->load_binary(bprm); read_lock(&binfmt_lock); put_binfmt(fmt); bprm->recursion_depth--; if (retval < 0 && !bprm->mm) { ・・・

どれも標準のC言語では、出てこないような・・・・
見たことのない記述の仕方です。
ちなみに拡張子にcppと付いていないので、C++ではない・・・かな?
と思うのですが・・・

わかる方いましたら教えてください。

[追記]
3番について補足です。

# ifdef PIC # define SYSCALL_ERROR_LABEL 0f # else # define SYSCALL_ERROR_LABEL syscall_error # endif # undef PSEUDO # define PSEUDO(name, syscall_name, args) \ .text; \ ENTRY (name) \ DO_CALL (syscall_name, args); \ cmpq $-4095, %rax; \ jae SYSCALL_ERROR_LABEL # undef PSEUDO_END # define PSEUDO_END(name) \ SYSCALL_ERROR_HANDLER \ END (name)

となっていまいました。

ENTRY()とEND()に挟まれている部分にアセンブリ言語が記述されています。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

fuzzball

2017/07/19 04:12

「アセンブリ言語」のタグを消して下さい。
guest

回答2

0

ベストアンサー

1, これは・・・名前にシャープを付けているんでしょうか?

C標準機能です。##はトークン連結演算子とよばれるプリプロセッサへの指定で、両側の文字列(トークン列)を単純に連結します。

2, プリプロセッサの[!]はC言語の[!]と同じ意味です??

C標準機能です。両者とも論理否定を表します。

3, インラインアセンブリではなく、アセンブリ言語をC言語と混合して使用している?

少し微妙ですが、C標準の範囲内です。プリプロセッサをアセンブリ言語と組み合わせています。プリプロセッサはC言語(とC++言語)の一部ですが、プリプロセッサ単体でも利用可能ですし、別プログラミング言語と組み合わせることも可能です。

行末\は、物理行は分離しているが論理行としては続いていることを、プリプロセッサへ伝えるものです。

4, 中括弧を大括弧で囲んでいる?
これは・・・関数の定義ですか?それともマクロですか? 融合しているような・・・
よく見ると可変長関数ですかね? 関数内部では可変長用の処理が行われていないような・・・

可変長マクロ引数を伴う関数マクロ(function-like macro)の定義です。ここは2つのGCC独自拡張機能が使われています。

  • 通常の{ ~ }ブロックは文(statement)になりますが

({ ~ })は式(expression)として扱えます。詳細はStatements and Declarations in Expressionsを参照ください。

  • 可変長マクロ引数をargs...で受け、マクロ定義本体ではargsで引数リストを展開します。詳細はVariadic Macrosを参照ください。

5, 関数の中に関数を定義 & 呼び出しているんでしょうか??

list_for_each_entryは独自定義されたマクロです。マクロ展開後はC標準機能で解釈可能です。

http://wiki.bit-hive.com/north/pg/list_for_each_entry

投稿2017/07/19 03:13

編集2017/07/19 04:25
yohhoy

総合スコア6191

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

strike1217

2017/07/19 03:22

へ〜〜〜。 そうなんですか! すごいです。
strike1217

2017/07/19 03:23

4番は、式としているということは、マクロという解釈で合ってます?
maisumakun

2017/07/19 04:19

>4番 これ全体はマクロですが、({})の構文は(マクロ以外で積極的に使う箇所があるかは別問題として)通常の式に混ぜ込んで使うことができます。
strike1217

2017/07/19 04:28

C言語の複雑な関数定義をマクロ化したようなイメージですかね?
yohhoy

2017/07/19 04:30

4番目について追記しました。maisumakunさん指摘どおり、({})は「マクロ展開結果を式として扱いたい」ときに便利です。(というかそれ以外で使うメリットはたぶんない)
strike1217

2017/07/19 04:42 編集

3番が一番難しいですかね。 このファイルはヘッダーファイルになっていました。 C言語の関数の呼び出しも普通に行われているようですが・・・アセンブリ言語も入っている? ちなみに、3番と4番は同じファイル内にあったものです。 DO_CALL()はC言語ですよね。
maisumakun

2017/07/19 04:44

可能性として、「インラインアセンブラの中で使うマクロ」ということも考えられます(DO_CALLも大文字なので、これ自体もマクロ、という可能性が大いにあります)
strike1217

2017/07/19 04:53

追記いたしました。
strike1217

2017/07/19 04:57 編集

アセンブリ言語+プリプロセッサ = おk! C言語+プリプロセッサ = おk! C言語+アセンブリ+プリプロセッサ = ??
yohhoy

2017/07/19 05:09

3番については一度 http://www.cs.fsu.edu/~baker/devices/notes/systemcalls.html 等を読まれたほうが早いかと思います。 ここでは「単一ヘッダファイルをC言語ソースからもアセンブリ言語ソースからも呼び出せるように記述しておく」という方策が採られているようです。該当マクロの前後に「#ifdef __ASSEMBLER__」のような記述があるはずです。(マクロ定義はその場所だけを見て解釈するのが難しいです)
strike1217

2017/07/19 05:15

>「単一ヘッダファイルをC言語ソースからもアセンブリ言語ソースからも呼び出せるように記述しておく」という方策が採られているようです。 では、アセンブリ言語で記述されている箇所はアセンブリ言語のソースからのみ使用可能なようになっているんですかね! そんなことができるんですか!
strike1217

2017/07/19 05:20

5番は・・・ マクロなんですか? 関数の定義のように見えるんですが・・・
strike1217

2017/07/19 10:16

list_for_each_entryは・・・for文ぽいですね。 ああ〜。 for文に置き換わるんですね。 わかりました。
strike1217

2017/07/19 10:16

4番の「マクロ展開結果を式として扱いたい」 通常のマクロ展開は式として扱われず、どう扱われるんですか??
maisumakun

2017/07/19 10:37

マクロは単なる文字列置換なので、C言語の文法に合わない形でも作成できます(例: http://unkode-mania.net/view/50cb152f969ce0d97f000026 )。 「マクロの途中で変数を宣言する」かつ「マクロ自体が値を返す」ようなものを作ろうとすれば、{}の構文を使わないとなかなか難しいです。
strike1217

2017/07/19 10:45

ほぉ〜 そういうことですか!! わかりました。 大変分かりやすいです。
guest

0

1と2については、プリプロセッサの担当する処理です(標準的なC言語環境で利用できます)。

1の##は、前後のトークンを繋いで1つのトークンにするプリプロセッサ演算子です(MSDN)。

2は、演算の意味はふつうのC言語と同じですが、プリプロセッサ段階で処理されます。

4のように「式の中に中カッコを入れて、中で変数宣言などを行う」や5の「関数の中で関数を宣言」などは、GCCの独自拡張です。

投稿2017/07/19 03:23

maisumakun

総合スコア145184

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

strike1217

2017/07/19 03:25

GNU拡張ですね! (´Д`)ハァ… また勉強しないといけないですね。
strike1217

2017/07/19 04:09

C言語で使える演算子はすべてプリプロセッサの方でも使用可能なんですか?
maisumakun

2017/07/19 04:13

#ifの条件に使える式は、整数型の定数を扱う式のみ(なので*や[]は使用不可、不等号は0/1を返すので問題なし)で、sizeofやキャストを含まないものです。
strike1217

2017/07/19 04:19

リンク先を見たのですが・・・ #と##の使い分けはどうすれば良いのでしょう? #は文字列。 ##は変数名や関数名と言ったシンボルに使用できるんですかね?
maisumakun

2017/07/19 04:21

はい、#で連結したものは文字列となります。##で連結したものはシンボルになるので、変数名や関数名としても使えます。
strike1217

2017/07/19 04:25

おお! なるほど! わかりました。
strike1217

2017/07/19 10:18

関数の中に関数を宣言できる機能もあるんですね!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問