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

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

新規登録して質問してみよう
ただいま回答率
85.50%
Win32 API

Win32 APIはMicrosoft Windowsの32bitプロセッサのOSで動作するAPIです。

マクロ

定義された処理手続きに応じて、どのような一連の処理を行うのかを特定させるルールをマクロと呼びます。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

3回答

6825閲覧

[C++] wingdi.hのRGBマクロについて [WINAPI]

退会済みユーザー

退会済みユーザー

総合スコア0

Win32 API

Win32 APIはMicrosoft Windowsの32bitプロセッサのOSで動作するAPIです。

マクロ

定義された処理手続きに応じて、どのような一連の処理を行うのかを特定させるルールをマクロと呼びます。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

1クリップ

投稿2015/04/14 15:45

編集2015/04/15 18:01

いつもお世話になります.忙しい中だとは思いますが質問よろしくお願いいたします.

まずRGBマクロ原文を以下に示させていただきます.
#define RGB(r,g,b) ((COLORREF)(((BYTE)(r)|((WORD)((BYTE)(g))<<8))|(((DWORD)(BYTE)(b))<<16)))

このマクロを自分はつぎのように解釈しました.
#define RGB(r,g,b) (
(COLORREF)(
(
(BYTE)(r)
| ( (WORD)( (BYTE)(g) )<<8 )
)
| (( (DWORD)(BYTE)(b) )<<16)
)
)

ここで,
BYTE = unsigned char : 1byte
DORD = unsigned short : 2byte
DWORD = unsigned long : 4byte
COLORREF = DWORD : 4byte
です.
したがって,これらを一つずつ構文解析して,
BYTE r, g, b;

( r | ((WORD)g) << 8 )

[g][g] [r][r] 16進表示

((DWORD)b) << 16
[0][0] [b][b] [0][0] [0][0]

((r | ((WORD)g) << 8 )) | (((DWORD)b) << 16)
[0][0] [b][b] [g][g] [r][r]

となっているのではないかと推測しました.
疑問なのは,
((DWORD)( (BYTE)g))

(DWORD)(BYTE)b
の違いです.この二つは異なるシンタックスの同じ動作だと解釈して上のようにイメージしたので,根本からして違うのならこの解釈は間違っていることになります.

この二つの違いは何なのでしょうか?
そしてこの解釈は正しいのでしょうか?

[追記:2015/4/16]
// macrosTest.h
#ifndef TESTER_MACROS_MACROTEST_H_
#define TESTER_MACROS_MACROTEST_H_

#ifndef WINDOWS
typedef unsigned char BYTE;
typedef unsigned short WORD;
typedef unsigned long DWORD;
typedef DWORD COLORREF;
#endif

// WinAPIにあるRGBマクロの動作確認
#ifndef WINGDI_H
#define RGB(r,g,b) ((COLORREF)(((BYTE)(r)|((WORD)((BYTE)(g))<<8))|(((DWORD)(BYTE)(b))<<16)))
#endif

#define R_CASE1(r) (WORD)(BYTE)(r)
#define R_CASE2(r) (WORD)((BYTE)(r))
#define R_SHIFT(r) (WORD)(BYTE)r << 8
#define R_CASE1_SHIFT(r) (WORD)(BYTE)(r) << 8
#define R_CASE2_SHIFT(r) (WORD)((BYTE)(r)) << 8

#define TRGB(r,g,b) ((COLORREF)(((BYTE)(r)|(((WORD)(BYTE)(g))<<8))|(((DWORD)(BYTE)(b))<<16)))
// RGBマクロここまで

#endif

// main.cpp
#ifndef IOSTREAM
#include <iostream>
#endif

#include "macrosTester.h"

int main()
{
using namespace std;

char a{ 1 }, b{ 1 }; WORD w1{ 0 }, w2{ 0 }, w3{ 0 }; // 両方とも2^(1+8) = 512になることを期待したマクロ w1 = R_CASE1_SHIFT(a + b); cout << "R_CASE1 : r = " << w1 << ", type = " << typeid(w1).name() << endl; w2 = R_CASE2_SHIFT(a + b); cout << "R_CASE2 : r = " << w2 << ", type = " << typeid(w2).name() << endl; // 結果:期待通り // ではそもそも欠点のあるタイプでは? w3 = R_SHIFT(a + b); cout << "R_SHIFT : r = " << w3 << ", type = " << typeid(w3).name() << endl; // <<演算子の優先順位が~のエラーが出るものの512 // RGBマクロ本家のg部分のシフトを(DWORD)(BYTE)(g)に // 変更した場合との比較 char r{ 1 }, g{ 2 }; DWORD result1{ 0 }, result2{ 0 }; // 意地悪な式を代入 result1 = RGB(r+a, r%3/(g+a+b)*a+b, b+b); cout << "RGB = " << result1 << ", type = " << typeid(result1).name() << endl; result2 = TRGB(r+a, r%3/(g+a+b)*a+b, b+b); cout << "TRGB = " << result2 << ", type = " << typeid(result2).name() << endl; // 結果:どちらも同じ131330 return 0;

}

※少なくともvisual C++2013版では特に意味はないみたいです.
これがC++98や03になってくるとコンパイラの賢さとかでまた変わってくるかもしれませんが.

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

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

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

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

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

guest

回答3

0

naga3さんが書かれていることに捕捉させていただきますと、マクロは関数ではなく、文字置換です。
RGB(r,g,b)のr, g, bは変数と考えると痛い目にあいます。あくまでも文字の位置にある記述(式も含まれる)が文字列としてコード上で置き換わると考えてください。

投稿2015/04/15 00:45

KoichiSugiyama

総合スコア3041

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

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

退会済みユーザー

退会済みユーザー

2015/04/15 05:16

#define MAX 5 のような文字列置換はよく知っていましたが,変数っぽく書かれてる部分も置換なのは習ったはずなのに忘れていました.ありがとうございます
guest

0

キャスト演算子は右結合ですので、((DWORD)((BYTE)(g)))(DWORD)(BYTE)gで動きは変わりません。
ただgが式、例えば1+2だったとき、右のマクロでは(DWORD)(BYTE)1+2と展開され((DWORD)(BYTE)1)+2となりますので、意図通りでないキャストがされる可能性があります。左のマクロでは((DWORD)((BYTE)(1+2)))なので(DWORD)(BYTE)3となり、意図通りのキャストとなります。

投稿2015/04/15 00:24

編集2015/04/15 00:34
naga3

総合スコア1293

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

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

退会済みユーザー

退会済みユーザー

2015/04/15 05:14

なるほど!式が代入される場合はまったく考えていませんでした! ありがとうございます!
guest

0

ベストアンサー

自分で調べてみた内容を追記しました

投稿2015/04/15 18:05

退会済みユーザー

退会済みユーザー

総合スコア0

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問