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

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

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

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

Q&A

解決済

3回答

1320閲覧

C言語の文法で質問があります

Nshu

総合スコア14

C

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

0グッド

0クリップ

投稿2018/07/27 11:42

いつもお世話になっております。
qmk_firmware のソースコード(C)を読んでいる際に知らない文法が出てきたので、質問を投稿させていただきました。

以下が問題の文法です。

C

1void host_mouse_send(report_mouse_t *report) 2{ 3 if (!driver) return; 4 (*driver->send_mouse)(report); 5}

の中の

C

1(*driver->send_mouse)(report);

ここの部分の処理が分かりません。

変数、型の定義は以下の通りです。

C

1typedef struct { 2 uint8_t buttons; 3 int8_t x; 4 int8_t y; 5 int8_t v; 6 int8_t h; 7} __attribute__ ((packed)) report_mouse_t;

C

1static host_driver_t *driver;

C

1typedef struct { 2 uint8_t (*keyboard_leds)(void); 3 void (*send_keyboard)(report_keyboard_t *); 4 void (*send_mouse)(report_mouse_t *); 5 void (*send_system)(uint16_t); 6 void (*send_consumer)(uint16_t); 7} host_driver_t;

以上です。
よろしくお願いします。

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

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

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

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

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

guest

回答3

0

ベストアンサー

まず

(*driver->send_mouse)(report);

に出てくる演算子を列挙すると

  • ->: アロー演算子
  • *: 間接参照演算子
  • (): 関数呼び出し演算子

があります。つまり(report)の部分は関数呼び出し演算子です。それにreportという実引数を渡しています。

問題は*driver->send_mouseですね。->*の優先順位を考えましょう。

すると->のほうが優先順位が高いことがわかります。

つまり

  1. driverという構造体へのポインタを格納した変数がある
  2. ポインタをdereferenceしてさらに構造体のsend_mouseというメンバー変数にアクセスする(->)
  3. このメンバ変数は関数ポインタなので関数の実体を取ってくる(*)
  4. 関数呼び出し(())

ということをやっているわけです。

投稿2018/07/27 11:54

編集2018/07/27 11:56
yumetodo

総合スコア5850

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

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

Nshu

2018/07/27 23:16

解説ありがとうございます!理解できました!
guest

0

知らない文法が出てきた

とありますが、通常の関数呼び出しの文法です。たとえば、ans = sum(1, 2)みたいな。

(*driver->send_mouse)(report)

の(*driver->send_mouse)が関数名(実際はアドレス)で、reportがその引数です。
わかりずらいですが良く使われる方法です。この方法は慣れるしかないのでは。()があれば関数の引数と推定できますよ。
それでは、その実際の関数は何なのかと聞かれればgrep(サーチ)しまくりますね。IDEがあればそこらをスマートに行ってくれるかもしれませんが。
あとは、デバッガでその場所で止めてシンボルを確認する方法もありま。

投稿2018/07/27 12:02

ikapy

総合スコア1167

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

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

yumetodo

2018/07/27 12:04 編集

関数の実体を構造体変数にぶち込むのは一般にはxxx_initみたいな関数を呼び出すと入れてくれますね。
Nshu

2018/07/27 23:16

解説ありがとうございます!理解できました!
guest

0

host_driver_t のメンバは関数のアドレス群となってます。

(*driver->send_mouse)(report);

driver の中のメンバ send_mouse のアドレスの関数を実行してます。
report を引数として。

投稿2018/07/27 11:47

y_waiwai

総合スコア87774

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

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

Nshu

2018/07/27 23:16

解説ありがとうございます!理解できました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問