型のキャストについて

ActiveBasic製ソフトウェア、またはABサイドのソフトウェアを開発された方は、こちらへご紹介ください。関連Webサイトの紹介などもこちへ。
返信する
メッセージ
作成者
山本
Site Admin
記事: 535
登録日時: 2005年5月30日(月) 15:08
連絡する:

型のキャストについて

#1 投稿記事 by 山本 »

型のキャストについて
コミュニティトピック : これはエラーを出したほうが良いと思います
http://www.discoversoft.net/forum/viewtopic.php?t=251

Discoversoft管理人日記 : ABのタイプキャスト問題
http://d.hatena.ne.jp/dai_optimistic/20050804
というこでして、現行AB4は型チェックが甘いんじゃないかというご指摘…。今後は複雑化するであろうコードを前提としていかなければならないので、最低限の言語仕様として、型のキャストを考えていく必要があります。


早速、型のキャストについての案件なのですが…



1. #strictディレクティブ
ソースコード中に"#strict"が存在すると、厳密な型チェックを行うようにします。指定されていない場合は、現在と同様、型チェックはプログラマーに任せられます。


2. キャストについて
CDbl、CSng、CLong、CDWord、CInteger、CShort、CByte、CCharなど、キャストの際に使うコンパイラ埋め込み型関数を追加します。しかし、この手法を採用するとある問題が出てきます。それは、オブジェクトポインタのキャストです。

C言語では、

RECT *pRect;
void *ptr;
pRect=(RECT *)ptr;

という記述ができますが、この案件のキャストは関数の形をしているため、オブジェクトポインタの型を明示できなくなります。となると、C言語のように、カッコで型名をくくるなどの対策が必要になりますが、そうすると更にC/C++の色が強くなってしまいそうです。それに加え、熟練したプログラマーであればC/C++風のキャストは便利なのですが、Basic言語としての取っ付き易さを考慮するとあまり気の進む仕様変更でもありません。

いっそのこと、すべてのポインタ変数はCPtrというキャスト関数で済ませてしまい、VoidPtr扱いにしてしまうか…。そうすると、またまた甘い型チェックということになってしまいそうです…。

こんな感じでキャストの方法が一番悩ましいところです。何かいい記述方法、ありませんでしょうか…?
xsb007

#2 投稿記事 by xsb007 »

以下の2方法が考えられます。

1.CPtrの第二引数にポインタの型を指定

Dim pRect as *RECT
Dim ptr as VoidPtr
pRect=CPtr(ptr,RECT)

2.Castの第二引数に変換後の型を指定

Dim pRect as *RECT
Dim ptr as VoidPtr
pRect=Cast(ptr,*RECT)
hira
記事: 203
登録日時: 2005年5月31日(火) 20:14
お住まい: 兵庫県
連絡する:

Re: 型のキャストについて

#3 投稿記事 by hira »

> CDbl、CSng、CLong、CDWord、CInteger、CShort、CByte、CCharなど、キャストの際に使うコンパイラ埋め込み型関数を追加します。しかし、この手法を採用するとある問題が出てきます。それは、オブジェクトポインタのキャストです。
>
> C言語では、
>
> RECT *pRect;
> void *ptr;
> pRect=(RECT *)ptr;
>
> という記述ができますが、この案件のキャストは関数の形をしているため、オブジェクトポインタの型を明示できなくなります。となると、C言語のように、カッコで型名をくくるなどの対策が必要になりますが、そうすると更にC/C++の色が強くなってしまいそうです。それに加え、熟練したプログラマーであればC/C++風のキャストは便利なのですが、Basic言語としての取っ付き易さを考慮するとあまり気の進む仕様変更でもありません。

SizeOf関数で行われているように、引数に型名を取れるようにしてはどうでしょうか?
例えば pRect=Cast(ptr,*RECT) のような感じです。
または、Cast(ptr As *RECT) のようにするという手もあるかもしれません。
どちらにしても、少々強引な気がしないでもないですが…。
イグトランス
記事: 899
登録日時: 2005年5月31日(火) 17:59
お住まい: 東京都
連絡する:

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

もしCスタイルのキャストを採用するなら、それよりもC++/D形式のスタイルがいいのではないかと思います。
C++はstatic_cast<型>(式)などで、Dはcast(型)式という形です。

コード: 全て選択

RECT *pRect1, *pRect2; 
void *ptr;
pRect1 = static_cast<RECT *>(ptr); /* C++ */
pRect2 = cast(RECT *)ptr; /* D */
ようするにCスタイルのキャストだけは勘弁してくれということです。あとからコードを見たときうっかり見過ごしてしまいそうなほどCスタイルキャストは目立ちません。
もちろんxsb007さんやhiraさんのCast関数の引数というのも悪くありません。
それどころか今1番いいんじゃないかと考えているのはhiraさんのAsです。私は括弧は要らなさそうに思うのでCast ptr As *RECTはどうかと思います。

ところでC#にはキャストの一種としてasがあり、構文は式 as 型でhiraさんの案に偶然ながら近いです。あちゃ、これでもいいような気もしてくる。

コード: 全て選択

