時々初心不可忘
あぁこれだこれだ、というのがいくつかの角度からありまして、備忘。
よく言われる「初心忘るべからず」とありますが、おいちゃんが割と重視しているのは、こちらでございます。
おいちゃんは「風姿花伝」で知ったのですが。どうも「花鏡」で述べたあと、風姿花伝でも触れた、ってのが時間軸的に正しい流れっぽい。まぁ枝葉末節。
是非初心不可忘
時々初心不可忘
老後初心不可忘
是非初心不可忘はとても大切でございます。
見方を変えると尊異論。「専門家という世界(場)にとらわれることで見えなくなるもの」を、外に内に求めるのは重要なことで。
世阿弥はきっとそれを「己の内側」にも求めたんでしょうねぇ。
時々初心不可忘と老後初心不可忘は、おいちゃん的にはおんなじようなものに感じています。
…で、このあたりの心境に得心がいくと、否応なしに「上にいったからふんぞり返る」とかあり得なくなります。
この辺ちょっと言及したいのでかみ砕いて。
そうですねぇたまに(よく?)耳にする「オレは**をn年もやってるんだ(だからオレは間違ってない)」云々。
で、そういうタイプに限って「出来てない」んですねぇ。
多分、こういうこと。
例題「エンジニアを10年やってる」。
ダメな人は「エンジニア1年生を10年間やってる」。だからせいぜい1年生レベルのスキルしかなくて、ふんぞり返る。
出来る人は「エンジニア10年生の1年目」。だから適度に謙虚だし(ヤバい時は適切に雷も落とすし)、日々学習であることを知ってる。
そろそろ、アラフォーどころかアラフィフに手が届こうというおいちゃんですが。
そこそこの確率で拝見する「オレはできあがってる」な感じにたどり着けず。まぁたどり着く気もないのですが、あれは何だろうなぁ? と思うにつれ、しみじみと思うです。
時々初心不可忘。
いくつになっても。
勿論1つの側面として「プログラミングをn年やってきた*1」とかっていう経験の積み重ねはあるのですが。
それでもなお、もう一方で持っている属性は「プログラマーn年経過、を初めて経験している」人間なので。
そのあたりを踏まえて忘れずに、いつまでも「適度な手探り」と「ある程度までの冒険心」は見失わずに行きたいなぁ、と思う訳です。
んで、あわせて。
特に「上司上職になった」時に。
それは「上司上職になったからほかの連中よりも長けている」のではなくて「上司上職の1年生であること」を、あるいは「上司上職をn年経験した、という状況の1年生である」事を。
特に上に行けば行くほど空気が薄くなる…もとい、突っ込みが入りにくくなるので。
つい出てしまう傲慢を、いかに内省して自制していくか、ってのは、とても大切なんじゃないかなぁ、って思うです。
死ぬまで修行だなぁ、と、改めて、しみじみ。
*1:冷静にカウントすると…小学5年が初めてだったはずなので…35年くらい経つんですねぇ怖いですねぇw
MACアドレスでの認証があずましくない理由
UDIDの話は先日書いたわけなのですが( http://d.hatena.ne.jp/gallu/20130415/p1 )。
そうすると次は「んぢゃMACアドレス」という話が耳に入りまして。
ってなわけで第二弾「MACアドレスでの認証やめれ」をお送りいたします(拍手@サクラの群れ)。
先に結論を書くと「UUIDv4使おう」になりますので、そのように認識をしつつ以下をご覧くださいまっしょ。
UDIDなんで一端「iPhoneの話」をしますが、Androidでも大して変わりゃしませんので、そのようにご認識いただきたく。
さて。
簡単に、MACアドレスを使うのを止めるべき理由は
・プライバシ(名寄せ)にまつわる問題
・クラックしやすいぢゃん問題
の2つになります。
ちと経緯的に「下の状況」が発生しているので、そちらをメインに話を進めさせていただきます。
プライバシ周りは、例えば「固有IDのシンプル・シナリオ( http://www.hyuki.com/techinfo/uniqid.html )」などを適宜ご覧ください。
MACアドレスによる認証ですが、一撃で屠ると
・長さが足りなくて簡単に墜とせる
で片付きます。で、ここが片付いちゃうと「他人になりすませる」ので、「認証が必要」なはずのPageで、それはもぉ心置きなく思う存分「ひゃっほい」出来るという事になります。
かみ砕いて。
上述が成立するには「他人の、かつ"サービスに登録されている、有効なMACアドレス"」をゲトる必要があります。
入手手段その1:無線LANネットワークの傍受等
MACアドレスは、適当に無線LANの一つも設置すれば「簡単に入手」できます。
「この人のアカウントを乗っ取りたい」ならともかく、「とりあえず有効なMACアドレスが欲しい」くらいなら、手段はぶっちゃけなんぼでも。
大分と古い記事ですが、こちらが参考になるかもしれません。
「無線LANのMACアドレス制限の無意味さがあまり理解されていない( https://takagi-hiromitsu.jp/diary/20071103.html )」
入手手段その2:総当たり(ブルートフォース)
MACアドレスのアドレス空間は48ビット(281兆個)。
ただしベンダーIDは「このメーカ(iPhoneの場合、apple)である」というところで固定できるので、事実上24ビット(1677万)。ちなみにアップル社は現在、ベンダーIDを100個ほど持っているらしいってことは100程度しかバリエーションがない。
一端「ベンダーIDを1つ」と仮定して、1677万回で「全てのアドレス」へのチャレンジが出来る。秒あたり50アクセスすると、わずか93時間。
もちろん「可能性のあるあらゆるMACアドレス」を頑張れば93時間の100倍かかるわけなのだけど、実際にそこまで「恣意的にランダムにしている」とは考えにくく、おそらく「割とすぐに分かる規則性」が見て取れるので、つまり「そこそこ時間かければ」認証用MACアドレス、ゲットだぜ!! になる。
結論として、しゃれにならないくらい「弱い」。
ちなみに「hash化したら」というのは常に耳にする愚考で。ンなもんは「レインボーテーブル」作れば終わる。以上。
入り口で入ってくるデータ(MACアドレス)のアドレス空間が狭いんだから、ナニやったって無理。
ちなみにUUIDv4は128ビット。一部「バージョン番号とかで固定部分があるから実質、ランダムなのは122ビット」って話も書いてあったのですが、エビデンスは取れず。
まぁ短い方がよいので、一端「122ビット」で考察をしてみましょう。
アドレスの個数(範囲)は5.3169e+36。…えっと…日本の表記で「5.3澗」。
澗ってなによ?って話なのですが。
万、億、兆、京、垓、じょ(漢字でない…)、穣、溝、澗、という並びの、澗。
数字で書くと、こんな桁。…多分あってると思うけど、数えてミスがあったら突っ込んでちょw
5,316,900,000,000,000,000,000,000,000,000,000,000
…気が遠くなりそうな桁だ(苦笑
MACアドレスで「百時間未満」程度で出来た力技アタックですが。…桁数多すぎて計算できませんが、確か記憶が間違いなければ、億年単位くらいかかったような。
まぁ普通の用途なら「100年かかる」くらいの強度があれば大丈夫だと思いますので、強度的には「十二分」かと思われます。
上述のような理由があるので。
「間違っても」MACアドレスを認証に使おう、とか思っちゃいけません。
UUID、iPhoneならそんなに苦労なく使えるはずなので、ちゃんと素直に、UUIDのv4を、適切な疑似暗号ロジック使って、生成しましょう。
6冊目!
1〜3冊目は http://d.hatena.ne.jp/gallu/20091119/p1 を、4冊目は http://d.hatena.ne.jp/gallu/20100724/p1 を、5冊目は http://d.hatena.ne.jp/gallu/20120626/p1 を、それぞれご覧くださいませ。
んでもって、6冊目はこちら。

コーディングを支える技術 ~成り立ちから学ぶプログラミング作法 (WEB+DB PRESS plus)
- 作者: 西尾泰和
- 出版社/メーカー: 技術評論社
- 発売日: 2013/04/24
- メディア: 単行本(ソフトカバー)
- この商品を含むブログ (37件) を見る
「こんな感じの文章書きたいなぁ」のグレードアップ版、って感じでふ。
プログラミング。あの言語でもその言語でもなくて「プログラミング」を学びたい時に、その入り口付近にある書籍だと思う。
個人的には「1つくらい、ある程度学んだプログラミング言語があるほうがいい」とは思うんだけど、初学者の子が読んで「わかりやすい」という話を聞きもしたので、案外「万人に向いている」かもしれない。
平淡な文章で、そうそう学び得ない「非凡な内容」が書かれているので。
特に「プログラミングを勉強している」人には超お勧めであるほかに、「プログラミングを理解している人*1」が「知識の虫干し」をするにも大変によろしい書籍でございます。
合わせて
http://nhiro.org/langbook/
で、面白げなパワポが上がってたので、チェック。
いずれにしても、寺子屋の面々的には「読了must」な物件でございます。
*1:で、毎度のことなれど。「理解してる」って、なに?
じゃんけんロジックで考えてみる「壁」の厚さ
ん…たいしたことやってる訳でもないんだけどねぇ。
「そこに思考が及ぶかどうか」ってのには以外と壁があるみたいで。それを「ど〜やって乗り越えさせるのか」を含めて考えてみたくて、ちょっと種まき。
いつものことではありますが、いつも以上になんか「ふと思ったコメント」とか気軽に残しておいてもらえると嬉しいです ^^
2013/05/13
頂いたコメントで大きく気づきがあったので改修。
レベル1の前にレベル0.5を作成、前提を少しいじりました。
(2013/05/13 追記開始)
前提
・guu:ぐー
・tyoki:ちょき
・paa:パー
・変数 $my に、自分が出した手
・変数 $opponent に、相手(コンピュータ)が出した手
・勝敗は「自分の勝ち負け」
・値は「入っていて」かつ「正常値」である、と仮定
コードレベル0.5
if ('goo' === $my) {
if ('goo' === $opponent) {
echo '引き分け';
} else
if ('choki' === $opponent) {
echo '勝ち';
} else {
echo '負け';
}
} else
if ('choki' === $my) {
if ('goo' === $opponent) {
echo '負け';
} else
if ('choki' === $opponent) {
echo '引き分け';
} else {
echo '勝ち';
}
} else {
if ('goo' === $opponent) {
echo '勝ち';
} else
if ('choki' === $opponent) {
echo '負け';
} else {
echo '引き分け';
}
}(2013/05/13 追記ここまで)
前提修正
・0:ぐー
・1:ちょき
・2:パー
・変数 $my に、自分が出した手
・変数 $opponent に、相手(コンピュータ)が出した手
・勝敗は「自分の勝ち負け」
・値は「入っていて」かつ「正常値(0〜2の範囲)」である、と仮定
コードレベル1
if (0 === $my) {
if (0 === $opponent) {
echo '引き分け';
} else
if (1 === $opponent) {
echo '勝ち';
} else {
echo '負け';
}
} else
if (1 === $my) {
if (0 === $opponent) {
echo '負け';
} else
if (1 === $opponent) {
echo '引き分け';
} else {
echo '勝ち';
}
} else {
if (0 === $opponent) {
echo '勝ち';
} else
if (1 === $opponent) {
echo '負け';
} else {
echo '引き分け';
}
}
コードレベル1.5
コードレベル1を、switchで書き直す。面倒だから脳内変換してw
コードレベル2
$i = $my - $opponent;
if (0 === $i) {
echo '引き分け';
} else
if ( (-1 === $i)||(2 === $i) ) {
echo '勝ち';
} else {
echo '負け';
}
コードレベル3
$i = ($my - $opponent + 3) % 3;
if (0 === $i) {
echo '引き分け';
} else
if (2 === $i) {
echo '勝ち';
} else {
echo '負け';
}
まず「1が書けない」ってハードルがあって、これは多分「日本語コメント」書かせると、届くんじゃないかって思う。
1から2にたどり着くのにおそらく1ハードルあって、これはまぁ「やってみる」チャレンジ精神があると、多分届く。
2から3へは…「探究心」か「怠け心」がある程度以上強いと、多分、いけるんじゃないか、って思う。
いろいろな人のコードを見て、色々と思うこと多々。
ど〜なんだろう?
コンストラクタ系の実験
ちと興味があるので。
…おねちゅ気味なので、本当に備忘録程度。
<?php
class hoge {
public function hoge() {
echo 'hoge' , "\n";
}
}
$obj = new hoge();
<?php
class hoge {
public function __construct() {
echo '__construct' , "\n";
}
}
$obj = new hoge();
うんそりゃそうだ。
<?php
class hoge {
public function __construct() {
echo '__construct' , "\n";
}
public function hoge() {
echo 'hoge' , "\n";
}
}
$obj = new hoge();
なるほど。
バージョン依存かしらん? とか思って調べてみる。
http://www.php.net/manual/ja/language.oop5.decon.php
下位互換性を維持するため、PHP 5 が指定されたクラスの __construct() 関数をみつけられなくて、 かつそれが親クラスのコンストラクタを継承していない場合には、 古い形式のコンストラクタ関数、つまり、そのクラスの名前と同じ関数が探されます。 実際、互換性の問題が発生する可能性があるのは、 そのクラスが __construct() という名前のメソッドを 有しており、それが異なる用途で使用されている場合です。
「指定されたクラスの __construct() 関数をみつけられなくて、 かつそれが親クラスのコンストラクタを継承していない場合には、 古い形式のコンストラクタ関数、つまり、そのクラスの名前と同じ関数が探されます」あぁしっかり明記されてるわ。
一瞬、ふと。
んと…よくある「getInstance」とかのメソッドがあるような、いわゆる「Singletonとか」でやる「外からnewなんか、やらせねぇぜ?」なパターン、どうなるんだろ?
<?php
class hoge {
private function __construct() {
echo '__construct' , "\n";
}
public function hoge() {
echo 'hoge' , "\n";
}
}
$obj = new hoge();
[gallu@localhost ~]$ php t.php
Fatal error: Call to private hoge::__construct() from invalid context in /home/gallu/t.php on line 19
あぁよしよし、ちゃんとエラーになる。
んじゃ次、もうちょいとだけ。
<?php
class hoge {
public function __construct() {
echo '__construct' , "\n";
}
public function hoge() {
echo 'hoge' , "\n";
}
}
class foo extends hoge {
public function foo() {
echo 'foo' , "\n";
}
}
$obj = new hoge();
あぁこうくるかぁ確かにそりゃそうか。
古い形式の改修、結構手間かかりそうだなぁ。
すごく雑なのでいいから「古い形式のコンストラクタ使ってるかもしれない程度に怪しいブツを探す」バッチとか、組んでおくと、もしかしたら楽かしらん?
イメージとしては
・grep ぽいので classの文字引っかけて
・classの後に続くワードを取得して
・同一ファイル内で「function ワード」とかで荒っぽくひっかけて
くらい?
どっかにないかなぁ?w
UDIDの話の軽いまとめ
ちょいと今日話が出ていたので、多分今後も「出るだろうなぁ」との予想込みで、Blogに。
(余談。タグに「プライバシ」とか追加しようかしらん? どう思います?)
ん…直接的には、あぽー様がすでに「おら受けトンねぇ」宣言をなさってるでごわす。
ちなみにそれって2011/08/19のお話( http://techcrunch.com/2011/08/19/apple-ios-5-phasing-out-udid/ )。「最近」とか騒いではいけません。
- AppleのApp Store、Retina非対応/UDID採用アプリの登録とアップデートが不能に 5月1日から
- ( http://www.itmedia.co.jp/news/articles/1303/22/news041.html )
- Apple、5月1日からUDIDにアクセスするアプリ・非iPhone 5最適化アプリはリジェクトと発表。
- ( http://www.appbank.net/2013/03/22/iphone-news/568323.php )
- ■[iOSプログラミング]UDIDが完全に利用禁止に
- ( http://d.hatena.ne.jp/nakamura001/20130325/1364231754 )
- アップル、UDID利用アプリを5月から拒否へ--Retinaディスプレイや「iPhone 5」への対応も必須に
- ( http://japan.cnet.com/news/service/35029839/ )
で、その背景ですが。
いくつかあるかと思うのですが、おいちゃんが認識している限りで
・広告とかビッグデータとか行動ぶっこ抜きとか系のプライバシ周り
・認証に使う馬鹿が後を絶たない
の2つがあると思ってるでやんす。
元々は、フューチャーホン(ガラケー)の契約者固有IDの頃から、少なくとも一部では言われるったけ言われまくった話ではあるのですが。
ん…以下のURIを適宜ごらんやがれください。
- 契約者固有IDとは
- ( http://itpro.nikkeibp.co.jp/article/Keyword/20081007/316269/ )( http://itpro.nikkeibp.co.jp/article/Keyword/20081007/316269/?SS=imgview&FD=-499245482&ST=keyword )
- 無責任なキャリア様に群がるIDクレクレ乞食 ―― 退化してゆく日本のWeb開発者
- ( http://takagi-hiromitsu.jp/diary/20080727.html )
根っこにあるのは「変更のきかない固定ID」がやべぇって話です。
こちらがその辺では秀逸なURIの一つ。
- 固有IDのシンプル・シナリオ
- ( http://www.hyuki.com/techinfo/uniqid.html )
フューチャーフォンはそれでも「限定されたIP空間内であるが故に安全である」とかいう嘘がまかり通っていたので、とりあえず「見えなければ安全」というクラスタ相手には、大砲の前の半紙10枚分ほどの防御力は見込めたのですが。
iPhoneにおいて、もはやその辺は半紙1枚ほどの防御力にも満たない状況となってます。
あぁ物凄く一応念のため。
極めてごく稀に「UDIDは偽装が出来ないから云々」とかいう話を聞きますが。360度大体どの角度から見ても「嘘」です。
まずUDIDのリストはぶっちゃけ「結構なところの広告会社がお手持ち」な可能性が想起されます。特に「行動ターゲットマーケティング」という言葉を用いているところには要注意。
行動ターゲティング広告
http://advertising.yahoo.co.jp/ad/privacy/
掲載場所
スマートフォン版の行動ターゲティング広告は、スマートフォン版Yahoo! JAPAN(iOS、Android対応ページ)のページ、またはYahoo! JAPANが提供するスマートフォン向け公式アプリケーション内のWebViewを対象に掲載されます(一部対象外のページ・アプリケーション内のWebViewもあります)。
※1 アプリケーション内WebViewとは、アプリケーションからウェブページを閲覧できる簡易的なブラウザー機能です。
※2 個体を識別する情報とは、iOSにおいてはUDID(Unique Device Identifier)、AndroidにおいてはAndroidIDを指します。アプリケーションを識別する情報とは、iOS、Androidともにアプリケーションごとに生成されたUUID(Universally Unique Identifier)を指します。
(「UDID使って広告流してます」ってはっきりと書いてある一例)
iOSにおけるリワード広告でのUDIDを使わない計測方法の提案
http://blogs.itmedia.co.jp/jinmsk/2012/02/iosudid-eb91.html
個体識別番号はリワード広告におけるユーザユニークIDを特定するための一つの方法であり、このIDを使わなくともリワード広告は行えると何回か書きましたが、今回はその一例の仕組みを書きたいと思います。
(使わなく"ても"というあたりから背景をかぎ取ってください)
UDIDに依存する人々とたしなめる人々
http://togetter.com/li/177744
(困っている人の論調を見てみましょう)
iOS の UDID 廃止問題は誰にとっての問題なのか
http://www.deftrash.com/blog/archives/2011/09/ios_udid.html
利用ポイントを抜粋させていただくと、
アプリケーションのサーバとのセッション保持
行動トラッキングによるターゲティング広告
リワード広告
目的は異なるにせよ、デベロッパーにとって容易にユーザを特定するための手段としての UDID というのは、便利な代物です。UDID の万能なところは、ターゲティング広告やリワード広告で使われているように、アプリを横断しても同一ユーザを特定できるところです。その良し悪しは別として、iOS 関連のエコシステムの拡張において、UDIDの果たした役割は小さくなかったと思います。
(「誰にとって」便利なのか、って話ではありますが)
なぜiOSでUDIDが必要とされていたのか、メモ
http://d.hatena.ne.jp/shinichitomita/20110822/1314013326
米グーグル、iOS向け広告プラットフォームからUDIDを除外
http://ggsoku.com/2013/04/google-admob-remove-udid/
UDIDと行動ターゲッティング広告
http://d.hatena.ne.jp/next49/20110822/p1
などなど。
んで、お手持ちにそういったリストがあると、次に出てくるのは漏洩。
直接的には「デジタル出版を手掛ける米BlueToad(本社フロリダ州)」の事件が有名ですが。
http://www.itmedia.co.jp/enterprise/articles/1209/11/news031.html
http://internet.watch.impress.co.jp/docs/news/20120911_558780.html
http://jp.techcrunch.com/2012/09/12/20120911inside-the-udid-hack-how-a-lone-programmer-cracked-the-case/
まぁじゃぁ「上述以外のすべてのadやってる会社さまが、技術力がパーペキでイージスの盾レベルの強度の防御能力を有する」って考えるのは、少々ナイーブに過ぎる見方か、と。
さて。んじゃUDIDが適当に流出しますと。まぁぶっちゃけ「ネットで流出した」その手のデータは、もはや為す術もなく散らかっていきます。
http://d.hatena.ne.jp/gallu/20120505
んで。UDIDは「ふつ〜に偽装ができます」。
- 識別子(UDID)の偽装
- ( http://blog.livedoor.jp/sirazumi_rio/archives/50785204.html )
- JailBreakで出来る色々な偽装
- ( http://zuzu-service.net/misc/iphone/20110429/235.html )
つまり。
UDIDを使う場合、それがどんな目的であれ「とてもしゃれになっていない」状況になります。
ちなみに「じゃぁ代わりにMACアドレス」とか考えちゃうような頭には脳みそが入ってないと思いますので、漂白剤とかで頭蓋骨洗ってからぬかみそかおがくずを詰め込んできてください。
UDIDの代わりは、UUIDを、もうちょい正しく書くと「UUIDのバージョン4」を用いるのが現状もっとも適切であると考えられます。
以下を参考にしてみてください。
- UUID を作る - CFUUIDCreate と globallyUniqueString
- ( http://xcatsan.blogspot.jp/2009/11/uuid-cfuuidcreate-globallyuniquestring.html )
- ■[iPhoneプログラミング]UUIDを生成する
- ( http://d.hatena.ne.jp/nakamura001/20100706/1278376345 )
ついで。
- OpenUDIDはUDIDの代替にはならない
- ( http://ameblo.jp/ryoji4321/entry-11204718235.html )
- 今更聞けないUDIDとUUIDまとめ for iPhoneアプリ開発
- ( http://matome.naver.jp/odai/2134045671202872301 )
別口で「広告識別子(Advertising Identifier)」ってのが出てきました。
認証目的に使うのは御法度ですが、広告系ならまぁ考えてみてもいいのかも(まだ問題山盛りですが、UDIDよりはわずかばかりマシ)。
- iOS6.1の新機能「Advertising Identifierをリセット」を見てみる
- ( http://d.hatena.ne.jp/mikanmarusan/20130211/1360581304 )
- iOS6.1の新機能「Advertising Identifierをリセット」
- ( http://otoko50.cocolog-nifty.com/blog/2013/02/ios61advertisin.html )
- iOS6のAdvertising Identifierについて
- ( http://togetter.com/li/377573 )
…ん、なんかリセット系の記事ばかりですねぇ。
一応、実装も…と思ったが、見事に見つからねぇ orz
まぁいいや誰かが突っ込んでくれたら追記しようw
以上、めっさ雑にですが「UDID使うな」なお話、でした。
ビット演算の説明と実例
某所でこんな質問をもらいまして。
うん確かに「ビット演算がわからない」と、それ以上に「なにに使うのかがわからない」って話はよく耳に目にするところなので。
せっかくなんで、Blogで返答をいたしますw
質問は、これ。
ビット演算子のこの部分が
$a = 0xFF;
$b = 0xF0;
$c = $a & $b;
var_dump($c);
echo sprintf("%08b\n",$c); //2進数で出力11110000
よくわかりません。
この11110000って、16進数だとF0、10進数に戻すと240になります。なので、直接F0を2進数にすればいいのに。。。(2進数にするやりかたわからないのですが^^;)
$a & $bは教科書には$a及び$bの両方にセットされているビットをセットするって書いてあります。なんですかこれ^^;
ビット演算子についてあまり理解ができていないからかもしれませんが、、、
その$a & $bと、実際にどういった場面でビット演算子を使うのか教えていただけませんでしょうか。
ん…まずは「演算子」を念のために。
1と0の世界において、andとorとxorは、こんな風になります。
1 and 1 → 1
0 and 1 → 0
1 and 0 → 0
0 and 0 → 0
1 or 1 → 1
0 or 1 → 1
1 or 0 → 1
0 or 0 → 0
1 xor 1 → 0
0 xor 1 → 1
1 xor 0 → 1
0 xor 0 → 0
andはかけ算みたいな感じで「どっちかが0なら0」なので、論理積なんて言い方もします。つまり「右手のダイヤも左手のプラチナも全部よこせ」ってな感じですねw
orは足し算みたいな感じで「どっちかが1なら1」なので、論理和なんて言い方もします。「右もいいけど左もいいから、どっちでもいいわ(両方もありだけどね)」って感じ。
xorは排他的論理和って言われますが、まぁつまりは天の邪鬼。「2つの値が異なれば1、一緒なら0」。そうですねぇさしずめ「他の人と同じなんて嫌!!」ってな感じでしょうか。
で、ビット演算の、まずは「結果」から。
$a = 0xFF;
$b = 0xF0;
$c = $a & $b;
var_dump($c);
echo sprintf("%08b\n",$c); //2進数で出力11110000ん…先にprintf周りから。
echo sprintf("%08b\n",$c); //2進数で出力11110000
は、一般的には以下のように書くことが多いですね。
printf("%08b\n",$c); //2進数で出力11110000
printfについては、とりあえず下記参照。
http://www.php.net/manual/ja/function.printf.php
フォーマットはまぁ色々あるので( http://www.php.net/manual/ja/function.sprintf.php )、ここでは「%b」と「%08b」について覚えておきましょう。
b - 引数を整数として扱い、 2 進数として表現します。
とあるので、%bで「数値を2進数として表現」。
ただ、それだけだと、例えば2進数で「00000100」を「100」て出しちゃうので。
ん…サンプルコード。
printf("%b\n", 4);慣習的に2進数って大抵「4桁とか8桁とか、先頭の0を省略せずに書く」のが一般的なので、08ってのをいれて「先頭が0なら0でいいからちゃんと0だして8桁で表示して」って感じにしておくです。
printf("%08b\n", 4);
次。
$a = 0xFF; $b = 0xF0;
は、単純に16進数で$aと$bに値を突っ込んでる。
計算が見やすいように書いておくと、こんな風になる(実際にプログラムとして書くとエラーになるから注意)。
$a = 11111111(二進数); $b = 11110000(二進数);
で、質問のコードでは&、つまり「ビット積(ビット演算子で、ビットごとにandする)」が指定されているので。
上下に書くとこんな感じ。
11111111:$aの内容
11110000:$bの内容
これのand。
andは上述の通り「両方1なら1」「それ以外は0」なので。
したがって、こうなる。
11111111:$aの内容
11110000:$bの内容
11110000:$aと$bをandした内容
なので、$cには11110000(二進数)が入る。
んで。「$a および $b の両方にセットされているビットがセットされます」「$a または $b のどちらかにセットされているビットがセットされます」はわかりにくいので。
これは「$aと$bを、ビットごとにandします」「$aと$bを、ビットごとにorします」って読み替えてOK。orしたりandしたりした結果は、左辺の変数にぶちこまれる感じ。
ここまではよいかし?
んで、実用例。
基本的には、フラグ、って考え方があって。
orは「フラグを立てるとき」に使って、andは「特定のフラグが立っているかどうかを見るとき」または「強制的に特定のフラグを寝かせたいとき」に使うざんす。
xorは「bit反転」でよく使うんだけど、今回はオミット。
ん…まずは基礎知識。
「フラグ」っていう、これは概念があって、プログラムではよく使われます(時点はエロゲー、ギャルゲー、その他ゲームなどでよく用いられますw)。
いわゆる「フラグが、フラグが立った!」っていうアレですね。
んで。100%ではないですが、フラグ用の値にはよく整数が用いられます。
昔々は「1bitのメモリにも88人の神様が」とか言われている時代もあったので(それはお米)(いやでも実際、それくらい貴重でした)。
出来るだけ無駄を省くために、bitをフラグに見立てていた時期があったんですね。いやまぁ実際、なれると計算楽だし。
ん…わかりやすく、ここでゲームのフラグを仮想してみましょう。
2進数で0000 0000の8桁を想像してください。
左から順番に、以下の意味をもつと仮定します。
・マリさんとのデートしたフラグ
・マリさんとデートが可能フラグ
・マリさんとおしゃべりをしたフラグ
・マリさんにアプローチをしたフラグ
・ミエさんとのデートしたフラグ
・ミエさんとデートが可能フラグ
・ミエさんとおしゃべりをしたフラグ
・ミエさんにアプローチをしたフラグ
ある人のフラグが00010001(16進数で11、10進数で17)だとすると、この人は「マリさんとミエさんにアプローチをしている」状態であることがわかります。
これをプログラム的に書くと、こうなります。なお、フラグ情報は「$gflg」の中に入っていると仮定します。
また、プログラム理解が楽なように、数値は二進数で書いてます。ので、そのまんまPHPコードとして動かすとエラーが出るんで注意。
// ミエさんへのアプローチチェック
if (0 !== (00000001(二進数) & $gflg)) {
echo "あんた、ミエさんにアプローチしたね?\n";
}
// マリさんへのアプローチチェック
if (0 !== (00010000(二進数) & $gflg)) {
echo "あんた、マリさんにアプローチしたね?\n";
}こんな感じ。
つまり「特定のbit(フラグ)がたっているかどうか」をみたい場合、そこだけbitを立てた値とandしてみて、0以外が帰ってくれば「あぁきっとbitがたってるんだろうなぁ」って見当がつくわけですね。
で、何かイベントがあってもし「マリさんとおしゃべりをしたフラグ」を立てたい場合。
「マリさんとおしゃべりをしたフラグ」そのものは「00100000」なんで、これは、orを使います。
// おしゃべりしたらしい $gflg = $gflg | 00100000(二進数);
これで、gflgの「マリさんとおしゃべりをしたフラグ」が必ず1になります。
単純に「+で足しても一緒じゃん」とか思ってしまいがちですが、「すでに"マリさんとおしゃべりをしたフラグ"がたっている」場合に予期しない動きになるので、この手のflg操作にはor演算子(つまり |)を使うのが一般的です。
…っていう、なんか微妙に一般的じゃない説明を書いてみましたw
質問とかあったらよろしくです〜 ノ