アプリ版:「スタンプのみでお礼する」機能のリリースについて

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 回答 (4件)

> 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]);

を実行してみてください。ただし、わかりにくくなるトリッキーな書き方なので、使わないのが普通です。
    • good
    • 0
この回答へのお礼

ありがとうございます。
分かりました。

(ptr+2) = "aaa";

*(ptr+2) = "aaa";
の間違いでした。

お礼日時:2002/02/12 01:57

まず、"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" に書き換えられしまったのです。

よって言えることは、

○ ""で囲んだリテラル文字列を、文字列へのポインタ変数に代入してはいけない。

ということです。

ポインタマニアの、はぽるんでした。
    • good
    • 0

かなり危険ですね。


char *ptr;
として宣言しただけでは、ある、メモリ領域を指示するための、言ってみれば
目印みたいなものが用意されるだけに過ぎません。
ポインタのみを宣言した場合は、1番の方が書いているように、newなりmalloc
なりで、必要なメモリ領域を確保する必要があります。
目印が用意されただけだと、実際にどこにアクセスしいいのかは不明なため、
(下手をすればシステム領域をさしている)怪しい挙動を示します。

>char *ptr = "\0";
>としたら、できたみたいでした。
とかいてありますが、これだと、ptrの先には1バイト分の領域しか用意されません。
それを超えた分は、他のメモリ領域を食い荒らします。ということは、最悪クラッシュ
するということですね。

ポインタは、なんでも出来てしまうが故に、一番危険な存在です。
メモリの割付は忘れずにしましょう。
    • good
    • 0
この回答へのお礼

char *ptr = "\0";
でだいじょうぶかと思っていたらだめでしたか。

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

お礼日時:2002/01/20 09:03

char *ptr;



このあと、どこかで、メモリを確保していますか?>new などして

そうでなければ、
ptr = new char[100];
みたいなコードを入れてみてください。
    • good
    • 0
この回答へのお礼

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

質問文を書き間違えてました。
正しくは

wsprintf(str, "%d", 1234567);

wsprintf(ptr, "%d", 1234567);

お礼日時:2002/01/20 02:43

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!