文字列について

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
みるく

文字列について

#1

投稿記事 by みるく » 13年前

こんばんは。質問です!

#include <stdio.h>
int main()
{
int i;
char str[]="Hello!¥n";
for(i=0;i<9;i++){
printf(&str);
}
}
このプログラムについてなのですが
i=6、7、8のときは表示がされません。
I=6のときは「¥n¥0」、i=7のときは「¥0」
が実際にはあると考えられるのですが、I=8のときは
実際は何が出力されているのでしょうか。
わかる方、お願いいたします。

nil
記事: 428
登録日時: 14年前

Re: 文字列について

#2

投稿記事 by nil » 13年前

コードタグを使ってください。

まず6の時、何も表示されはしないでしょうが、改行はされているのではないでしょうか?
7の時は終端文字'\0'が1文字目に出てくるため文字は表示されません。
8の時はstrのバッファをオーバーしているため処理は未定です。

box
記事: 2002
登録日時: 15年前

Re: 文字列について

#3

投稿記事 by box » 13年前

みるく さんが書きました:

コード:

                        printf(&str[i]);
printf()を使うときは、書式文字列("%d"とか"%s"とか"%f"とか"%p"とか)を
必ず使いましょう。
Cの文法書に、そういう風に書いてあるはずです。それに従うべきです。
バグのないプログラムはない。
プログラムは思ったとおりには動かない。書いたとおりに動く。

アバター
みけCAT
記事: 6734
登録日時: 15年前
住所: 千葉県
連絡を取る:

Re: 文字列について

#4

投稿記事 by みけCAT » 13年前

box さんが書きました:
みるく さんが書きました:

コード:

                        printf(&str[i]);
printf()を使うときは、書式文字列("%d"とか"%s"とか"%f"とか"%p"とか)を
必ず使いましょう。
Cの文法書に、そういう風に書いてあるはずです。それに従うべきです。
それは迷信だと思いますが、違いますか?
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

ISLe
記事: 2650
登録日時: 15年前
連絡を取る:

Re: 文字列について

#5

投稿記事 by ISLe » 13年前

printfの第一引数を変数にすると不正アクセスのきっかけを作りやすく、脆弱性を高めることになると思いますけどね。

コード:

const char *sz = "%s";
printf(sz);
printf("%s", sz);
そもそも書式指定を使わないならprintfにとって役不足ですし。
コンパイラが最適化で置き換えてくれそうですが。

box
記事: 2002
登録日時: 15年前

Re: 文字列について

#6

投稿記事 by box » 13年前

みけCAT さんが書きました: それは迷信だと思いますが、違いますか?
違いますよ。
本来第1引数に書くべき書式文字列を省略して、
第2引数以降に書くべき(文字列の)中に書式文字列に相当する内容があった場合、
何が起こるかわかったものではありません。よく理解しましょう。

そもそも、printf()のプロトタイプに反する記述をすることが正しいとは、どうしても思えません。
プロトタイプに反する記述をすることは正しいですか?
バグのないプログラムはない。
プログラムは思ったとおりには動かない。書いたとおりに動く。

アバター
shiro4ao
記事: 224
登録日時: 15年前
住所: 広島

Re: 文字列について

#7

投稿記事 by shiro4ao » 13年前

フォーマット文字列攻撃  http://ow.ly/eMKt8
こちらがわかりやすいかなと思います。

コード:

 printf(&str[i]);
とした場合、引数に%xを指定するとスタック上の4バイトが出力されます。
%xをたくさん渡すことでスタックのデータを順番に見ることができるようになります。

無害そうですが、今度は引数に%nを渡すとアドレスに書き込みが行えます・・・・・・・ orz
任意のアドレスの書き換えができるので、プログラム作成者の意図しない挙動をさせることが可能になります。
つまり、不幸にして管理者権限をもったプロセスがフォーマット文字列攻撃を受ければ
管理者権限のシェルを奪取されることになります。

beatle
記事: 1281
登録日時: 14年前
住所: 埼玉
連絡を取る:

Re: 文字列について

#8

投稿記事 by beatle » 13年前

boxさんの、printfの第一引数には文字列リテラルを書くべき、という指摘は僕も同意するところです。
単純に文字配列を表示したいだけならputsやfputsでいいでしょう。

その上で、純粋な疑問なのですが、以下の発言の「プロトタイプに反する記述」が何を指しているのか良くわかりません。
printf(&str);
は特にプロトタイプ宣言に違反しているわけではないですよね?
(printfのプロトタイプはint printf(const char*, ...)です。printf(&str);はこれに合致していると思います)
だとすると他に何がプロトタイプに反しているか見つけられませんでした。
box さんが書きました: そもそも、printf()のプロトタイプに反する記述をすることが正しいとは、どうしても思えません。
プロトタイプに反する記述をすることは正しいですか?

box
記事: 2002
登録日時: 15年前

Re: 文字列について

#9

投稿記事 by box » 13年前

【編集後】
別に荒れてないですよ。ご心配なく。
そういえば、

コード:

    printf("123\n");
とか書いてたんですよね~。でも、

コード:

    char *p = "%s";
    printf(p);
とか書くのは、さすがにまずいんだろ~な~。なんてね。
ちゃんちゃん♪
最後に編集したユーザー box on 2012年10月26日(金) 21:15 [ 編集 2 回目 ]
バグのないプログラムはない。
プログラムは思ったとおりには動かない。書いたとおりに動く。

