• ベストアンサー

wsprintf( ポインタ , "%d" , "123" );

char str[100]; char *ptr; wsprintf(str, "%d", "1234567"); と wsprintf(ptr, "%d", "1234567"); について、 TextOut(hDC,0,10,str,lstrlen(str)); TextOut(hDC,0,30,ptr,lstrlen(ptr)); で出力したいんだけど、str ならできたけど、 ptr の方が文字化けしていました。 lstrlen(ptr); がいけないのかと思って、 その値を調べたら 0 でした。 strlen( ) はポインタに対応していると思いました。 #include <iostream.h> main(){ char *p = "あいう"; cout << strlen(p); } で 6 だったから。 Win32 の lstrlen( ) はポインタに対応していないんですか?

  • A__
  • お礼率59% (194/328)

質問者が選んだベストアンサー

  • ベストアンサー
  • sssohei
  • ベストアンサー率33% (33/98)
回答No.3

> new char[100]; この場合、char 型で、100個分確保して、そのポインタが返ります new int[50] だったら int 型50個分 もちろん、型だけでなく、クラスも指定出来ます。 new string[50] > 0065FE08, 0065FE0C, 0065FE10 > で、&ptr が 0065FE00 だったとすると、 > (ptr+2) = "aaa"; *(ptr+2) = "aaa"; の間違いですよね^^; > としたら、sonota[] の値が変更されてしまうしいうことですね? 変更されますが、変更される値は"aaa"のポインタが、sonata[0]以降に格納されます。 書き換える先が、システムの領域だったら、「不正なアクセス」が起きて、プログラムが落ちます。Linuxだと「Segmentation fault」です。 後、配列とポインタは同じものと思っておいても通常差しつかえありません。array[a] は *(array + a) の様に解釈されます。そのため int array[3] = { 1,2,3 }; printf("%d, %8x\n", array[0], &array[0]); printf("%d, %8x\n", 0[array], &0[array]); printf("%d, %8x\n", array[1], &array[1]); printf("%d, %8x\n", 1[array], &1[array]); printf("%d, %8x\n", array[2], &array[2]); printf("%d, %8x\n", 2[array], &2[array]); を実行してみてください。ただし、わかりにくくなるトリッキーな書き方なので、使わないのが普通です。

A__
質問者

お礼

ありがとうございます。 分かりました。 (ptr+2) = "aaa"; は *(ptr+2) = "aaa"; の間違いでした。

その他の回答 (3)

  • haporun
  • ベストアンサー率40% (230/562)
回答No.4

まず、"1234567" が間違っています。 wsprintf(str, "%d", "1234567"); は、3つ目の引数はint型の変数だから、それを文字列に変換してstrの指す先にコピーしてくれ、という文です。 だから、 wsprintf(str, "%d", 1234567); が正しくなります。 char str[100]; char *ptr = str; とすると簡単に動作させられます。 char *ptr = "\0"; とするのは、ほかの方もおっしゃいますが、ほかの方とはまた違う理由で、この使用を勧めません。 配列初期化文以外の場所で "ほげほげ" と記述したとき、たとえばポインタ初期化で char *y = "ほげほげ"; などと記述した場合、この値はどこかで static char x[] = "ほげほげ"; と宣言されているものとして、そこにxを記述するのと同じこととなります。 つまり、"" で囲むと、プログラム起動時に自動的に静的変数が確保されるのです。 また、次のようなことが起こる場合もあります。 strcpy("abcd", "efgh"); printf("abcd"); 出力: efgh "abcd" という領域に "efgh" をコピーしろという変な文です。 そして "abcd" をプリントしているにも関わらず、"efgh" が出力されてしまうのです。 コンパイラの最適化機能によっては、""で囲んだ同じ文字列は、同じメモリ領域を指していることがあります。 よって、すべての "abcd" が "efgh" に書き換えられしまったのです。 よって言えることは、 ○ ""で囲んだリテラル文字列を、文字列へのポインタ変数に代入してはいけない。 ということです。 ポインタマニアの、はぽるんでした。

  • layer13
  • ベストアンサー率47% (37/78)
