これからの季節に親子でハイキング! >>

いつもお世話になっております。
static変数の配列の初期値を空文字列(各要素が'\0')にしたいです。
static変数なので放って置いても各要素に'\0'が入りますが、
初期値として空文字列にしている事を明記したいです。
そこで以下の様な方法を考えてみました。
(1)初期値に何もせず、コメントを書いておく
(2)初回起動フラグを持ち、フラグが立っていれば空文字列にする
(3)初期値にnull文字をSTR_LENの数だけ書く
(4)初期値の先頭のみnull文字にし、残りは省略する

どの様な方法が一般的でしょうか?
上記以外にもあれば、教えていただければ幸いです。
また、以下は私が考えたそれぞれの方法のソースです。

--------------------------------------------------------------------------------
#include <stdio.h>
#include <string.h>
#define STR_LEN 16
#define FLAG_ON (1)
#define FLAG_OFF (0)
--------------------------------------------------------------------------------
/* 初期値に何もせず、コメントを書いておく */
--------------------------------------------------------------------------------
void clear_1(void)
{
static char hoge[STR_LEN];/* 空文字列 */
}
--------------------------------------------------------------------------------
/* 初回起動フラグを持ち、フラグが立っていれば空文字列にする */
--------------------------------------------------------------------------------
void clear_2(void)
{
static char hoge[STR_LEN];
static int first = FLAG_ON;

if(first == FLAG_ON){
strncpy(hoge, "\0", STR_LEN);
first = FLAG_OFF;
}
}
--------------------------------------------------------------------------------
/* 初期値にnull文字をSTR_LENの数だけ書く */
--------------------------------------------------------------------------------
void clear_3(void)
{
static char hoge[] = {'\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
'\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0'};
}

--------------------------------------------------------------------------------
/* 初期値の先頭のみnull文字にし、残りは省略する */
--------------------------------------------------------------------------------
void clear_4(void)
{
static char str[STR_LEN] = {'\0', };
}
--------------------------------------------------------------------------------

このQ&Aに関連する最新のQ&A

A 回答 (4件)

★面白い質問です。


>(1)初期値に何もせず、コメントを書いておく
>(2)初回起動フラグを持ち、フラグが立っていれば空文字列にする
>(3)初期値にnull文字をSTR_LENの数だけ書く
>(4)初期値の先頭のみnull文字にし、残りは省略する
>どの様な方法が一般的でしょうか?
 staticな変数はプログラムが起動したときに全要素をゼロの値で埋め尽くします。
 よって(2)~(4)の方法はする必要性がありません。普通は(1)でしょう。
 分かりやすく記述したいのであれば
 『static char str[STR_LEN] = { 0 };』
 で十分だと思います。
 staticな変数の意味をもう一度確認して下さい。
・以上。
    • good
    • 0
この回答へのお礼

ご回答ありがとうございます。
static char hoge[STR_LEN] = {0};
の方法にしようと思います。

お礼日時:2008/02/24 16:00

やはり、



static char hoge[STR_LEN] = {0};

でしょうね。
空文字列という意味では "" ですが、全要素を0にする必要があるとのことですので。
ちなみにC++では、文字列リテラルを初期化子とした場合には、残りの要素が 0 で埋まることが保証されません。
    • good
    • 0
この回答へのお礼

ご回答ありがとうございます。
static char hoge[STR_LEN] = {0};
の方法にしようと思います。

お礼日時:2008/02/24 15:57

>/* 初期値に何もせず、コメントを書いておく */


コメントには「/* 空文字列 */」ではなく、何の為に
使用する変数であるかを記述するようにして下さい。

コメントを見なくてもstatic変数が初期起動時にクリア
される事はすぐに判るようになりますが、変数が何の為
のものであるかは、プログラム作ってから時間がたって
いたり他人がプログラムを修正する時に解析するのが
困難になりバグを発生しやすくする原因となります。
#1年後・数年後の自分は他人であるつもりで、他人が
#見て判り易いプログラムを書くようにすることが大事
#です。
    • good
    • 0
