char配列cをクリアする


104

最初の要素をnullに設定すると、char配列の内容全体がクリアされると思いました。

char my_custom_data[40] = "Hello!";
my_custom_data[0] = '\0';

ただし、これは最初の要素をnullに設定するだけです。

または

my_custom_data[0] = 0; 

memset上記の2つの例では、を使用するのではなく、すべてのデータを消去すると思いました。


1
Jared、なぜc ++タグを設定したのですか?彼は「C」について話し、C ++関連のタグを追加しませんでした。
Johannes Schaub-litb 2009年

1
これは、彼が指定しなかったとしても、C ++の文字配列にも同様に当てはまります。
Adam Hawes

4
C ++タグを削除して、C ++固有のソリューションを提供している人々にすでに見られていることを回避しました
Alnitak

回答:


113

配列の表示方法によって異なります。配列を一連の文字として表示している場合、データを消去する唯一の方法は、すべてのエントリに触れることです。memsetおそらくこれを実現する最も効果的な方法です。

一方、これをC / C ++のnullで終了する文字列として表示する場合は、最初のバイトを0に設定すると、文字列が実質的にクリアされます。


4
彼らの答えのキーワードは「効果的に」です。最初の要素のみが0に設定され始め、残りは未定義の値のままですが、配列をnullで終了する文字列として扱い、最初の要素がnullの場合、文字列は空と見なされます。
アーノルドスペンス

確かに、これは答えの人々です。
Johannes Schaub-litb 2009年

@caparcode、まさに。そのため、配列がどのように使用されているかを理解することが非常に重要です。
JaredPar 2009年

はい、それは私が私の最初の投稿で言うべきだったものです。charは終了文字列です。どちらかがそのトリックを行います。char [0] = '\ 0'; またはchar [0] =0。わかりませんが、nullで終了する文字列を使用する場合は '\ 0'を使用する方が良いと聞きました。
ant2009 2009年

@robUK、はい、あなたは正しいです。技術的には '\ 0'は0(asciiで)に等しいですが、意図を明確にするため '\ 0'を使用する必要があります
Mark Testa

70

Cの配列は単なるメモリの場所なので、実際のmy_custom_data[0] = '\0';割り当てでは、最初の要素をゼロに設定し、他の要素はそのまま残します。

配列のすべての要素をクリアしたい場合は、各要素にアクセスする必要があります。それがmemset目的です:

memset(&arr[0], 0, sizeof(arr));

これは通常、これを処理する最も速い方法です。C ++を使用できる場合は、代わりにstd :: fillを検討してください。

char *begin = &arr;
char *end = begin + sizeof(arr);
std::fill(begin, end, 0);

1
2番目のバージョンは次のようになるはずです。std :: fill(arr、arr + sizeof(arr)/ sizeof(arr [0])、0);
デビッドロドリゲス-ドリベス2009年

明確化:後でint、long、doubleなどの配列で問題が発生するため、fillでsizeofを使用しないでください。
Zan Lynx

私が好むのは:std :: fill(&arr [0]、&arr [arr_len]、0);
Zan Lynx

Zan Lynx、それは未定義の動作です。&arr [arr_len]は実行できません。std :: fill(arr、arr + sizeof arr、0);を実行する必要があります。または、長さがstd :: fill(arr、arr + arr_len、0);のどこかにある場合。charの配列を想定
Johannes Schaub-litb 2009年

Cでのみ有効です。質問は明らかにCをターゲットにしていますが(別の人がC ++タグを追加しましたが、その理由はわかりません)、std :: fillはC ++の親和性を示します:)
Johannes Schaub-litb 2009年

25

単一の要素を設定すると、配列全体がクリアされると思いますか?特にCでは、プログラマーが明示的にプログラミングしなければほとんど起こりません。最初の要素をゼロ(または任意の値)に設定した場合は、正確にそれを行っただけで、それ以上は行いません。

初期化時に配列をゼロに設定できます:

char mcd[40] = {0}; /* sets the whole array */

それ以外の場合は、memsetまたは同様の何か以外のテクニックを知りません。


これは、使用するコンパイラに依存すると思います
cocoafan

1
@cocoafan:いいえ、コンパイラに依存しません。言語仕様の一部です。動作が異なるコンパイラは、C言語に従っていません。
abelenky

知らなかった、ありがとう。この特殊なケースを読むことができるリソースが見つかりませんでした。ブックマークとしてそれを持っているといいでしょう。
cocoafan 2011年

