
最近見かけたCのプログラムで、関数の引数の型は void* なのですが、その関数を使うときに 引数をvoid*でキャストしていました。
例えば、
func ( (void*) p );
こういうことです。
私の知っている知識では、
void* と 任意の型のポインタは キャストなしに相互に代入可能です。
関数の引数でも、キャストは要らないものだと思っていました。
そうすると、引数を void* でキャストするのは無意味だと思うのですが、・・・
違うのでしょうか。処理系によるとか。
逆に、関数の引数の型がchar*などで、渡すものが void* のときはどうなのでしょうか。
下のプログラムは、関数byte_orderの引数の型はvoid*ですが、int型へのポインタ( &a )を設定しています。私の環境では、コンパイルエラーも警告もないし、動作も正常です。
#include <stdio.h>
#include <string.h>
void byte_order(void *vp)
{
char char_array[4];
strncpy(char_array, vp, 4);
printf("出力します:%x %x %x %x\n", char_array[0], char_array[1], char_array[2], char_array[3]);
}
int main(void)
{
int a = 0x12345678;
byte_order(&a);
return 0;
}
このプログラムは単なる一例であって、質問はバイトオーダに関するものではありません。
また、C言語の質問であって、C++ではありません。
No.1ベストアンサー
- 回答日時:
>私の知っている知識では、
>void* と 任意の型のポインタは キャストなしに相互に代入可能です。
そのとおりです。
キャストの必要はありません。
あってもなくてもかまいません。
>関数の引数でも、キャストは要らないものだと思っていました。
>そうすると、引数を void* でキャストするのは無意味だと思うのですが、・・・
>違うのでしょうか。処理系によるとか。
明示的に”void*にしているよ!”ということを示したい場合などに私はよく書きます。
まぁ、書いても書かなくても一緒ってことですけど。
>逆に、関数の引数の型がchar*などで、渡すものが void* のときはどうなのでしょうか。
こちらに関しては、Cではエラーは出ませんが、C++ではエラーになります。
>明示的に”void*にしているよ!”ということを示したい場合などに私はよく書きます。
>まぁ、書いても書かなくても一緒ってことですけど。
>>逆に、関数の引数の型がchar*などで、渡すものが void* のときはどうなのでしょうか。
>Cではエラーは出ません
ありがとうございます。わかりました。十分です。
No.3
- 回答日時:
> ここの意味を確認させていただきたいのですけど。
関数のポインタについてのコードを含めて、補足に書かれた通りです。
規格上保証されていないとあっても、私も、期待した通りに動作しない処理系には
出会ったことがありません。
仮想メモリ上で、heap や stack に置かれるものを指すポインタと、コードが
置かれる領域を指すポインタに互換性があるわけではない、という意味だと解釈
しています。
No.2
- 回答日時:
> void* と 任意の型のポインタは キャストなしに相互に代入可能です。
ほとんど正しい知識です。「ほとんど」と書いたのは、関数のポインタだけは
ANSI の規格上、保証されていないからです。
すくなくとも、質問に
> また、C言語の質問であって、C++ではありません。
とあるのが、ある程度正しい理解をしているのだ、と想像させます。
> 逆に、関数の引数の型がchar*などで、渡すものが void* のときはどうなのでしょうか。
「渡すものが void* である」というのが、意味がありません(*)。規格上は、変換を
保証されてはいますが、それは、void* が指している内容についてまで保証して
いるわけではありません。質問にあるプログラムが、以下のようになっていても
意味がない、ということは分かるでしょう。
void byte_order(char* vp)
...
int a = 0x12345678;
void* p = &a;
byte_order(p);
(*) 特別な場合、例えば、組み込み系のプログラムで直接物理アドレスを
指すようなケースはありますが、あくまでも、特別な場合です。
この回答への補足
「任意の型のポインタ」と書いたときに思い浮かべていたのは、char* や int* ですが、「任意の」という表現は、確かに関数のポインタも含めますね。
>> void* と 任意の型のポインタは キャストなしに相互に代入可能です。
>ほとんど正しい知識です。「ほとんど」と書いたのは、関数のポインタだけは
>ANSI の規格上、保証されていないからです。
ここの意味を確認させていただきたいのですけど。
「void*型の変数に、関数へのポインタを代入したり、
関数へのポインタに、void*型の変数を代入する」
ということについてですね。
例えば、次のプログラム(実用的な意味に乏しいですが…。とりあえず私の環境ではコンパイル・リンク時にエラーも警告もなく、動作も正常)
ANSIの規格上保証されないということは、エラーになる処理系があっても問題はないことになるわけですね。
#include <stdio.h>
#include <string.h>
int main( void )
{
void *vp;
size_t ( * func_P ) (const char *);
vp = strlen ; /* void*型の変数に、関数へのポインタを代入する。*/
printf( " vpは%p\n" , vp ) ;
printf( " strlenは%p\n" , strlen ) ;
func_P = vp ; /* 関数へのポインタに、void*型の変数を代入する。 */
printf(" \"abcdefg\" の長さは%d\n" , func_P("abcdefg") );
return 0;
}
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- C言語・C++・C# 宣言する関数の形が決まっている状態で、 str1とstr2の文字列をこの順に引っ付けてstrに保存し 2 2022/05/30 18:21
- C言語・C++・C# const char** p;のとき、free(p)でC4090エラーとなるのはなぜですか 3 2023/03/31 16:28
- C言語・C++・C# c言語でユーザ関数を利用して入力された文字列を反転させるプログラムを作りたいです。 3 2023/01/29 19:47
- C言語・C++・C# c言語配列の結合についてです。 なぜうまくいかないのでしょうか。 #include <stdio.h 4 2022/05/30 22:42
- C言語・C++・C# c言語の問題です 課題1 (二分探索木とセット) 大きさ size の配列 array を考える。す 2 2023/01/10 21:08
- C言語・C++・C# カードシャッフルのブログラムを使ってc言語でブラックジャックをしたい 2 2022/04/12 15:13
- C言語・C++・C# スタックフレームの消滅 6 2023/05/20 12:33
- C言語・C++・C# Cのdoubleの浮動小数点表示について 3 2023/04/17 13:14
- C言語・C++・C# C言語 共用体について コマンドライン引数で値を2つ入力したときに、argv[2]の値をUNI u1 4 2022/04/25 20:34
- C言語・C++・C# 未解決の外部シンボル _printfが関数_mainで参照されました 1 2022/09/18 15:28
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
C言語のポインタに直接アドレス...
-
セグメントエラー
-
戻り値で構造体を返すことは可...
-
init関数の意味
-
ポインタについて
-
ExcelVBAでのkernel32(64bit)
-
LPSTR型の初期化について
-
Run-Time Check Failure #3とい...
-
トリプルポインタが必須!とな...
-
popenした子プロセスのプロセス...
-
va_listを使用したfscanf()関数...
-
基本アルゴリズムの『返す』の...
-
関数ポインタの利点
-
fopne で失敗する原因
-
C言語習得のレベル.
-
メモリのアドレスからの値の取...
-
C++で関数ポインタから関数名を...
-
アプリを32bitから64bit移行
-
#define NULL ((void *)0) の弊害
-
構造体の中の構造体
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
セグメントエラー
-
C言語のポインタに直接アドレス...
-
init関数の意味
-
Run-Time Check Failure #3とい...
-
戻り値で構造体を返すことは可...
-
ExcelVBAでのkernel32(64bit)
-
アプリを32bitから64bit移行
-
参照型で受け取った引数をポイ...
-
fopne で失敗する原因
-
PASCALとFARの意味
-
LPSTR型の初期化について
-
CWnd::EnableWindow()の扱い方
-
ポインタについて
-
プーさんのマウスポインタを教...
-
連結リスト 要素の入れ替え
-
ハンドルはポインタか
-
C++で関数ポインタから関数名を...
-
自作DLLの引数について、ポイン...
-
NULLポインタが0でない処理系と...
-
TCHAR文字列内の検索について
おすすめ情報