この回答へのお礼

ご回答ありがとうございます。
今後は初期値の目的を書く様にします。

お礼日時:2008/02/24 16:00

空文字列なんだから普通は


 char str[STR_LEN] = "";
にするんじゃないかな。

あと、空文字列って普通は先頭が'\0'の文字配列のことを言うと思うけど。(全要素じゃなくて)
    • good
    • 0
この回答へのお礼

ご回答ありがとうございます。
空文字列は全要素を0クリアするものと思っておりました。

static char hoge[STR_LEN] = {0};
の方法にしようと思います。

お礼日時:2008/02/24 16:02

このQ&Aに関連する人気のQ&A

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

このQ&Aを見た人が検索しているワード

このQ&Aと関連する良く見られている質問

Q構造体の静的な初期化

構造体の静的な初期化で、初期化が書かれていないメンバーは、
どうなるのでしょうか。。?
たとえば・・・

// 構造体の宣言
strcut MY_STRUCT {
   int data1 ;
   int data2 ;
   int data3 ;
   int data4 ;
} ;

// 変数宣言&初期化
static strcut MY_STRUCT st = {
   .data1 = 100,
   .data3 = 300
} ;

ネットで調べると、
初期化で指示されていないメンバーは0に初期化される、
という記述も一つだけ見つけたのですが・・・これはC言語(C99)の仕様でしょうか?
それともコンパイラ依存の仕様でしょうか?

Aベストアンサー

#2, #3 の方、この初期化の方法は C99で導入されたもので
gcc固有の拡張ではありません。
単にVC++などがC99の規格を満たしていないだけです。

質問者さんへ。
どうせネットで探すのなら原規格をあたるべきでしょう。
こういうところで訊いても所詮二次情報なので、
(わたしも含め)回答者が勘違いしていたり
無知のために
間違った回答をすることが少なくありません。

C99 は JIS規格 X 3010 になっていますので、
ネット上でpdfのものを参照することができます(ただし、保存も
印刷もできません。規格書を買えば別ですが)。

とりあえず今回の質問に関連するところを抜き出して引用します。

X 3010 6.7.8 初期化
要素指示子が
.識別子
という形式の場合、現オブジェクトは構造体型または共用体型をもち、
識別子はその型のメンバ名でなければならない。

意味規則
自動記憶域期間をもつオブジェクトを明示的に初期化しない場合、
その値は不定とする。
静的記憶域期間をもつオブジェクトを明示的に初期化しない場合、
次の規定に従う。
a) そのオブジェクトの型がポインタ型の場合、空ポインタに初期化する。
b) そのオブジェクトの型が算術型の場合、(正または符号なしの)0に初期化する。
c) そのオブジェクトが集成体の場合、各メンバにa)~d)の規定を(再帰的に)
適用し初期化する。
d) そのオブジェクトが共用体の場合、最初の名前つきメンバにa)~d)の規定を
(再帰的に)適用し初期化する。

原文を読みたいのであれば、
日本工業標準調査会のページ
http://www.jisc.go.jp/
にアクセスし、ウィンドウの右の方にある
「JIS 検索」のリンクをクリックして
該当の規格を検索してください。
今回は規格番号がわかっているので、
一番上の 「JIS規格番号からJISを検索」で
テキストボックスに X3010を入力して検索すれば
一発ででます。
pdfファイルへのリンクは毎回変わるので直接示すことができません。
面倒ですが検索からやってください。

参考URL:http://www.jisc.go.jp/

#2, #3 の方、この初期化の方法は C99で導入されたもので
gcc固有の拡張ではありません。
単にVC++などがC99の規格を満たしていないだけです。

質問者さんへ。
どうせネットで探すのなら原規格をあたるべきでしょう。
こういうところで訊いても所詮二次情報なので、
(わたしも含め)回答者が勘違いしていたり
無知のために
間違った回答をすることが少なくありません。

