コンボボックスの編集で苦戦しています

ActiveBasicでのプログラミングでわからないこと、困ったことなどがあったら、ここで質問してみましょう(質問を行う場合は、過去ログやWeb上であらかじめ問題を整理するようにしましょう☆)。
メッセージ
作成者
7
記事: 473
登録日時: 2005年5月31日(火) 18:51
お住まい: 新潟県
連絡する:

Re: コンボボックスの編集で苦戦しています

#16 投稿記事 by 7 »

> Char → Long の上位変換を論理演算で表現しようとするとこんな感じなのかな?
>

コード: 全て選択

Dim a As Long
> Dim b As Char
> b = -2
> a = &HFFFFFFFF Xor Not b
> 
>
> *追記
> 上でいけるかと思いましたが、
> Not b の結果がLong型になってないと成立しない計算ですね。
ぅ~ん...どういう処理をしてるのかほとんど分からないですね...。
それにしてもコンボボックスから随分とお話をずらしてしまいました...。
イグトランス
記事: 899
登録日時: 2005年5月31日(火) 17:59
お住まい: 東京都
連絡する:

#17 投稿記事 by イグトランス »

淡幻星さん さんが書きました:Code:
Dim w As Word
Dim i As Integer

i = &Hffff '「-1」を表す。
w = i As Word '「65535」を表す。
> 値が溢れた場合?、上限値(?)が設定されるんですね。これは何か使い道がありそう。
というよりもこれはInteger型の-1のビットパターンが、ちょうどWord型の65535のビットパターンと一致するからです。
2の補数 - Wikipedia

符号付整数も符号無整数も所詮はビットの並びです。
そのビットの並びは、プログラマが符号付だと言えば符号付として扱われ符号無だと言えば符号無として扱われます。
それを指示する手段がABなどの言語では型というわけです。

ABの整数型同士の変換の場合、変換先が元より小さければ、
単に下位から変換先の型の大きさのビットパターンを取り出していくはずです。(下位ビットを論理積しているも同然ですね)
逆に変換先が大きければ、下位のビットには元のビットパターンを当てはめ、
上位のビットには、おそらく変換先の型が符号付か符号無かによって符号拡張か0拡張を行うはずです。
符号拡張 - Wikipedia
淡幻星
記事: 183
登録日時: 2005年7月19日(火) 07:02
お住まい: 宮城県
連絡する:

Re: コンボボックスの編集で苦戦しています

#18 投稿記事 by 淡幻星 »

引き続き蛇足・・・。
新スレを立てるべきかもしれませんね^^;
7さん さんが書きました:> 使ったことの無いChar型についてちょっと調べてみたら、ASCIIコードだけを扱うんですね。
> -128~127なので、マイナスの文字コードがあってそれを操作する為の型なのかと思ってました...。
ちなみに私は、Char型=Byte型だとさっきまで思ってました(^^;)。
文字コード(ASCII)を扱うための変数なのに、なんで符号付にしているのか・・・。
必要なのは0~255なのだから、符号無で良いじゃないかと。
それとも・・・いわゆるアルファベットは0~127の範囲だから、
だったら空いたビットを用いてマイナスも表現しておこう、というノリなのか。
う~ん。分からない(?_?)

7さん さんが書きました:> 値が溢れた場合?、上限値(?)が設定されるんですね。これは何か使い道がありそう。
いや、「-1」はオーバーフロー(上限値超)の意味じゃないです。
> いや、ご存知じゃないです...どうやるんでしょう。説明をうまく理解できません...。
失礼しました。
えっと・・・
「それぞれの変数型の値の表現法方法が違うのです」って言って伝わるでしょうか?

簡単のために、ビット数が一番小さいChar型(符号あり)、Byte型(符号無し)を例に取ります。
ともに8bitで値を表現します。
Char型は正負の整数を表すための型です。
ここで「マイナスを表現するために最上位のビットを利用する」と約束します。
したがって、最上位を除いた残りの7bitで整数を表現することになります。
その範囲は

コード: 全て選択

000,0000( = 0) ~ 111,1111( = 127)
になります。
これで正の整数は最大127まで表現できました。
では、残りの1ビット(最上位)を使って負の整数を表現することを考えます。
バランス的に、-128くらいまで表現できれば良いですよね。
ならば「最上位のビットはマイナスを意味する」と約束
1000,0000 = 128 → Char型においては「-128」を意味する 
とするわけです。
したがって、

