#2
by みけCAT » 7年前
ソースコードを提示する際は、BBCodeが有効な(無効にしない)状態で、
BBCodeのcodeタグの開始タグと終了タグの組(開始タグが先)で囲んでいただけると、
見やすくてありがたいです。
gumi さんが書きました:★「printf("%s\n", word); 」がエラーになるのはなぜか?
%sを使う時は有効なNUL終端の文字列を指すポインタ(char*型のデータ)を与えないといけないのに対し、
wordはchar*型のデータを要素とする配列であり、先頭要素へのポインタ(char**型のデータ)に変換されるので、
型が間違っており、未定義動作になります。
使用しているコンパイラがわかりませんが、GCCでは警告が出る場合があり、警告をエラーとして扱うオプションを使えばエラーになるでしょう。
gumi さんが書きました: 以下は手持ちの書籍のサンプルコートですが、ポインタによる文字列であるptrはちゃんと
「printf("ptr = \"%s\"\n", ptr);」
でも出力できているため、疑問に思いました。
******************************
int main(void)
{
char *ptr = "123";
printf("ptr = \"%s\"\n", ptr);
}
******************************
ptrはchar*型であり有効な文字列を指しているので、問題ありません。
gumi さんが書きました:
★「result = word[0];」とすると、
「warning: format ‘%S’ expects argument of type ‘wchar_t *’, but argument 2 has type ‘int’ [-Wformat=]」が出てしまう。
この文には%Sが含まれていないので、この文を原因としてこのメッセージが出るのは不自然です。
こうしない場合はこれが出ないのですか?
gumi さんが書きました:
printf("%d\n", result)で試すと、分割した文字列要素の先頭文字のアドレスが入っていることは確認できるが、
resultには文字が入っており、通常この文だけではデバッガを使用しない限りアドレスが入っていることは確認できないはずです。
gumi さんが書きました:
printf("%S\n", result)として文字を直接出力できないのはなぜか?
書式%S (N1570では見つけられませんでした) が文字ではなくwchar_t *型のデータを要求する仕様だからでしょう。
printfで1文字出力するには、書式%cを使うといいでしょう。
gumi さんが書きました:
resultはchar型なので、そもそもintは入りようがないのではないか?
printfの不定長の引数の部分は型がわからないので、integer promotionが適用され、int型に変換されます。
gumi さんが書きました:★ 「puts(result);」ではなく、「printf(result)」にできないのはなぜか?
printfは書式の処理を行うので、入力に%を含む文字列が与えられた時、想定しない場所の読み書きが行われ、危険になります。
また、C言語では式文の最後にはセミコロンが必要です。
コード:
printf("%s\n", result);
なら大丈夫です。
ソースコードを提示する際は、BBCodeが有効な(無効にしない)状態で、
[url=http://dixq.net/board/board.html#k10]BBCodeのcodeタグの開始タグと終了タグの組(開始タグが先)で囲んでいただける[/url]と、
見やすくてありがたいです。
[quote="gumi" id=3,19881,149195]★「printf("%s\n", word); 」がエラーになるのはなぜか?[/quote]
%sを使う時は有効なNUL終端の文字列を指すポインタ(char*型のデータ)を与えないといけないのに対し、
wordはchar*型のデータを要素とする配列であり、先頭要素へのポインタ(char**型のデータ)に変換されるので、
型が間違っており、未定義動作になります。
使用しているコンパイラがわかりませんが、GCCでは警告が出る場合があり、警告をエラーとして扱うオプションを使えばエラーになるでしょう。
[quote="gumi" id=3,19881,149195] 以下は手持ちの書籍のサンプルコートですが、ポインタによる文字列であるptrはちゃんと
「printf("ptr = \"%s\"\n", ptr);」
でも出力できているため、疑問に思いました。
******************************
int main(void)
{
char *ptr = "123";
printf("ptr = \"%s\"\n", ptr);
}
******************************
[/quote]
ptrはchar*型であり有効な文字列を指しているので、問題ありません。
[quote="gumi" id=3,19881,149195]
★「result[i] = word[i][0];」とすると、
「warning: format ‘%S’ expects argument of type ‘wchar_t *’, but argument 2 has type ‘int’ [-Wformat=]」が出てしまう。
[/quote]
この文には%Sが含まれていないので、この文を原因としてこのメッセージが出るのは不自然です。
こうしない場合はこれが出ないのですか?
[quote="gumi" id=3,19881,149195]
printf("%d\n", result[i])で試すと、分割した文字列要素の先頭文字のアドレスが入っていることは確認できるが、
[/quote]
result[i]には文字が入っており、通常この文だけではデバッガを使用しない限りアドレスが入っていることは確認できないはずです。
[quote="gumi" id=3,19881,149195]
printf("%S\n", result[i])として文字を直接出力できないのはなぜか?
[/quote]
書式%S (N1570では見つけられませんでした) が文字ではなくwchar_t *型のデータを要求する仕様だからでしょう。
printfで1文字出力するには、書式%cを使うといいでしょう。
[quote="gumi" id=3,19881,149195]
result[i]はchar型なので、そもそもintは入りようがないのではないか?
[/quote]
printfの不定長の引数の部分は型がわからないので、integer promotionが適用され、int型に変換されます。
[quote="gumi" id=3,19881,149195]★ 「puts(result);」ではなく、「printf(result)」にできないのはなぜか?[/quote]
printfは書式の処理を行うので、入力に%を含む文字列が与えられた時、想定しない場所の読み書きが行われ、危険になります。
また、C言語では式文の最後にはセミコロンが必要です。
[code=c]printf("%s\n", result);[/code]なら大丈夫です。