回答No.2

かなり危険ですね。 char *ptr; として宣言しただけでは、ある、メモリ領域を指示するための、言ってみれば 目印みたいなものが用意されるだけに過ぎません。 ポインタのみを宣言した場合は、1番の方が書いているように、newなりmalloc なりで、必要なメモリ領域を確保する必要があります。 目印が用意されただけだと、実際にどこにアクセスしいいのかは不明なため、 (下手をすればシステム領域をさしている)怪しい挙動を示します。 >char *ptr = "\0"; >としたら、できたみたいでした。 とかいてありますが、これだと、ptrの先には1バイト分の領域しか用意されません。 それを超えた分は、他のメモリ領域を食い荒らします。ということは、最悪クラッシュ するということですね。 ポインタは、なんでも出来てしまうが故に、一番危険な存在です。 メモリの割付は忘れずにしましょう。

A__
質問者

お礼

char *ptr = "\0"; でだいじょうぶかと思っていたらだめでしたか。 他のメモリ領域を食い荒らすというのは、 char sonota[] = "xxx"; があったして、そのアドレスが 0065FE08, 0065FE0C, 0065FE10 で、&ptr が 0065FE00 だったとすると、 (ptr+2) = "aaa"; としたら、sonota[] の値が変更されてしまうしいうことですね? この解釈が間違っていたら教えてください。

  • sssohei
  • ベストアンサー率33% (33/98)
回答No.1

char *ptr; このあと、どこかで、メモリを確保していますか?>new などして そうでなければ、 ptr = new char[100]; みたいなコードを入れてみてください。

A__
質問者

お礼

ありがとうございます。 char *ptr; だけではだめだったんですね。 メモリの確保が必要ということで、 char *ptr = "\0"; としたら、できたみたいでした。 1バイトでも確保されたらいいみたいに思ったけど、 これで問題があるなら教えてください。 new char[100]; というのを知らないから、今はとりあえず char *ptr = "\0"; としてみることにしました。 質問文を書き間違えてました。 正しくは wsprintf(str, "%d", 1234567); と wsprintf(ptr, "%d", 1234567);