コード: 全て選択

 8ビット         最上位     それ以外のビット
(&H80)
1000,0000 = 1000,0000 + 0000,0000
         = (-128) + 0
         = -128

(&Hf5)
1111,0101 = 1000,0000 + 0111,0101
         = (-128) + 117
         = -10

(&Hff)
1111,1111 = 1000,0000 + 0111,1111
         = (-128) + 127
         = -1

(&H75)
0111,0101 = 0000,0000 + 0111,0101
         = ( 0 ) + 117
         = +117

(&H0a)
0000,1010 = 0000,0000 + 0000,1010
         = ( 0 ) + 10
         = +10
(&H7f)
0111,1111 = 0000,0000 + 0111,1111
         = ( 0 ) + 127
         = +127
と8bitを用いて-128~+127が表現されるわけです。

一方でByte型は、符号無しなので、符号の有無を考える必要が無く、
8ビット全部を使って整数を表現すれば良い。
したがってその範囲は

コード: 全て選択

0000,0000( = 0) ~ 1111,1111( = 255)
になります。

つまり、同じ8ビットを使った整数の表現でも、表現方法(=約束事)の違いによって、
ビットが表す値が変わる、ということです。
そこをキチンとやるために型変換(キャスト)が必要、となるわけです。

コード: 全て選択

Dim b As Byte
Dim c As Char
Dim i As Integer

b = 255 '(=1111,1111)
c = -1 '(=1111,1111)

'仮にキャストしなければ、そのままビットを移すと仮定して
i = b '(0000,0000,1111,1111 = 255)
i = c '(0000,0000,1111,1111 = 255) ※つまり「-1→255」であり、値が壊れた。

i = c As Integer '(1111,1111,1111,1111 = 65535)※キャストすると、値が壊れないようにビットを変えて格納する
/*
Integer型に置いて、-1は「1111,1111,1111,1111=&Hffff」で表現される。
したがって、格納されるビットの内容はcのビットをそのまま移したもの(&H00ff)ではなく、
こちらの&Hffffとなる。これによって「-1→-1」となり、値は壊れない・
*/
・・・でも、上記のコードは嘘で(マテ)、実際にはキャストしなくても
「-1→-1」ちゃんと保持(暗示的にキャストしてる)してくれますね。
わ~い、コンパイラさん賢い~(苦笑)。
むしろ、こっちみたいですね。キャストに意味を持たせようとするならば。

コード: 全て選択

Dim b As Byte
Dim c As Char
Dim i As Integer

b = 255 '(=1111,1111)
c = -1 '(=1111,1111)

i = b '「255」が代入される。
i = c As BYte '「255」が代入される。

i = b As Char '「-1」が代入される。
i = c '「-1」が代入される。
・・・う~ん。キャストの必要性を感じねーな(爆)。
(個人的には、構造体のキャストくらいしか恩恵感じてなかったり・・・とまた余計なことを言ってみる^^;)。

---
追記:
また前後してしましました。今度はイグトランスさんと・・・。
あ~、「符号拡張」って呼ぶんですね。初めて知りました^^;。
イグトランス
記事: 899
登録日時: 2005年5月31日(火) 17:59
お住まい: 東京都
連絡する:

#19 投稿記事 by イグトランス »

2/4/8バイト整数型には符号付と符号無の両方があるのに、
1バイト整数型だけは符号無のByteしかなく不揃いだったということが、Char型を導入した最大の動機だと思っています。
そしてChar型という名前はC/C++で1バイト符号付整数型と言えばchar型ということからでしょう。
#ちなみにC/C++のchar型は符号付のほうが多い気がしますが、符号の有無はどちらでも良いことになっています。

文字列に対してCharへのポインタや配列を使おうと思っても結局は*Byteとのキャストの山になりいまいち使えないのが個人的には残念です。
#いつかヘッダをいっせいに書き換えてみたいですが互換性のためいつまでもこのままでありそうな気がしてなりません
7
記事: 473
登録日時: 2005年5月31日(火) 18:51
お住まい: 新潟県
連絡する:

#20 投稿記事 by 7 »

イグトランスさん さんが書きました:> 値が溢れた場合?、上限値(?)が設定されるんですね。これは何か使い道がありそう。
というよりもこれはInteger型の-1のビットパターンが、ちょうどWord型の65535のビットパターンと一致するからです。
2の補数 - Wikipedia

