printfで表示したアドレス値を、int変数に代入するのが目的です。
#include <iostream>
using namespace std;
main(){
char buf[20];
char *(*pp)[2];
char *p[2];
int i;
pp = &p;
printf("%lu\n", pp);
// i = (int)(&pp);
sprintf(buf, "%lu\n", pp);////
i = atoi(buf);////
printf("%lu\n", i);
}
とりあえずできていますが、
pp = &p;以降の処理で、bufを使ったり非推奨?のatoi()を使っています。
pp = &p;以降の処理でもっとよい方法はないでしょうか?
また、このソースは不正なことをやっていないでしょうか?
必要な初期化をやってない、などということはありませんか?
No.10ベストアンサー
- 回答日時:
// i = (int)(&pp);
のようにしてあるのは、
i = (int)(&pp);
//sprintf(buf, "%lu\n", pp);////
//i = atoi(buf);////
だと結果がおかしかったからです。
i = (int) pp; としてください。(&をとってください)
それで正しい結果が得られます。
もし、だめなら
i = unsigned long;として
i=(unsigned long)pp;としてください。
No.11
- 回答日時:
#1です。
私の#1の回答で正解だったのが、#11の回答ではっきりしてすっきりしました。
私の#1の回答では、変数の宣言方法が変化していることに注意してください。
私は、質問者のソースに対して回答を出したのではなく、ポインタを整数にキャストする方法を説明しただけですから。
※要は、質問者がポインタの使い方をわかっていないだけのことだった。
No.9
- 回答日時:
// i = (int)(&pp); ・・・・A方式
sprintf(buf, "%lu\n", pp);////
i = atoi(buf);////
printf("%lu\n", i); ・・・・B方式
A方式でもB方式でも、同じ結果が得られる
として、
どうしてB方式のやり方(もしくはもっとうまいやり方)のほうにこだわるのか(又はA方式が何故まずいと考えるのか)に非常に興味があります。
よろしかったら、その理由を教えていただけませんでしょうか。私としては、A方式がシンプルで良いと思うのですが。
この回答への補足
それが分かっていなかったのですか。逆ですよ。
質問文で
// i = (int)(&pp);
のようにしてあるのは、
i = (int)(&pp);
//sprintf(buf, "%lu\n", pp);////
//i = atoi(buf);////
だと結果がおかしかったからです。
なのでA方式の方法で得たいです。
No.8
- 回答日時:
どう転んでも、
unsigned int ではなくて、unsigned long でしょうね。
%ul という書式指定に対応するのは。
そして、その値は、「アドレス値」であるという保証はありません。
たまたま、printf() に積み上げられたポインタの値を、unsigned long だと解釈して表示してみただけのものですから。
ですから、ポインタの値を、%ul という書式指定で解釈すること自体が、「不正」なのです。
例えば、64bit Windows の時代に、Visual C++ で、同じソフトを動かすと、かなり不幸な目に会うはずです。(URL 参照)
また、古くは 16bit の時代では、MS-DOS だとこのプログラムはとりあえず動きます。が、int の変数に代入された結果が異なるのに、同じアドレスを参照しているポインタというのが、山ほど存在しているような環境でした。
そして、ここで上げた2例も、それぞれの時代には、「充分一般的」でしょう。(だったでしょう)
参考URL:http://pcweb.mycom.co.jp/articles/2004/06/24/win …
この回答への補足
ポインタの値を%ulで処理してはいけない理由は、型がポインタだからですか?
環境によるサイズが理由でだめということなんでしょうか?
No.7
- 回答日時:
printfで表示したアドレス値を、int変数に代入するのが目的です。
それなら、ご呈示のソースで概ねOKでしょう。
ただし、既に指摘があるように、それは、「アドレス値」であるという保証はありません。単に、「ポインタ変数の中身を、%lu という書式で変換した」だけのものです。
他には、sprintf で buff に書き込んで、sscanf で読み込むとか、fprintf と fscanf の組み合わせも良いでしょう。
あと、「int変数に代入するのが目的」なのに、%lu という書式指定はいかがでしょうか?
その通りなら、書式指定は、%d のはずですね。
特に、u サフィックスがあるものを int に変換するのはその時点で変です。
> また、このソースは不正なことをやっていないでしょうか?
この点は、そもそも、ポインタ変数の値を "%ul" で変換すると言うこと自体が、printf() 系の関数の使い方として誤りです。
参考 URL は、「ポインタをlong型変数で保持できると決めつける」についてです。
参考URL:http://www.cmagazine.jp/src/kinjite/c/notcoding. …
この回答への補足
%luは、アドレス値が大きかった場合に不になってしまう対策です。
7行目はint i;でなくunsigned int i;と書くべきでした。
これなら「ポインタをlong型変数で保持できると決めつける」とすれば%luを使うことについては問題ないですか?
No.6
- 回答日時:
#5 & #6です。
> 普通が分かる人間の回答しかあてになりません。
あなたの「普通」がどういうものかは知りませんが、少なくとも私が普段仕事で感じている「普通」は、汎整数型やポインタ型のサイズはさまざまであるということです。
> intは4バイトです。
依然として、ポインタのサイズとlongのサイズは特定しないわけですね。
> 質問者がこんな高度なこと理解できるわけないでしょ。
理解できなければ、理解できるまで、まずは自分で調べてください。
> sprintf(buf, "%lu\n", pp);////
> i = atoi(buf);////
> よりもよいソースは思いつかなかったということですか?
何をもって「よい」とするかを明確にしましょう。
私は、少なくとも未定義の動作を追放し、ポインタがunsigned longより大きい場合を除いて、処理系への依存性も排除しました。元のコードより格段に「よく」なっているはずです。#include <iostream>を除去し忘れたのが、唯一の汚点です。
もう少し、詳しくみていくと、
> printfで表示したアドレス値を
とのことですので、処理系に依存せずに同じ値を取得するには、sprintfを使うか、fprintfでいったんファイルに書いてから読む以外にありません。
これはテストコードとのことですので、実際の利用に際しては"C"ロケール以外に設定されているかもしれないため、3桁ごとの区切りが挿入される等の可能性があるからです。
次に、その値をintに変換する方法です。ロケールも考慮すると確実な方法はないのですが、まともな動作を期待できるのはsscanfとstrtoulです。どちらでもよいのですが、strtoulの方が効率がよいので、今回はそれを利用しました。
> 欲しい回答はSTL未使用のものです。
#6の回答では、STLを一切使用していません。
> なにしろ初心者なので。
STLの意味も理解されていないようですので、初心者であることはよく分かります。しかし、この際、「初心者」というのが免罪符にならないことも理解してください。
No.5
- 回答日時:
とりあえず、処理系に依存しないように書いてみました(ただし、標準準拠度の低い処理系は無視)。
ポインタがunsigned longより大きい場合は、意図的にコンパイルエラーが発生するようにしています。
#include <iostream>
#include <cerrno>
#include <cstdio>
#include <cstdlib>
#include <climits>
using namespace std;
template <bool Cond, typename T1, typename T2>
struct select
{
typedef T2 type;
};
template <typename T1, typename T2>
struct select<true, T1, T2>
{
typedef T1 type;
};
template <size_t N>
struct ptr2int
{
typedef typename select<N <= sizeof(unsigned long), unsigned long, void>::type type;
};
int main()
{
char buf[(sizeof(unsigned long)*CHAR_BIT+2)/3+1];
char *(*pp)[2];
char *p[2];
int i;
pp = &p;
printf("%lu\n", ptr2int<sizeof(pp)>::type(pp));
sprintf(buf, "%lu\n", ptr2int<sizeof(pp)>::type(pp));
errno = 0;
unsigned long t = strtoul(buf, 0, 10);
if (errno != 0 || t > INT_MAX)
puts("overflow");
i = static_cast<int>(t);
printf("%d\n", i);
return 0;
}
この回答への補足
この質問に限っては
sprintf(buf, "%lu\n", pp);////
i = atoi(buf);////
よりもよいソースは思いつかなかったということですか?
STLが処理系に依存する話はここのスレには書かないで下さい。
どんなコンパイラでもSTLはサポートされることにしておきましょう。
欲しい回答はSTL未使用のものです。
なにしろ初心者なので。
No.4
- 回答日時:
処理系を特定していないのでどうしようもないのですが...
> また、このソースは不正なことをやっていないでしょうか?
とりあえずこの部分だけ。
・printfやsprintfを関数原型なしで呼び出した場合の動作は未定義です。
・実引数ppおよびiを"%lu"で受けていますが、型に矛盾があるので動作が未定義です。
・sprintf関数で、bufの最後を越えて書き込んだ場合の動作は未定義です。
・atoi関数では、結果の値が表現できない場合の動作は未定義です。
想定している処理系があるのでしょうが、それにしても未定義になる部分が多すぎます。
No.3
- 回答日時:
はっきりいって、プログラムをする目的が理解不能ですね。
単純にアドレスを表示するなら、%pでするべきです、これなら、セグメントとオフセットで表示されます。ここから、セグメントとオフセットを取り出すことは可能です(というか、そういう手続もある)。
これをlongで受けてもはみ出すことはあるし(キャストだとユーザーは検知不能)、intではなおさらでしょう。
このプログラムでは、ppに代入している時点でオーバーフローしているはずで、pp(intだとすれば)にはすでに意味をなさない数値が入っていると思いますから、それを参照しても無意味です。
この回答への補足
どう見てもテストプラグラムですよ。
有益なソフトの作成に見えたとしたらはっきりいって、専門家???ですよ。
ppに代入している時点でオーバーフローというのは間違っていませんか?
ポインタのサイズとlongのサイズは普通同一です。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
関連するカテゴリからQ&Aを探す
おすすめ情報
- ・漫画をレンタルでお得に読める!
- ・人生のプチ美学を教えてください!!
- ・10秒目をつむったら…
- ・あなたの習慣について教えてください!!
- ・牛、豚、鶏、どれか一つ食べられなくなるとしたら?
- ・【大喜利】【投稿~9/18】 おとぎ話『桃太郎』の知られざるエピソード
- ・街中で見かけて「グッときた人」の思い出
- ・「一気に最後まで読んだ」本、教えて下さい!
- ・幼稚園時代「何組」でしたか?
- ・激凹みから立ち直る方法
- ・1つだけ過去を変えられるとしたら?
- ・【あるあるbot連動企画】あるあるbotに投稿したけど採用されなかったあるある募集
- ・【あるあるbot連動企画】フォロワー20万人のアカウントであなたのあるあるを披露してみませんか?
- ・映画のエンドロール観る派?観ない派?
- ・海外旅行から帰ってきたら、まず何を食べる?
- ・誕生日にもらった意外なもの
- ・天使と悪魔選手権
- ・ちょっと先の未来クイズ第2問
- ・【大喜利】【投稿~9/7】 ロボットの住む世界で流行ってる罰ゲームとは?
- ・推しミネラルウォーターはありますか?
- ・都道府県穴埋めゲーム
- ・この人頭いいなと思ったエピソード
- ・準・究極の選択
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
C言語のポインタに直接アドレス...
-
セグメントエラー
-
関数ポインタの利点
-
C言語の文字列?処理 strcpyやl...
-
fopne で失敗する原因
-
PASCALとFARの意味
-
LPSTR型の初期化について
-
^と*の違いについて
-
アプリを32bitから64bit移行
-
VBはCを混乱させる?
-
【なぜポインタを使うのか】
-
init関数の意味
-
ハンドルはポインタか
-
x64プログラムでアドレスが32bi...
-
Cで作成したDLL関数をVBから呼...
-
VB.NET DLL【API関数(コールバ...
-
こんな内容の本を探しています
-
**って何でしょう?
-
gccでMAKEINTRESOURCEするとdif...
-
アドレスをint変数に代入する方法
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
C言語のポインタに直接アドレス...
-
init関数の意味
-
セグメントエラー
-
fopne で失敗する原因
-
戻り値で構造体を返すことは可...
-
Run-Time Check Failure #3とい...
-
ExcelVBAでのkernel32(64bit)
-
LPSTR型の初期化について
-
C言語でのconstを返す関数
-
ハンドルはポインタか
-
【C言語】戻り値が構造体の関数
-
nullポインタを逆参照とは?
-
基本アルゴリズムの『返す』の...
-
参照型で受け取った引数をポイ...
-
#define NULL ((void *)0) の弊害
-
アプリを32bitから64bit移行
-
ハンドル、アドレス、ポインタ...
-
デバイスハンドルとは?
-
C++で関数ポインタから関数名を...
-
Cで作成したDLL関数をVBから呼...
おすすめ情報