関連するQ&A

  • wParam

    wParamは、unsigned int型で、仮想キーコードを、格納してますよね。 wsprintf()内で(TCHAR)キャストしてますが、 これは、変数strの型がTCHAR型なので(wParamは、unsigned intなので型をあわせるために)やっているんですか? (TCHAR)キャストしないとエラーになりますか?教えてください。 HDC hdc; TCHAR str[255]; swich(umsg){   case WM_CHAR:     wsprintf( str, TEXT("%c"), (TCHAR)wPara );     hdc = GetDC(hwnd);     TextOut(hdc, 0, 0, str, lstrlen(str));     return0 }

  • C言語で文字列バッファを消去する方法

    今、C言語とWin32 APIを使ってプログラミングをしています。 wsprintf(str,TEXT("プレイヤーの攻撃!")); TextOut(hdc,0,520,bstr,lstrlen(str)); if(ehp <= 0) {    wsprintf(str,TEXT("敵を倒しました"));    TextOut(hdc,0,520,bstr,lstrlen(str)); } このコードを実行すると、2回目のTextOutのところで 「敵をたおしました撃!」と出てしまいます。 きっとstrに以前の文字列が残っているからだと思いますが、 この保存した文字列を消去するにはどうしたらよいのでしょうか? for文でstr[0]から'\0'までナル文字を代入し続けたり、いろいろと試したのですが駄目でした。どうかこんな自分にご助力お願いできないでしょうか? どうかお願い致します。

  • wsprintf( ) でポインタに代入

    wsprintf(p, "%d" , i); を書いたせいで、i の値が変わります。 wsprintf(p, "%d" , i); によってどんなことが起こっているのか詳しく知りたいです。 ポインタのことがまだよく分かってないんです。 #include <windows.h> LPCSTR szStr = "\n char c[255];\n char *p = \"\\0\";\n int i = 12345;\n\n switch (msg){\n case WM_LBUTTONDOWN:\n  wsprintf(c, \"%d\" , i);\n  wsprintf(p, \"%d\" , i);\n  MessageBox(hWnd , c , \"\" , MB_OK);\n break;"; LRESULT CALLBACK WndProc(HWND , UINT , WPARAM , LPARAM); int WINAPI WinMain(HINSTANCE hInstance , HINSTANCE , LPSTR , int){ 省略 return msg.wParam; } LRESULT CALLBACK WndProc(HWND hWnd , UINT msg , WPARAM wParam , LPARAM lParam){ HDC hDC; PAINTSTRUCT ps; RECT rt; char c[255]; char *p = "\0"; int i = 12345; switch (msg){ case WM_LBUTTONDOWN: wsprintf(c, "%d" , i); wsprintf(p, "%d" , i); MessageBox(hWnd , c , "" , MB_OK); break; case WM_PAINT: GetClientRect(hWnd, &rt); hDC = BeginPaint(hWnd, &ps); DrawText(hDC, szStr, lstrlen(szStr), &rt, DT_WORDBREAK); EndPaint(hWnd, &ps); break; case WM_DESTROY: PostQuitMessage(0); break; default: return(DefWindowProc(hWnd , msg , wParam , lParam)); } return (0L); }

  • (SHORT)

    ウインドウプロシージャ内ですが、(SHORT)は何のためについているんでしょうか?(どんな効果がありますか) 教えてください。 case WM_MOUSEWHEEL :     wsprintf(str,TEXT("WHEEL %s"),        ((SHORT)HIWORD(wparam))>0 ? TEXT("↑"):TEXT("↓"));     hdc=GetDC(hwnd);     TextOut(hdc,0,0,str,lstrlen(str));

  • ポインタとポインタのポインタの違い

    #include<iostream> #include<cstdlib> using namespace std; long myclass(const char *start,char **end,int base=10); int main(){ long d; char *p; char ss[]="231231"; d=myclass(ss,&p,16); cout<<d; d=myclass(ss,&p); cout<<d; return 0; } long myclass(const char *start,char **end,int base){ return strtol(start,end,base); } これはあるサンプルプログラムです。 これを自分が少しいじって char *pをchar**pにして&pをpにしました。 すると初期化されていないローカル変数pが使用されますと出て、警告がでました。 自分ではどちらのソースも初期化されていないと思うのですが、実際サンプルプログラムをコンパイルすると警告はでません。 何故なのでしょうか? コンパイラはvisual studio2008です。 よろしくお願いします。

  • C++のコンストラクタを使った自動ポインタでoperator関数の使い

    C++のコンストラクタを使った自動ポインタでoperator関数の使い方で分からないところがあります。 環境下はVisual C++でC/C++のWin32コンソールアプリケーションを使って行っています。 下記のコードで実行させています。やっていることは文字列を反転させて表示させるだけのことです。 #include "stdafx.h" #include <string> #include <iostream> class AutoPtr { char *ptr; public: AutoPtr():ptr(0) { } ~AutoPtr() { delete [] ptr; } // char *operator=(char *ptr) { delete [] this->ptr; this->ptr = ptr; return this->ptr; } operator char *(){ return ptr; } char &operator[](int index) { return ptr[index]; } }; void reverse(char *str) { int i, n; AutoPtr work; n = strlen(str); work = new char[n+1]; strcpy(work, str); for(i=0; i<n; i++) { str[i] = work[n-i-1]; } printf("%s\n", str); } int _tmain(int argc, _TCHAR* argv[]) { reverse("ABCDEFG"); return 0; } これを実行させると、reverse関数のfor()文の、str[i] = work[n-i-1];を実行させた所で実行エラーになってしまいます。その前の、strcpy(work, str);でworkにstrの内容が正常にコピーされているところまでは確認できています。operator関数の、 char &operator[](int index) { return ptr[index]; } で、operator[]はAutoPtrを配列のように扱っているはずなのですが、何故かstr[i] = work[n-i-1]; の所で実行エラーになってしまいます。 operaror関数の書き方が悪いのか、何が原因なのか分かりかねています。御経験のあるかたは、御教示いただけたらと思っています。 よろしくお願い致します。

  • ポインタ配列の動的確保

    ポインタの配列の動的確保について教えてください。 入力した数値をポインタ配列に入れるプログラムです。 下記のように書いてみました。(見づらくてごめんなさい) #include<stdio.h> #include<stdlib.h> #define kensu 3 main() { char abc[kensu+1]={'A','B','C','\0'}; char *ptr[kensu]; int i; printf("3つの整数を入力して下さい。\n"); for(i=0;i<kensu;i++){ ptr[i]=(char*)malloc(sizeof(char)*10); if(ptr[i]==NULL){ printf("メモリの取得に失敗しました"); exit(1); } printf("整数%c:",abc[i]); fgets(ptr[i],10,stdin); if(ptr[i][strlen(ptr[i])-1]=='\n') ptr[i][strlen(ptr[i])-1]='\0'; } for(i=0;i<kensu;i++) free(ptr[i]); } ちゃんと動いているようです。 しかし、ポインタ配列の動的確保をネットで調べてみると、ポインタのポインタ(?)を使って、下記のように2度mallocしています。 #include <stdio.h> #include <stdlib.h> #define N 3 int main(void) { char** arr; int i,j; arr = (char**)malloc(N * sizeof(char*)); /* ポインタ配列を確保 */ /* 配列の要素それぞれにつき、メモリ領域を確保 */ for(i=0;i<N;i++) arr[i] = (char*)malloc(N * sizeof(char));   ・・・ ポインタの配列を宣言して、配列の各要素に動的確保するのと ポインタのポインタを宣言し、ポインタ配列を動的確保して、再度配列の要素に動的確保するのとでは、何か違いがあるのでしょうか? ポインタのポインタを宣言し、ポインタ配列を確保する必要性が良く分かっていないのです。 ネット等で調べて見たのですが、理解力がないのかよく分かりませんでした。 どうか教えてください。

  • Windows APIでおかしな事になる。

    Windows APIでプログラミングをしています。 Windows APIでプログラミングをしています。 char*型の文字列を表示させようと、このように記述しました。 const char * y; y=f(); SelectObject(hdc , hFont); SetBkColor(hdc , RGB(255 , 255 , 255)); wsprintf( str, "名前は、%s", y ); TextOut(hdc , 300, 20, str, lstrlen(str)); すると、表示できたのはいいのですが、 タイトルバーをクリックしてウィンドウを広げたり、別のウィンドウを一番前に持ってきて、 その後、そのウィンドウを出したりすると、エラーが出て、強制終了になってしまします。 何か問題はありますか? ちなみに、strの宣言はこのようになっております。 static TCHAR str[64]; あとですが、 wsprintf( str, "名前は、%s", y ); この部分のyを&yに変えると、エラーは起こりませんが、 変な文字が表示されてしまいます。 ウィンドウを少し操作すると、その文字がまた変な文字に変わります。 何が原因でしょうか。

  • ポインタ勉強中です。しかも実行するとおかしいです。

    <本に載ってたソース> #include<stdio.h> #include<string.h> int main() { char msg[20]; char *str=NULL; int i; int cnt; str=&msg[0]; printf("文字を入力してください"); scanf("%s",&str); cnt=strlen(msg); str=msg+cnt; for(i=cnt;i>=0;i--){ printf("%c",*(str--)); } printf("\n"); return 0; } char *str=NULL;は、ポインタstrを空にするということでしょうか? いつもながらstrlenとsizeofが混じります。 sizeofがバイトの大きさで、strlenが、文字数でしたっけ?

  • ポインタについて

    #include<stdio.h> int main(void) { char str[10]; char *ptr = str; printf("文字列を入力してください。\n"); scanf("%s",ptr); printf("文字列は%sです。",str); return 0; } 上記のプログラムのscanf("%s",ptr);の ptrに&をつけるとなぜ先頭の4文字は入力しても 表示されなくなってしまうのでしょうか? よろしくお願いします。