上位のビットには、おそらく変換先の型が符号付か符号無かによって符号拡張か0拡張を行うはずです。
符号拡張 - Wikipedia
どちらのリンク先も難しくて悩ましいんですけど、各ビットを反転させた値に1を足すと符号の逆転?が出来るってのが驚きというか勉強になりました。
実用的かどうかは...?。

コード: 全て選択

Dim i As Integer
	i=10000
	i=(i Xor &HFFFF)+1	' -10000になる
	' i=-i	' いつもはこうやる
淡幻星さん さんが書きました:つまり、同じ8ビットを使った整数の表現でも、表現方法(=約束事)の違いによって、
ビットが表す値が変わる、ということです。
そこをキチンとやるために型変換(キャスト)が必要、となるわけです。

中略

・・・でも、上記のコードは嘘で(マテ)、実際にはキャストしなくても
「-1→-1」ちゃんと保持(暗示的にキャストしてる)してくれますね。
なるほど。だから値が壊れる現象って起きないんですね。(あんまり?)
淡幻星さん さんが書きました:(個人的には、構造体のキャストくらいしか恩恵感じてなかったり・・・とまた余計なことを言ってみる^^;)。
余計なことを言ってくれましたね(^_^)
構造体のキャストってどういうことでしょうか?

コード: 全て選択

Dim rc As RECT
Dim pt As POINTAPI

	' ウィンドウの位置をPOINTAPIに代入(コピー)する
	' 通常のやり方
	GetWindowRect(hMainWnd,rc)
	memcpy(VarPtr(pt),VarPtr(rc),SizeOf(POINTAPI))

	' ウィンドウの位置をPOINTAPIに代入(コピー)する
	' 構造体のキャスト?動かない。
'	GetWindowRect(hMainWnd,rc)
'	pt=rc As POINTAPI
これ動いたら凄くいいと思いました...。
淡幻星
記事: 183
登録日時: 2005年7月19日(火) 07:02
お住まい: 宮城県
連絡する:

#21 投稿記事 by 淡幻星 »

> 余計なことを言ってくれましたね(^_^)
> 構造体のキャストってどういうことでしょうか?
あはは。
ちょっと言い方に語弊がありました。失礼。
「GetMessage?とかで得てきた構造体のポインタ(DWord型)を、
 構造体(RECT型とか)にキャストして使うことがある」って意味でした。
リストビューの処理で、これを使って「あ、コーディングしやすい」って思ったので^^;

時間が合ったら、後でもう少し詳しく書きます。ではでは。
淡幻星
記事: 183
登録日時: 2005年7月19日(火) 07:02
お住まい: 宮城県
連絡する:

勘違いでした。すみません。

#22 投稿記事 by 淡幻星 »

> 構造体のキャストってどういうことでしょうか?
>

コード: 全て選択

Dim rc As RECT
> Dim pt As POINTAPI
> 
> 	' ウィンドウの位置をPOINTAPIに代入(コピー)する
> 	' 通常のやり方
> 	GetWindowRect(hMainWnd,rc)
> 	memcpy(VarPtr(pt),VarPtr(rc),SizeOf(POINTAPI))
> 
> 	' ウィンドウの位置をPOINTAPIに代入(コピー)する
> 	' 構造体のキャスト?動かない。
> '	GetWindowRect(hMainWnd,rc)
> '	pt=rc As POINTAPI
> これ動いたら凄くいいと思いました...。
7さん、大変申し訳ない。
私の勘違いでした。

コード: 全て選択

pt = rc As POINTAPI
/* C/C++だと、これで通ったはず。
  pt = (POINTAPI)rc
*/
で、任意の構造体へキャストできるよな~、って思って書いたのですが
それはC/C++の話でした。m(_ _)m
私もABでこれをやろうとしたらエラーして、結局memcpy()を使ったのでした。
失礼いたしました。
7
記事: 473
登録日時: 2005年5月31日(火) 18:51
お住まい: 新潟県
連絡する:

Re: 勘違いでした。すみません。

#23 投稿記事 by 7 »

> C/C++の話でした。m(_ _)m
> 私もABでこれをやろうとしたらエラーして、結局memcpy()を使ったのでした。
C/C++のお話でしたか...ABでも動いたらすごくイイですよねっ!
返信する