• ベストアンサー

newについて

newを使った場合、3バイト分確保したつもりでしたが、7バイト?になります。どうしてでしょうか? newした場合はdeleteをしないといけませんが、deleteした後にNULLで初期化する意味はあるのでしょうか? CとC++が混在?(newはC++かな?)しているソースなのですが、 現場(クリティカルな開発)ではこういう書き方はNGでしょうか? 組み込み系のお仕事をされている方の意見も聞きたいです。 #include <string.h> void main(void){ char *cstr = new char [3]; printf("%d\n", strlen(cstr)); // 3を期待していたのですが、7になります。 if (cstr != NULL){ delete cstr; cstr = NULL; } }

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

  • ベストアンサー
  • jacta
  • ベストアンサー率26% (845/3158)
回答No.2

> newを使った場合、3バイト分確保したつもりでしたが、7バイト?になります。どうしてでしょうか? 領域は割付けても、その内容は不定だからです。 > newした場合はdeleteをしないといけませんが、 newした場合でも、常にdeleteしないといけないわけではありませんが... > deleteした後にNULLで初期化する意味はあるのでしょうか? すでにdeleteしたポインタを誤って使ってしまわないようにするための対策です。 > CとC++が混在?(newはC++かな?)しているソースなのですが、 こういうのは混在しているとはいいません。 > 現場(クリティカルな開発)ではこういう書き方はNGでしょうか? クリティカルな開発というのが何を意味するのか分かりませんが... 少なくとも、未初期化のchar配列に対してstrlenを呼び出すのはNGです。 > 組み込み系のお仕事をされている方の意見も聞きたいです。 組込み系といっても、環境がさまざまですので一概には言えません。 OSなしの環境と、μITRONのような簡易なOSの環境と、LinuxやWindowsCEのような環境では、まったく事情が異なります。

その他の回答 (2)

  • zwi
  • ベストアンサー率56% (730/1282)
回答No.3

>newを使った場合、3バイト分確保したつもりでしたが、7バイト?になります。どうしてでしょうか? newしただけでは3バイトの内容は不定です。 文字列の終端は\0(0x00)ですから、\0が見つかるまでが文字列の長さということになります。たまたま、8バイト目に\0があったのでしょう。 newした文字列の領域は自分で\0を書き込むか、strcpyするときは\0を含めて3バイト以内になるように自分で面倒を見る必要があります。コンパイラは何もガードしてくれません。 >newした場合はdeleteをしないといけませんが、deleteした後にNULLで初期化する意味はあるのでしょうか? cstrをNULLにすることで領域の解法を明示的に表現します。LinuxなどでNULLにされた値を使ったらメモリ保護例外になりますし、他の環境でもcstrがNULLだったらエラーにする処理をあちこちに埋め込んでトラブルをガードする事ができます。 >CとC++が混在?(newはC++かな?)しているソースなのですが、 >現場(クリティカルな開発)ではこういう書き方はNGでしょうか? >組み込み系のお仕事をされている方の意見も聞きたいです。 CとC++の書き方を混ぜることは普通しません。読むほうもややこしくなりますから。開発の現場では、コーディング規約でどちらかに統一されているはずです。 最近質問を多くされてますが、締め切っていない質問が沢山あるみたいです。回答に不十分な部分があればお礼などで補足を求めてはどうでしょうか?満足したのなら締め切ってください。 ほとんど問い返されないので回答がうまく伝わっているのか疑問に思っています。こういう場は、お互いに情報交換しないと解決に持っていくことが難しい場合が多いですから、tobasuさんもうまく回答者コミュニケーションを取ってくださいね。 今回のnewの問題も今までの回答者の言いたいことが伝わってないんじゃないと感じました。

tobasu
質問者

お礼

わかりやすいご説明ありがとうございます。 回答を見た直後では、正直理解しておりませんが、2-3日すると少し理解できるので、しばらく申し訳ないのですが放置しています。 最終的にこの回答で解決したと断言できるのは、だいたい1週間後以降になり、それで締め切りが遅れております。 独学なので体系的に理解していなく、CとC++の過渡期の時期に、学ぶ機会を逃したので、テンプレートやstd::系の知識が0でC++を使いこなせていません。 今後もいろいろ質問させていただきますが、よろしくお願いいたします。

  • koko_u_
  • ベストアンサー率18% (459/2509)
回答No.1