C99 は JIS規格 X 3010 になっていますので、
ネット上でpdfのものを参照することができます(ただし、保存も
印刷もできません。...続きを読む

Qstatic付き宣言の初期化

static付きの宣言をした場合の変数の初期化について教えてください。(ANSI-C)

int func(void)
{
static int si;
static char sca[10];
static char *scp;
/* 何らかの処理 */
return 0;
}

このように関数内でstatic付きで宣言したとき、変数はどのように初期化されますか?
siは0、sca[0]からsca[9]までは'\0'、scpはNULLで初期化されますか?

また、このようなstatic付きの宣言が関数の外にあった場合は、どのように初期化されますか?

Aベストアンサー

自信を持って取り消し。

質問に対しての
~~~~
>siは0、sca[0]からsca[9]までは'\0'、scpはNULLで
>初期化されますか?
A.はいそうです。
>static付きの宣言が関数の外にあった場合は、どのよう
>に初期化されますか?
A.同じです。
~~~~
についての結論は変わりませんが、
根拠説明時の宣言領域内の全クリアについては、確かに
確実な回答ではないようです。

calloc は単にメモリのバイト単位クリアなので、値に対する
保障が無関係なのはその通りですが、静的領域のクリア
にはコンパイラにより確実な処理が含まれているのかも
知れません。

事実上は
ポインタ→NULL=0
数値変数→0
なのでどっちでも同じことですが、
・値・・・0かつビット配列・・・0以外 の型定義が存在するとき
・NULLポインタのビット配列が0でない場合
現実的かどうかは別として、上記の条件のものがある場合の
動作保障については、よくわかりません。

参考までに構造体と列挙型の静的宣言確認を載せておきます
ただしこれも、ビットクリアされているのか、メンバ単位に
数値変数=0・ポインタ=NULLとしてのコンパイラ処理されて
いるのかの区別はつきません。

おかげでひとつ利口になった。

----------------------------------------------
#pragma pack(1)// 境界整列用(処理系依存デフォルト4)

struct TESTSTRUCT {
double numd;
int num;
char chara[13];
void* ptr;
};
enum TESTENUM {
aaa = 2,
bbb =356,
ccc = 568
};

static struct TESTSTRUCT ts;
static enum TESTENUM te;
int main()
{
char* pdump;
int i;
int tssize, tesize;
tssize = sizeof(struct TESTSTRUCT);
tesize = sizeof(enum TESTENUM);
// ダンプ
printf("TESTSTRUCT size = %d\n", tssize);
pdump = (char*)&ts;
for(i = 0; i < tssize; i++) {
printf("%02X ", pdump[i]);
if((i % 8) == 7)printf(" ");
if((i % 16) == 15)printf("\n");
}
printf("\n");
printf("TESTENUM size = %d\n", tesize);
pdump = (char*)&te;
for(i = 0; i < tesize; i++) {
printf("%02X ", pdump[i]);
if((i % 8) == 7)printf(" ");
if((i % 16) == 15)printf("\n");
}
printf("\n");
// メンバ
printf("TESTSTRUCT (double)ts.numd = %f\n", ts.numd);
printf("TESTSTRUCT (int)ts.num = %d\n", ts.num);
printf("TESTSTRUCT (char[])ts.chara[] = ");
for(i = 0; i < sizeof(ts.chara); i++)
printf("%02X ", ts.chara[i]);
printf("\n");
printf("TESTSTRUCT (void*)ts.ptr = 0x%08X\n", ts.ptr);

printf("TESTENUM te = %d\n", te);

return 0;
}
----------------------------------------------

自信を持って取り消し。

質問に対しての
~~~~
>siは0、sca[0]からsca[9]までは'\0'、scpはNULLで
>初期化されますか?
A.はいそうです。
>static付きの宣言が関数の外にあった場合は、どのよう
>に初期化されますか?
A.同じです。
~~~~
についての結論は変わりませんが、
根拠説明時の宣言領域内の全クリアについては、確かに
確実な回答ではないようです。

calloc は単にメモリのバイト単位クリアなので、値に対する
保障が無関係なのはその通りですが、静的領域のクリア
...続きを読む

QC++言語で、構造体のコピーは可能(しても良い)のでしょうか?

C++言語で、構造体のコピーは可能(しても良い)のでしょうか?
問題がある場合は、なぜだめなのか知りたいです。
構造体は可変長ではありません。

typedef struct kumi {
char namae[10];
int ten;
}Kumi;

Kumi a, b;

strcpy(a.namae, "AAA");
a.ten = 50;

b = a;

Aベストアンサー

「C++」では何の問題もありません.
「C」だと, ふる~い時代の遺跡級のコンパイラが文句を言うかもしれません. ま, その手の遺跡級のコンパイラだと
・void がない (void * は char * で代用する)
・プロトタイプが存在しない
・const や volatile がない
・ひょっとすると単項の + もない
など, 今の視点からするといいたいことは山ほどあります (さすがに a -= b; ではなく a =- b; とするコンパイラを使うことはないだろう).
そのような時代には構造体のコピーを memcpy でやっていましたが, C++ では逆に危険です.

Qgcc: incompatible pointer type

以下のCソースでコンパイルすると、warning: passing arg 1 of `func_b' from incompatible pointer type
となります。
void (*p_func)() は、引数を省略しているので int として扱われるということでしょうか?

#include <stdio.h>
#include <stdlib.h>
void func_a( unsigned char x ){
printf( "x=%d\n", x ) ;
}
void func_b( void (*p_func)() ){
p_func( 1 ) ;
}
int main(){
func_b( func_a ) ;
return 0 ;
}

Aベストアンサー

まずは訂正から。

「関数や関数へのポインタを宣言するときに仮引数リストを空にすると、仮引数はないものとして扱われます。」と書きましたが、今の C の規格では
「関数を定義するときに仮引数リストを空にすると、仮引数はないものとして扱われます。これに対し、関数の(定義ではない)宣言や関数へのポインタの宣言(定義を含む)の場合には、引数の個数や型について一切情報が与えられないことを意味します。」くらいに解釈されます。将来的には変更されるはずですが。

今の場合 void (*p_func)() となっているので「p_func は void を返す関数で、その引数の個数や型は不明」ということになります。

ではなぜ unsigned char や unsigned short のときには warning が出るのに int や char * や long では出るのかという点に移るのですが、これはおそらく過去との互換性だと思います。ANSI/ISO C 以前、つまりいわゆる K&R の時代にはプロトタイプ宣言が存在しませんでした。この時代、char 及び short の引数は int に、また float の引数は double に自動的に変更されていました。つまり、関数の仮引数として char、short、float は許されていませんでした。

今考えている例では p_func に引数の情報が与えられていないため、その引数として char、short 及び float は許されず、その結果これらの型を持つ仮引数があるような関数を渡そうとすると warning が出るのだと思います。

まずは訂正から。

「関数や関数へのポインタを宣言するときに仮引数リストを空にすると、仮引数はないものとして扱われます。」と書きましたが、今の C の規格では
「関数を定義するときに仮引数リストを空にすると、仮引数はないものとして扱われます。これに対し、関数の(定義ではない)宣言や関数へのポインタの宣言(定義を含む)の場合には、引数の個数や型について一切情報が与えられないことを意味します。」くらいに解釈されます。将来的には変更されるはずですが。

今の場合 void (*p_func)() となっ...続きを読む

QC言語 配列の長さの上限

C言語で配列Array[N]の長さNの上限っていくらなんでしょうか?
もし可能なのであれば上限を2147483647にしたいのですが、方法を教えてください。

Aベストアンサー

そもそもWindowsの32bit版はアプリが仮想メモリ空間を2GBしか使えません。2GBを超えるには64bit版が必要です。
たとえ64bit版OSだとしても添え字が2147483647って、単純なintの配列だとしても4x2147483647=8GB必要ですね。実メモリ16GBとかのPCを用意しますか?
そもそも配列で2147483647個必要なアルゴリズムに問題ありだと思います。


人気Q&Aランキング