pRect = Cast(ptr As *RECT)
pRect = Cast ptr As *RECT
pRect = ptr As *RECT
山本
Site Admin
記事: 535
登録日時: 2005年5月30日(月) 15:08
連絡する:

#5 投稿記事 by 山本 »

"As 指定"、見過ごしていました。良さそうですね。

Dim a As *RECT
Dim base As *RECT
Dim i As Long
a=base As *RECT
a=(base As Long + i As Long) As *RECT

こういう記述もできそうです。これだったら、新しい仕様の使い勝手としてはかなりいいほうですね。有力候補として検討していこうと思います。
xsb007

#6 投稿記事 by xsb007 »

>"As 指定"、見過ごしていました。良さそうですね。

これならキャスト関数はコンパイラレベルでサポートしなくても、マクロ定義でできるから CastとC(型) 両方サポートするよりも簡単そうですね。

Const CByte(a) = ((a) As Byte)
Const CInt(a) = ((a) As Integer)
Const CLng(a) = ((a) As Long)
Const CDWord(a) = ((a) as DWord)
Const CSng(a) = ((a) as Single)
Const CDbl(a) = ((a) as Double)
高信期

Re: 型のキャストについて

#7 投稿記事 by 高信期 »

型キャストの疑問はここでいいのかな…

さて、計算途中に型キャストを指定してもキャストされないのは仕様でしょうか?

コード: 全て選択

#prompt
Dim A = &H7FFFFFFF As Long
Print Hex$((A As Word) - 1) '7FFFFFFE と表示されてしまう
山本
Site Admin
記事: 535
登録日時: 2005年5月30日(月) 15:08
連絡する:

#8 投稿記事 by 山本 »

高信期 さんが書きました:型キャストの疑問はここでいいのかな…

さて、計算途中に型キャストを指定してもキャストされないのは仕様でしょうか?

コード: 全て選択

#prompt
Dim A = &H7FFFFFFF As Long
Print Hex$((A As Word) - 1) '7FFFFFFE と表示されてしまう
ご報告ありがとうございます。16ビット整数値へのキャストを行ったときにデータの切り捨てが正常に行えないバグを確認できましたので、次回のバージョンアップで修正します。
高信期

#9 投稿記事 by 高信期 »

たびたびすみません。
リテラル値を64bit整数型にキャストしたものを乗算しようとするとアクセス違反が起きます。
またキャストとは関係ないのですが、リテラル値同士の \ での除算が異常な値を返します。
ABver4.1beta1で確認しました。

(Codeで囲うと \ が / と表示されるようなのでべた書きで)
#prompt
Dim A = 356 As Word
Print Str$(356 \ 12) '2が表示される
Print Str$((A As QWord) * &HAAAAAAAB) '変数であれば問題なし
Print Str$((356 As DWord) * &HAAAAAAAB) '64bit整数型にキャストしなければ問題なし
Print Str$((356 As Int64) * &HAAAAAAAB) 'アクセス違反が起きる
Print Str$((356 As QWord) * &HAAAAAAAB) 'アクセス違反が起きる
山本
Site Admin
記事: 535
登録日時: 2005年5月30日(月) 15:08
連絡する:

#10 投稿記事 by 山本 »

高信期 さんが書きました:リテラル値を64bit整数型にキャストしたものを乗算しようとするとアクセス違反が起きます。
またキャストとは関係ないのですが、リテラル値同士の \ での除算が異常な値を返します。
ABver4.1beta1で確認しました。

(Codeで囲うと \ が / と表示されるようなのでべた書きで)
#prompt
Dim A = 356 As Word
Print Str$(356 \ 12) '2が表示される
Print Str$((A As QWord) * &HAAAAAAAB) '変数であれば問題なし
Print Str$((356 As DWord) * &HAAAAAAAB) '64bit整数型にキャストしなければ問題なし
Print Str$((356 As Int64) * &HAAAAAAAB) 'アクセス違反が起きる
Print Str$((356 As QWord) * &HAAAAAAAB) 'アクセス違反が起きる
ご報告ありがとうございます。下記のバグを確認することができましたので、次回のバージョンアップで修正します。

・リテラル値同士の整数除算""が正常に行えないバグ
・64ビット整数値へのキャストをリテラル演算内で正常に行えないバグ
高信期

#11 投稿記事 by 高信期 »

キャストしたリテラル値を定数にしようとしても無効となるようです。
またキャスト関連とは違うバグですが、
#promptを指定したプログラムが最後にEnd命令語を呼び出さずに終了するとアクセス違反が起きます。

コード: 全て選択

Const BYTE_MAX = (-1 As Byte)
#prompt
Print Str$(BYTE_MAX)
高信期

#12 投稿記事 by 高信期 »

環境を書き忘れました。
WinXp Home SP2
IE6 SP2
です。
山本
Site Admin
記事: 535
登録日時: 2005年5月30日(月) 15:08
連絡する:

#13 投稿記事 by 山本 »

ご報告ありがとうございます。

Str$関数など、パラメータに浮動小数型を持つ場合に発生するようです。ようは、パラメータ引き渡し時にByte→Doubleの変換が正常に行われていないってことになります。

こちら、バグ扱いとなりますので、次回のバージョンアップで修正します。
返信する