🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Q&A

解決済

2回答

1642閲覧

printf("Hello World! %d"); の出力について

020n

総合スコア36

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

0グッド

1クリップ

投稿2019/09/14 08:47

質問

以下プログラムはprintf関数の引数が足りないためにエラーになるかと思いきや、実行できました。
数値の部分は何の数値でしょうか。
調べ方が思いつかなく、ご回答頂けると嬉しいです。

プログラム

C

1#include <stdio.h> 2int main(void){ 3 printf("Hello World! %d"); 4}

###実行結果

Hello World! -504048920

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

cateye

2019/09/21 10:53

コンパイル時に、ワーニング出ませんでしたか? clang version 10の環境では以下のワーニングが出ます。 usr ~/Project/NewProject % cc tst.c tst.c:3:27: warning: more '%' conversions than data arguments [-Wformat] printf("Hello World! %d"); ~^ 1 warning generated.
guest

回答2

0

ベストアンサー

関数を呼び出される側と呼び出す側で引数を実際にやりとりする方法は一貫した規則があります。 コンパイル後に出来上がる機械語が実際にどうのようになるのかというのは言語仕様では規定されていませんが呼び出す側と呼び出される側が同じルールをあてにするのは説明するまでもなく自明ですね。

引数に矛盾があれば一般的にコンパイル時に検出されるのは「関数の型」がわかっているからです。 関数の型というのは引数の型も含みます。

ところが、 printf に関しては引数の数が可変です。 様々な型の値が渡ってくる可能性があります。 なので、 C の型システムでは上手く表現できません。 型で制限されていないので、間違いをコンパイラが見つけることが出来ません。

結果的に起こるのは、 printf は表示すべき値が渡されていると思ってそれが格納さるはずの場所から値を取りだして表示しているわけです。 値を渡す側はルールを守っていないのですから、そこには意味のある値はなく、そのときたまたま入っていたデタラメな値を表示してしまいます。

念のために強調しておきますが、これは「コンパイラが発見できない間違い」です。 間違っていることにかわりありません。 渡す値の数・型が矛盾しないことはプログラマが保証しなければならず、ルールに沿わないことをした場合の挙動は未定義です。 未定義というのはどのような動作になっても良いことを意味し、何が起こるかは言語仕様での規定がありません。 クラッシュしてもデータがふっとんでも言語仕様通りです。 (OS が上手く保護しているのでそんな極端なことはそうそう起こりませんが。)

たまたま何かの値が表示されても言語仕様上のルールで決まっている値ではないので、何の数値であるかを考えるのは無意味です。

ちなみに書式指定にあるよりも引数の数の方が多い場合には単に無視されることが言語仕様で規定されています。

投稿2019/09/14 09:47

SaitoAtsushi

総合スコア5684

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

020n

2021/01/18 07:38

丁寧なご回答ありがとうございました。 なんとなくイメージできました。初期化されていないメモリ領域が参照されてたまたまこの値になったのでしょうね。
guest

0

たまたまそのときにスタックに入っていた数値ですね。

投稿2019/09/14 08:49

y_waiwai

総合スコア88038

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

pepperleaf

2019/09/14 15:10

スタックとは限らない。 コンパイラ次第で、どっかのレジスタ。
y_waiwai

2019/09/14 22:29

まあ、この広い世の中、可変引数をレジスタで渡す環境があっても、また別の渡し方をする環境があったとしても不思議ではないですわな。 ましかし、特殊な環境を云々しだすときりがないわけで。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.36%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問