1
これは部分初期化と呼ばれます。C99仕様はありませんが、次の2つのソースがあります。bit.ly / enBC2m "配列のすべての要素を初期化する必要はありません。配列が部分的に初期化されている場合、初期化されていない要素は適切なタイプ。」 bit.ly/f9asHH "配列の要素より初期化子の数が少ない場合、残りの要素は自動的に0に初期化されます
abelenky

これは、すでに宣言され、値が割り当てられている配列には適用されませんか?
skinnedKnuckles 2018年

10

使用する:

memset(my_custom_data, 0, sizeof(my_custom_data));

または:

memset(my_custom_data, 0, strlen(my_custom_data));

1
2番目のオプション(memset(my_custom_data, 0, strlen(my_custom_data));)は、最初の '\ 0'のみをクリアします。これは、配列の終わりを超えている可能性があります。これは大丈夫かもしれませんし、そうでないかもしれません。
brewmanz

9

次のコードを試してください:

void clean(char *var) {
    int i = 0;
    while(var[i] != '\0') {
        var[i] = '\0';
        i++;
    }
}

2
FYI-コードを4つのスペースでインデントするか、コードを選択して、2行のバイナリのように見える「コード」ボタンを押します。
貧乳

memset()にstring.hを含めたくない場合の優れたソリューション。
Akash Agarwal


6

Plsは、ケース1とケース2の後で配列内のデータを使用して説明した場所を以下に示します。

char sc_ArrData[ 100 ];
strcpy(sc_ArrData,"Hai" );

ケース1:

sc_ArrData[0] = '\0';

結果:

-   "sc_ArrData"
[0] 0 ''
[1] 97 'a'
[2] 105 'i'
[3] 0 ''

ケース2:

memset(&sc_ArrData[0], 0, sizeof(sc_ArrData));

結果:

-   "sc_ArrData"
[0] 0 ''
[1] 0 ''
[2] 0 ''
[3] 0 ''

最初の引数をNULLに設定するとうまくいきますが、memsetを使用することをお勧めします


4

いいえ。最初の値を '\ 0'または0に設定するだけです。

nullで終了する文字列を使用している場合、最初の例では、期待どおりの動作をしますが、メモリは設定されています。

memsetを使用せずにメモリをクリアする場合は、forループを使用します。


私はforループでノーと言います。独自の「改善された」(そして通常はそうではない)ライブラリ関数を書かないようにしてください。実際、memsetとmemcpyはかなり特殊で、データの配置と長さに関する既知の情報に基づいて、CPUのカスタムマシンコードにインライン化されることがよくあります。
ザンリンクス

OPの@Zanはmemsetを使用したくありません(おそらく埋め込まれていて利用可能ではありません)。しかし、はい、通常、memsetは非常に最適であり、forループよりも高速です。
アダムHawes

確かに、しかし彼はmemsetを使いたくないので、forループを提案しました。
アラン

3

memsetを使用する必要があります。最初の要素だけを設定しても機能しません。すべての要素を設定する必要があります。そうでない場合、最初の要素のみを0に設定するにはどうすればよいでしょうか。


memsetのは、読みやすさの上に使用してはならない。stackoverflow.com/questions/453432/...
ヨハンGerell

2

最初の文字にnull文字を書き込むと、まさにそれが可能になります。文字列として扱う場合、null終了文字に従うコードはそれをnull文字列として扱いますが、これはデータをクリアすることとは異なります。実際にデータを消去したい場合は、memsetを使用する必要があります。



1

最初の要素をnullに設定すると、char配列の内容全体がクリアされると思いました。

あなたが発見したようにそれは正しくありません

ただし、これは最初の要素をnullに設定するだけです。

丁度!

すべてのデータをクリアするにはmemsetを使用する必要があります。エントリの1つをnullに設定するだけでは不十分です。

ただし、配列の要素をnullに設定することが特別な意味を持つ場合(たとえば、null終了文字列を使用する場合)、最初の要素をnullに設定するだけで十分な場合があります。このようにして、配列にメモリ内の古い文字がまだ含まれている場合でも、配列のユーザーはそれが空であることを理解できます


読みやすさの上に「memsetを」を使用しないでください。stackoverflow.com/questions/453432/...
ヨハンGerell

1

最初の要素をNULLに設定します。char配列を出力しても何も返されません。



-3
void clearArray (char *input[]){
    *input = ' '; 
}

1
これはクリアではなく、最初の文字を ''に設定しているだけです!* input = '\ 0'
stviper

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.