>printf("%d\n", strlen(cstr)); // 3を期待していたのですが、7になります。 strlen() は最初に \0 が現れるまでをカウントするので、中身の入っていない配列については、「どこまで数えられるか」予測できません。 >deleteした後にNULLで初期化する意味はあるのでしょうか? 多分、どこか別の場所で delete cstr; としたときに、領域が二重に開放されることがないように、という意図ではないでしょうか。

関連するQ&A

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

    <本に載ってたソース> #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が、文字数でしたっけ?

  • 多次元配列の new 2

    追加の質問ですみません^^; char の8個の配列へのポインタの配列を new する場合などは、以下のサンプルのように typedef しないとかけないんでしょうかね?たとえば、  char (**bb)[8] = new (char (*)[8])[8]; 書きたいように思いますが、これは文法違反ですし・・・^^; ==== サンプル:(iostream の初期化時に、定義した new が呼び出されるかもしれないことを一応考慮して、stdio の関数を使っています^^) #include <new> #include <stdlib.h> #include <stdio.h> void *operator new(std::size_t s) { void *p = malloc(s); fprintf(stderr, "::new(): %p\t%lu\n", p, (unsigned long)s); return p; } void operator delete(void *p) { fprintf(stderr, "::delete(): %p\n", p); if (p) free(p); } void *operator new[](std::size_t s) { void *p = malloc(s); fprintf(stderr, "::new[](): %p\t%lu\n", p, (unsigned long)s); return p; } void operator delete[](void *p) { fprintf(stderr, "::delete[](): %p\n", p); if (p) free(p); } int main() { typedef char (*T)[8]; char (**b)[8] = new T[8]; delete[] b; } ==== % ./a.exe ::new[](): 0x6e01b0 32 ::delete[](): 0x6e01b0

  • 文字列クラスを作りたいと思っています

    文字列クラスを作りたいと思っています。 以下のようなところまでは作れましたが、 エラーがでてしまいます。 どこかおかしいところがあるのでしょうか? *********************************************** #include<stdio.h> #include<string.h> class stt { public: char *str; int len; bool maked; stt::stt() { len=0; str=NULL; maked=false; } stt::~stt() { delete[] str; } stt &operator =(char *c) { if(maked) { delete[] str; maked=false; } len=strlen(c); str=new char[len]; strcpy(str,c); maked=true; return (*this); } virtual operator char*() { return str; } }; int main() { stt s; s="Hello World"; printf(s); getchar(); return 0; } ***********************************************

  • new演算子のオーバーロードについて

    #include <stdio.h> #include <windows.h> class MyNew { public: void* ptr; MyNew( void* p ) { ptr = p; } void* MyNew::operator new( size_t size ) { printf("new-\n"); return malloc( size ); } void MyNew::operator delete( void* ptr ) { printf("delete-\n"); free( ptr ); } }; void main( void ) { MyNew p = new int; } クラスのメモリ確保をnew演算子のオーバーロードを用いて書いてみたのですがオーバーロードしたnew演算子が呼ばれません。 なぜでしょうか? /** VisualStdio2005コンソールアプリケーション WindowsXP */

  • operator +()について

    --------------------------------------- 文字列クラスを作りたいと思っています。 以下のようなところまでは作れましたが、 全てのstrをdelete[] str;しているのかわかりません。 delete[] str;を確認するにはどうすればいいですか? --------------------------------------- #include<stdio.h> #include<string.h> #include<conio.h> class stt { public: char *str; int len; bool maked; stt::stt() { len=0; str=NULL; maked=false; } stt::~stt()// ちゃんとデストラクタ内で、全てのstrがdeleteされているのでしょうか? { if(maked) { delete[] str; } else { maked=true; } } stt &operator =(char *c) { if(maked) { delete[] str; maked=false; } len=strlen(c); str=new char[len+1]; strcpy(str,c); maked=true; return (*this); } stt &operator =(stt &ste) { if(maked) { delete[] str; maked=false; } len=strlen(ste.str); str=new char[len+1]; strcpy(str,ste.str); maked=true; return (*this); } stt operator +(stt ste) { stt tet; int len1=strlen(str); int len2=strlen(ste.str); tet.str=new char[len1+len2+2]; strcpy(tet.str,str); strcat(tet.str,ste.str); tet.str[len1+len2+1]='\0'; ste.maked=false;//不安部分 return tet; } virtual operator char*() { return str; } }; int main() { stt ss,ww,pp; ss="a"; ww="b"; pp=ss+ww; printf(pp); printf("\n"); getchar(); return 0; }

  • abcdとキーボードで打ったらdcbaと表示されるプログラム

    C言語に関しては初心者です。 メイン関数は変更せずに行います。 /* reverse.c: reverse a given string */ #include <stdio.h> #include <string.h> void reverse(char *); /* プロトタイプ宣言 */ int main(void) { char str[100]; scanf("%s", str); reverse(str); printf("%s\n", str); return (0); } void reverse(char *s) { char n; int i; char str; n = strlen(str) - 1; for(i=0,i++,i<=100) { s[i] = *s[n-i]; printf("%s\"s[i]); } }

  • C言語 ファイルの意味

    C言語 文字列で分からない部分があるのでご教示お願いします。 内容は「文字列の検索」です。 #include<stdio.h> #include<string.h> int main(void) { char word[] = "abcabdabe"; char word2[] = "abd"; char *word3 = "ABD"; char *word4 = NULL; printf("処理前の文字列:%s\n", word); word4 = word; word4 = strchr(word4, *word2); while (word4 != NULL){ printf("'a'が見つかった場所からの文字列: %s<\n", word4); if (strncmp(word4, word2, strlen(word2)) == 0) { strncpy(word4, word3, strlen(word3)); } word4 += 1; word4 = strchr(word4, *word2); } printf("処理後のword4: %s\n", word); return 0; } このプログラムの場合、word3とword4ではなぜ、*word3, *word4とポインタで設定するのでしょうか? また、「word4 = strchr(word4, *word2)」と *word2のようにlここでポインタ指定するのは何故なのでしょうか?

  • C++のnew演算子について質問です。

    C++のnew演算子について質問です。 以下は関数にポインタを渡して値を得ようしたプログラムです。 ※ディレクティブは省略しています。 void test( int* a ) { a = new int( 100 ); } void main() { int* b; test(b); printf( "%d", *b ); delete b; b = NULL; } このプログラムを実行すると、コンソール画面には100と表示されるかと思っていたのですが、 実際には滅茶苦茶な値と、例外が発生して強制終了しました。 また、関数に渡したポインタのアドレスもNULLとなってしまいます。 そこで以下のようにソースを変更すると正常に100が表示されました。 void test( int** a ) { *a = new int( 100 ); } void main() { int* b; test(&b); printf( "%d", *b ); delete b; b = NULL; } 結果的には目的が達成できたのでいいのですが、なぜこのような動作をするのかが いまいち釈然としません。 new演算子は自動的には破棄されないのではないのでしょうか? 回答の程、よろしくお願いします。

  • new演算子とインクリメント

    #include <iostream.h> main(){ char *str = new char[10]; memset(str, 0, 10); char *p = str; *p = 1; printf("%x", *p); delete [] str; } これで0が出力されるけど、*p = 1; を *p += 1; にすると *p += 1; の部分の実行時にエラーでフリーズしました。 この場合、*p += 1; と書いてはだめなのですか? *p = 1; との違いがあれば教えてください。

  • 文字列クラスを作りたいと思っています。-2

    文字列クラスを作りたいと思っています。 以下のようなところまでは作れましたが、 エラーがでてしまいます。 どこかおかしいところがあるのでしょうか? ********************************************** #include<stdio.h> #include<string.h> #include<conio.h> class stt { public: char *str; int len; bool maked; stt::stt() { len=0; str=NULL; maked=false; } stt::~stt() { delete[] str; } stt &operator =(char *c) { if(maked) { delete[] str; maked=false; } len=strlen(c); str=new char[len+1]; strcpy(str,c); maked=true; return (*this); } stt &operator =(stt &ste) { if(maked) { delete[] str; maked=false; } len=strlen(ste.str); str=new char[len+1]; strcpy(str,ste.str); maked=true; return (*this); } stt operator +(stt ste) { static stt tet; int len1=strlen(str); int len2=strlen(ste.str); tet.str=new char[len1+len2+2]; strcpy(tet.str,str); strcat(tet.str,ste.str); tet.str[len1+len2+1]='\0'; return tet; } virtual operator char*() { return str; } }; int main() { stt ss,ww,pp; pp="Hello"; ss="Nice to meet you.\n"; ww="I am studing Visual C++"; pp=ss+ww; printf(pp); getchar(); return 0; } **********************************************

専門家に質問してみよう