だんごさん
記事: 273
登録日時: 13年前

Re: 文字列について

#10

投稿記事 by だんごさん » 13年前

荒れているように見えますが、質問者さんの質問に答えてあげてください。
printfの引数がどうのこうのは別にトピックを立ててください。
printfで議論する場所では無いので。あくまで意見として受け止めては?

…と言っても質問者さんの返信が一件もないのであまり話が進めませんがね…。
 Dango San

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: 文字列について

#11

投稿記事 by softya(ソフト屋) » 13年前

問題点を指摘するのは必要な事だと思いますが波風の立たないやり方や他者からきつく見えない書き方を考えて頂くと助かります。
それと重箱の隅をつつくような話は別トピックを立てることやプライベートメッセージでお願いします。
以上、よろしくおねがいします。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

ISLe
記事: 2650
登録日時: 15年前
連絡を取る:

Re: 文字列について

#12

投稿記事 by ISLe » 13年前

個人的にはせっかく滅多にないセキュアなプログラミングの知識を得る機会を重箱の隅と非難されるのは悲しい気がしますね。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: 文字列について

#13

投稿記事 by softya(ソフト屋) » 13年前

ISLe さんが書きました:個人的にはせっかく滅多にないセキュアなプログラミングの知識を得る機会を重箱の隅と非難されるのは悲しい気がしますね。
セキュアな話は大事だと思いますが、どう見ても違う方向に流れている部分が見受けられるのでコメントさせていただきました。
ちゃんと流れを読んで穏やかに話し合って頂く分には問題ありませんので、よろしくお願いします。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

box
記事: 2002
登録日時: 15年前

Re: 文字列について

#14

投稿記事 by box » 13年前

いずれにしても、

コード:

#include <stdio.h>

int main(void)
{
    char *p = "Hello%s";

    printf(&p[0]);
    return 0;
}
こんなコードを書いた日には何が起きても知らんぜよ、という点においては、
みなさん納得していただけるのではないかと思います。
バグのないプログラムはない。
プログラムは思ったとおりには動かない。書いたとおりに動く。

アバター
みけCAT
記事: 6734
登録日時: 15年前
住所: 千葉県
連絡を取る:

Re: 文字列について

#15

投稿記事 by みけCAT » 13年前

box さんが書きました:いずれにしても、

コード:

#include <stdio.h>

int main(void)
{
    char *p = "Hello%s";

    printf(&p[0]);
    return 0;
}
こんなコードを書いた日には何が起きても知らんぜよ、という点においては、
みなさん納得していただけるのではないかと思います。
これは間違いないですが、
box さんが書きました:printf()を使うときは、書式文字列("%d"とか"%s"とか"%f"とか"%p"とか)を
必ず使いましょう。
Cの文法書に、そういう風に書いてあるはずです。それに従うべきです。
これはおかしいと思います。
box さんが書きました:そもそも、printf()のプロトタイプに反する記述をすることが正しいとは、どうしても思えません。
プロトタイプに反する記述をすることは正しいですか?
コンパイルしてもエラーは出ませんが、本当にプロトタイプに反していますか?
http://ideone.com/KWyK1i
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

box
記事: 2002
登録日時: 15年前

Re: 文字列について

#16

投稿記事 by box » 13年前

みけCAT さんが書きました: これはおかしいと思います。
はい。おかしいです。あなたの方が当方よりも優秀なことはよくわかりましたから、もう勘弁してください。
バグのないプログラムはない。
プログラムは思ったとおりには動かない。書いたとおりに動く。

アバター
Dixq (管理人)
管理人
記事: 1662
登録日時: 15年前
住所: 北海道札幌市
連絡を取る:

Re: 文字列について

#17

投稿記事 by Dixq (管理人) » 13年前

えーと、このままではみるくさんが、質問しにくいと思いますので話を戻しますね。

質問の件に関して、
char str[]="Hello!¥n";
で必要になる配列要素数は終端記号を含めた8個であるため、strのサイズは8で用意されています。
従って要素9個目にアクセスしようとすると、バッファオーバー(やってはいけない処理)になります。

これを踏まえてもし不明点があれば、また聞いて下さい。

AKIЯA

Re: 文字列について

#18

投稿記事 by AKIЯA » 13年前

printf(&str)は初めて見ました。
動くけども、親切ではないかと思いますね。

親切に作ると多分こうなるかと思います。
sizeof()を使ってオーバーフローしないようにしてます。

コード:

#include <stdio.h>
int main()
{ 
    int i;
    int len;

    char str[]="Hello!\n";
    len = sizeof(str);
    for(i=0;i<len;i++){
       printf("%s"&str[i]);
    }
}

アバター
みけCAT
記事: 6734
登録日時: 15年前
住所: 千葉県
連絡を取る:

Re: 文字列について

#19

投稿記事 by みけCAT » 13年前

改行したくなければ、fputsを使う方法があります。

コード:

#include <stdio.h>

int main(void) { 
    int i;
    int len;

    char str[]="Hello!\n";
    len = sizeof(str);
    for(i=0;i<len;i++){
       fputs(&str[i],stdout);
    }
    return 0;
}
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

閉鎖

“C言語何でも質問掲示板” へ戻る