質問をすることでしか得られない、回答やアドバイスがある。

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

新規登録して質問してみよう
ただいま回答率
85.48%
C

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

コンパイル

コンパイルとは、プログラミング言語のテキストソース(ソースコード)をコンピュータ上で実行可能な形式(オブジェクトコード)に変換することをいいます

Q&A

解決済

6回答

1574閲覧

C言語アドレス演算子の不具合かコンパイル不具合

shermansweet

総合スコア34

C

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

コンパイル

コンパイルとは、プログラミング言語のテキストソース(ソースコード)をコンピュータ上で実行可能な形式(オブジェクトコード)に変換することをいいます

0グッド

0クリップ

投稿2018/05/04 13:04

こんにちは。
C言語で以下のコードを書きました。

C

1int main(){ 2 int a=4; 3 printf("%ls\n", &a); 4 printf("%d\n", a); 5 return 0; 6}

実行結果は
4
でした。

つまり
printf("%ls\n", &a);
の結果が表示されません。

コンパイル環境は
gcc version 7.2.0 (Ubuntu 7.2.0-8ubuntu3.2)
です。

何が悪いのでしょうか?
おわかりの方お教えください。

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

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

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

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

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

yohhoy

2018/05/04 13:08

どのような結果(なにが出力されること)を期待していますか?
shermansweet

2018/05/05 02:32

値が格納されているメモリーのアドレスを表示させる事を期待していました。
guest

回答6

0

printf("%ls\n", &a);

マルチバイト文字として変数aの内容を表示させようということになりますが、これでそもそも良いのですか?また、これでいいのであればどのような表示を求めているのですか?

投稿2018/05/04 13:18

HogeAnimalLover

総合スコア4830

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

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

shermansweet

2018/05/05 02:37

値が格納されているメモリーのアドレスを表示させる事を期待していました。
guest

0

つprintf("%ls\n", &a); → printf("%p\n", &a);

投稿2018/05/04 13:11

hichon

総合スコア5737

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

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

shermansweet

2018/05/05 02:37

ご回答ありがとうございます
guest

0

ベストアンサー

フォーマット指示子%lswchar_t *型の文字列(NULLターミナルでなければならない)を表示する物で、wchar_t *型の文字列を期待し、wchar_t *型の文字列が与えられることを前提で動作します。しかし、対応する引数の&aint *型であり、wchar_t *とは型が一致しません。printfではフォーマットで指定した形式が期待する型と対応する引数の型が一致しない場合、その動作は未定義です。Cにおいて未定義な動作とは「何が起こるのかわからない。コード全体の内容、OSやコンパイラなどの実行環境、コンパイルのオプション、および、実行タイミング等によって、全く別の何かを表示したり、エラーになってプログラムが終了したり、何も起きなかったりと、様々な現象が発生する可能性がある」というものです。そのため、何も表示されなかったとしても、バグでもなでもなく、Cの仕様通りの動作になります。


以下、蛇足です。

さて、このコードですが、Windows環境でコンパイルしたり、Ubuntu環境でもint a = 4;の前後にint x = 0;等があるととASCII 4(ASCII制御文字4, EOT, 伝送終了, U+0004)が表示される場合があります。

  • Windowsではwchar_tがUTF-16LE(UCS-2)であり、また、リトルエンディアンであるため、int型の4は U+0004 U+0000 という文字列と見なせる。
  • Ubuntu(x86_64)ではwachr_tがUTF-32LE(UCS-4)であり、また、リトルエンディアンであるため、int型の4の前後にint型の0があると、スタック上の並びとして U+0004 U+0000 という文字列と見なせるようなメモリ配置になる場合がある。

では、何も表示されない今回の現象はなんなのでしょうか?考えられるのは、最適化によってaがスタックに積まれず、レジストリ上でのみ処理されたということです。もうひとつ考えられるのは、スタック外のメモリ領域へアクセスがあったため、強制的に停止させられたというということです。今回のコードは一種のセキュリティーホールになっているため、glibcのprintfにそういう仕組みがあってもいいような気がしないでもないです。ただ、それなら、プログラムの強制終了の方があり得そうですが、それはそれでDOS攻撃の起点とされると言うことで何もしないという選択になっているのかも知れません。逆アセンブリして追えばもう少し詳しくわかるかも知れませんが、いずれにしても「何が起こるかわからない」未定義の動作としては正しいため、気にしても仕方が無いのかも知れません。

投稿2018/05/04 16:07

raccy

総合スコア21735

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

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

0

%ls で何が出力されることを期待していますか?

投稿2018/05/04 13:24

episteme

総合スコア16614

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

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

shermansweet

2018/05/05 02:35

値が格納されているメモリーのアドレスを表示させる事を期待していました。
guest

0

表示されない問題だけ検証しました。

printf("%ls\n", &a); を
printf("%p\n", &a); に修正すると一応結果はでました。

結果

イメージ説明

環境は 
Linux
gcc version 6.3.0 20170516 (Debian 6.3.0-18+deb9u1)

でした。
ソースコードの内容を確認してから動作ですね。
あとはほかに回答されている内容を参考に。

投稿2018/05/04 13:37

kawakawa2018

総合スコア1195

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

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

shermansweet

2018/05/05 04:36 編集

%pという記述を初めて知りました。ありがとうございます。
hichon

2018/05/05 04:38

変換指定子というやつです。printfの書式指定は後発の言語でも使われているので覚えておくと良いでしょう。
shermansweet

2018/05/05 04:40

ありがとうございます。
guest

0

wchar_tって環境依存でucs2だったりucs4だったりするんだよね

c

1#include <stdio.h> 2#include <stdint.h> 3 4int main(){ 5 int64_t a=0x38; 6 printf("[%ls]\n", &a); 7 printf("[%ld]\n", a); 8 return 0; 9}

投稿2018/05/04 13:30

asm

総合スコア15147

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

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

shermansweet

2018/05/05 02:38

ご回答の内容に関してもっと勉強してみます。ありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問