ページ 11

16進数の下位2桁を取り出す処理について

Posted: 2016年11月30日(水) 20:53
by sadora3
学校の課題です。下記のような問題が出ましたが、サッパリ分かりません。
リトルエンディアンについて調べたのですが、理解出来ませんでした。
バイトオーダーがビックエンディアンとリトルエンディアンでは、実行結果が変わるのでしょうか?

それと、どうすれば16進数の下位2を取り出せますか?
桁数さえわかれば、あとはシフトして上位桁を追い出していくだけだと思うのですが、16進数の値の桁数の求め方とか分かりません。

OS:Windows10
コンパイラ:VisualStudio2010
言語:C

コード:

/*
以下のプログラムは「入力された整数の16進数下2ケタを表示する」プログラムである。
例・0x12345678 → 78  0x3456 → 56
「空欄」と記された部分を埋めてプログラムを完成させよ。
なお、このプログラムが動作するコンピュータのバイトオーダーはリトルエンディアンとする。
*/

#include<stdio.h>

//空欄1
void DispSimo(short* temp);
void DispSimo(long* temp);
//空欄1

void main(){
	short a;
	long b;

	printf("1つ目の整数を16進数で入力:");
	scanf("%hx", &a);
	DispSimo(&a);		//変数aの16進数下2ケタを表示

	printf("2つ目の整数を16進数で入力:");
	scanf("%lx", &b);
	DispSimo(&b);		//変数bの16進数下2ケタを表示

	rewind(stdin);
	getchar();
}

//空欄2
void DispSimo(short* temp){

	printf("%x\n", *temp);
}

void DispSimo(long* temp){

	printf("%x\n", *temp);
}
//空欄2

Re: 16進数の下位2桁を取り出す処理について

Posted: 2016年11月30日(水) 22:21
by box
sadora3 さんが書きました: 言語:C
C言語において
sadora3 さんが書きました:

コード:

void DispSimo(short* temp);
void DispSimo(long* temp);
このように同じ名前で違う型の引数を持つ関数は複数定義できないはずです。
どこかで何かが間違っているような気がします。

Re: 16進数の下位2桁を取り出す処理について

Posted: 2016年11月30日(水) 22:28
by sadora3
そうだったのですか・・・ではこの記述では間違っていますね。
では、
void DispSimo(void* temp);
こうなるのでしょうか?
しかし、この記述ですと実体にアクセスするにはどうすればいいのでしょうか?
void*の変数は、実体を使うためにはキャストが必要ですよね?

Re: 16進数の下位2桁を取り出す処理について

Posted: 2016年11月30日(水) 22:29
by C6b14
リトルエンディアンのマシンなら これで いいはず だけど (インテルはリトルエンディアンです)試してみてください。

コード:

void DispSimo1(short* temp) {
	*temp = *temp & 0xFF;
	printf("%x\n", *temp);
}
void DispSimo2(long* temp) {
	*temp = *temp & 0xFF;
	printf("%x\n", *temp);
}

Re: 16進数の下位2桁を取り出す処理について

Posted: 2016年11月30日(水) 22:33
by sadora3
*temp = *temp & 0xFF;
このやり方ですと、上位2ケタを取り出していませんか?
それともリトルエンディアンは、この記述で下位2ケタを取り出したことになるのでしょうか?

Re: 16進数の下位2桁を取り出す処理について

Posted: 2016年11月30日(水) 22:44
by C6b14
私のマシンでは 正解が でます。(インテルCPUです)

Re: 16進数の下位2桁を取り出す処理について

Posted: 2016年11月30日(水) 22:47
by みけCAT
C6b14 さんが書きました:リトルエンディアンのマシンなら これで いいはず だけど
ダメですね。
%xはunsigned int型のデータを期待するので、long型のデータを渡してしまうと未定義動作になり、int型とlong型のデータが異なる環境では誤動作の原因になるかもしれません。
リトルエンディアンならたまたま不都合を踏まないかもしれませんが、未定義動作を起こすのは美しくありません。

(shortは可変長引数に渡すときはintに変換され、符号付きでも符号なしでも表現できる値を符号の有無だけが違う所に渡すのは問題ないので、セーフでしょう)

(unsigned) shortを出力するにはhを、(unsigned) longを出力するにはlを%とxの間に入れますが、
今回の場合は出力する値が十分小さい(intは少なくとも-32767~32767の値を、unsigned intは少なくとも0~65535の値を格納できる)ので、
キャストするのが簡単でしょう。
ついでに、必ず2桁出力するように桁数の指定を入れてみました。

コード:

void DispSimo1(short* temp) {
	*temp = *temp & 0xFF;
	printf("%02x\n", (unsigned int)*temp);
}
void DispSimo2(long* temp) {
	*temp = *temp & 0xFF;
	printf("%02x\n", (unsigned int)*temp);
}
C6b14 さんが書きました:試してみてください。
ちゃんと警告が出ますね。
コード

コード:

#include <stdio.h>

void DispSimo1(short* temp) {
	*temp = *temp & 0xFF;
	printf("%x\n", *temp);
}
void DispSimo2(long* temp) {
	*temp = *temp & 0xFF;
	printf("%x\n", *temp);
}

int main(void){
    return 0;
}
コンパイラの出力

コード:

prog.c: In function 'DispSimo2':
prog.c:9:2: warning: format '%x' expects argument of type 'unsigned int', but argument 2 has type 'long int' [-Wformat=]
  printf("%x\n", *temp);
  ^
http://melpon.org/wandbox/permlink/5IjH7uSuHeiNRii8

Re: 16進数の下位2桁を取り出す処理について

Posted: 2016年11月30日(水) 22:51
by みけCAT
sadora3 さんが書きました:*temp = *temp & 0xFF;
このやり方ですと、上位2ケタを取り出していませんか?
それともリトルエンディアンは、この記述で下位2ケタを取り出したことになるのでしょうか?
(まともな処理系なら)エンディアンに関係なく、下位2ケタを残し、他のケタを0にする(=下位2ケタを取り出す?)でしょう。
なぜなら、C言語の(抽象機械上の計算として)定義された演算のみを使用し、エンディアンなどの具体的な計算機の性質に依存しないコードだからです。

Re: 16進数の下位2桁を取り出す処理について

Posted: 2016年11月30日(水) 23:01
by sadora3
あ!実行せずに変なこといって申し訳ありませんでした。
実行してみたらちゃんと下位2桁を取り出せていました。
以下のような計算になると勘違いしていました・・・。本当に申し訳ありません。

例えば4A5Bと入力したとする。
4A5B
FF
これの論理積になるので、出力は4Aとなる。

では、この問題はどうやって関数のプロトタイプ宣言を一つで済ませるか。という問題なのですね。
void DispSimo(void* temp);
これであっているのでしょうか?
また、こうした場合、実体を使うにはどうすればいいのでしょうか?

Re: 16進数の下位2桁を取り出す処理について

Posted: 2016年11月30日(水) 23:07
by みけCAT
sadora3 さんが書きました:では、
void DispSimo(void* temp);
こうなるのでしょうか?
しかし、この記述ですと実体にアクセスするにはどうすればいいのでしょうか?
void*の変数は、実体を使うためにはキャストが必要ですよね?
キャストしてデリファレンスすればいいのでしょう。
unsigned char型を含むcharacter typeのポインタを通じてなら、任意のオブジェクト(の中のバイト)へのアクセスが許されます。

Re: 16進数の下位2桁を取り出す処理について

Posted: 2016年11月30日(水) 23:08
by C6b14
もちろん プロトタイプ宣言 も 直す 必要が あります。C 言語は よく分からないけど 機械語 では これで 下位 がでるはずです。( コードは もとのまま 追加するだけです )

コード:

#include<stdio.h>

//空欄1
void DispSimo1(short* temp);
void DispSimo2(long* temp);
//空欄1

Re: 16進数の下位2桁を取り出す処理について

Posted: 2016年11月30日(水) 23:17
by sadora3
>>みけCATさん
申し訳ありませんが、仰っていることが分かりません・・・。
キャストはtempをキャストするのでしょうか?また、何型にキャストするのでしょうか?
「unsigned char型を含むcharacter typeのポインタ」というものが理解できません。character typeのポインタとはなんでしょうか?

>>C6b14さん
もしプロトタイプ宣言部をそのように直してしまうと、main関数内の関数使用部を変更しなければならなくなってしまいます。
問題文に、「「空欄」と記された部分を埋めてプログラムを完成させよ。」とあるように、空欄以外の部分は触ってはいけない決りとなっているためその方法は取れません。

Re: 16進数の下位2桁を取り出す処理について

Posted: 2016年11月30日(水) 23:19
by みけCAT
空欄以外を変えずに、関数を分けるプログラムを考えてみました。

コード:

/*
以下のプログラムは「入力された整数の16進数下2ケタを表示する」プログラムである。
例・0x12345678 → 78  0x3456 → 56
「空欄」と記された部分を埋めてプログラムを完成させよ。
なお、このプログラムが動作するコンピュータのバイトオーダーはリトルエンディアンとする。
*/

#include<stdio.h>

//空欄1
int afunc(short* x) {
	return printf("%02x\n", (unsigned int)(*x & 0xFF));
}

int bfunc(long* x) {
	return printf("%02x\n", (unsigned int)(*x & 0xFF));
}

#define DispSimo(x) 1 x ## func(x)
//空欄1

void main(){
	short a;
	long b;

	printf("1つ目の整数を16進数で入力:");
	scanf("%hx", &a);
	DispSimo(&a);		//変数aの16進数下2ケタを表示

	printf("2つ目の整数を16進数で入力:");
	scanf("%lx", &b);
	DispSimo(&b);		//変数bの16進数下2ケタを表示

	rewind(stdin);
	getchar();
}

//空欄2

//空欄2
&の存在をダミーの計算をさせることで邪魔にならないようにしつつ、トークンを結合する(プリプロセッサの)演算子を用いて別の関数を使えるようにしました。

Re: 16進数の下位2桁を取り出す処理について

Posted: 2016年11月30日(水) 23:19
by C6b14
ただ 関数 を 2個に しただけ ですよ。

Re: 16進数の下位2桁を取り出す処理について

Posted: 2016年11月30日(水) 23:24
by みけCAT
もしくは、void main()やrewind(stdin)を含む気持ち悪いプログラムは潰してしまえばいいでしょう。

コード:

/*
以下のプログラムは「入力された整数の16進数下2ケタを表示する」プログラムである。
例・0x12345678 → 78  0x3456 → 56
「空欄」と記された部分を埋めてプログラムを完成させよ。
なお、このプログラムが動作するコンピュータのバイトオーダーはリトルエンディアンとする。
*/

#include<stdio.h>

//空欄1
int main(void) {
	/* ここに好きなように実装を書く! */
	/* もちろん、このmain関数の前に関数を定義して使ってもOK! */
	return 0;
}

/* #if 0 ~ #endif で囲まれた部分はプリプロセッサに消し去ってもらえる! */
#if 0
//空欄1

void main(){
	short a;
	long b;

	printf("1つ目の整数を16進数で入力:");
	scanf("%hx", &a);
	DispSimo(&a);		//変数aの16進数下2ケタを表示

	printf("2つ目の整数を16進数で入力:");
	scanf("%lx", &b);
	DispSimo(&b);		//変数bの16進数下2ケタを表示

	rewind(stdin);
	getchar();
}

//空欄2
#endif
//空欄2

Re: 16進数の下位2桁を取り出す処理について

Posted: 2016年11月30日(水) 23:31
by sadora3
なんてコードだとびっくりしました!
defineを使う発想は思いつきもしませんでした。
しかも、2つめの回答もいい意味でいかれています!
こんな天才的な発想がよく出来ますね!
みけCATさんにはいつもお世話になっています。本当にありがとうございました。

この質問に回答してくれた他のお二方もありがとうございました!
物凄く勉強になりました!

Re: 16進数の下位2桁を取り出す処理について

Posted: 2016年11月30日(水) 23:34
by C6b14
>もしプロトタイプ宣言部をそのように直してしまうと、main関数内の関数使用部を変更しなければならなくなってしまいます。
>問題文に、「「空欄」と記された部分を埋めてプログラムを完成させよ。」とあるように、空欄以外の部分は触ってはいけない決りとなってい>るためその方法は取れません。
あ、ひっかかって しまった。 なぜ rewind(stdin); が使って あるかですね。

Re: 16進数の下位2桁を取り出す処理について

Posted: 2016年11月30日(水) 23:36
by C6b14
あ ごめん。

Re: 16進数の下位2桁を取り出す処理について

Posted: 2016年12月01日(木) 09:50
by C6b14
[追記]ビッグエンディアンとリトルエンディアンの 問題は バイトオーダーの 問題 なので C 言語 上は 同じ です。 バイト の 中身 が 逆 ( 答え 5B なら B5 )です。卵 の  さき どちらか ( 大きなほうか 小さなほうか ) に由来してるで どっちにしろ卵に かわりは 無い という たとえばなし です。

Re: 16進数の下位2桁を取り出す処理について

Posted: 2016年12月01日(木) 09:53
by みけCAT
C6b14 さんが書きました:バイト の 中身 が 逆 ( 答え 5B なら B5 )です。
いいえ。バイトの中身ではなく、バイトを配置する順番が違います。
例えば、0xDEADBEEFという値は、(バイト単位でアドレスがついている)メモリ上のデータは
リトルエンディアンだとEF BE AD DE
ビッグエンディアンだとDE AD BE EF
となります。

エンディアン - Wikipedia
バイトオーダ - ビッグエンディアン/リトルエディアン

Re: 16進数の下位2桁を取り出す処理について

Posted: 2016年12月01日(木) 09:54
by C6b14
ごめんなさい。”卵 の  さきは どちらか” です。

Re: 16進数の下位2桁を取り出す処理について

Posted: 2016年12月01日(木) 09:57
by みけCAT
もしもバイトの中身が逆だとしたら、どうして5B (0101 1011)はDA (1101 1010)ではなくB5になるのですか?

Re: 16進数の下位2桁を取り出す処理について

Posted: 2016年12月01日(木) 10:01
by C6b14
えーと ゆっくり 検証 してみますね。ややこしい 話なので。

Re: 16進数の下位2桁を取り出す処理について

Posted: 2016年12月01日(木) 10:41
by sadora3
C言語上ではバイトオーダーは気にしなくてもいいのですね。
では、なぜリトルとビッグがあるのでしょうか?
実行速度が若干変わったりするのでしょうか?

Re: 16進数の下位2桁を取り出す処理について

Posted: 2016年12月01日(木) 10:46
by Egg
オフトピック
ハッカーに反論するなら半端な知識じゃだめだし、言葉足らずな省略は通用しない
仕様書に記載するがごとく会話しなければ、突っ込まれるだけ

Re: 16進数の下位2桁を取り出す処理について

Posted: 2016年12月01日(木) 11:14
by Egg
>では、なぜリトルとビッグがあるのでしょうか?
https://msdn.microsoft.com/ja-jp/library/cc354745.aspx
こういうのに対応するためです。
順序を逆にする必要があるのは、Microsoft Windows オペレーティング システムがリトルエンディアン アーキテクチャを使っているからである。'Y' = 0x59、'U' = 0x55、および '2' = 0x32 なので、'2YUY' は 0x32595559 になる。
逆に言えばビッグエンディアン アーキテクチャの処理系なら
'YUY2' 0x59 0x55 0x59 0x32の順に1バイトづつ代入しないと'2YUY'とコンピュータが理解してしまって
「何やこのファイル、2YUYなんてコーデック、ワイ持ってないから再生できないわ」って言われます。

Re: 16進数の下位2桁を取り出す処理について

Posted: 2016年12月01日(木) 11:34
by sadora3
回答ありがとうございます。
今の私には難しい問題だと思いました・・・。
とても理解出来ませんでした。

Re: 16進数の下位2桁を取り出す処理について

Posted: 2016年12月01日(木) 11:37
by みけCAT
Egg さんが書きました:>では、なぜリトルとビッグがあるのでしょうか?
https://msdn.microsoft.com/ja-jp/library/cc354745.aspx
こういうのに対応するためです。
順序を逆にする必要があるのは、Microsoft Windows オペレーティング システムがリトルエンディアン アーキテクチャを使っているからである。'Y' = 0x59、'U' = 0x55、および '2' = 0x32 なので、'2YUY' は 0x32595559 になる。
逆に言えばビッグエンディアン アーキテクチャの処理系なら
'YUY2' 0x59 0x55 0x59 0x32の順に1バイトづつ代入しないと'2YUY'とコンピュータが理解してしまって
「何やこのファイル、2YUYなんてコーデック、ワイ持ってないから再生できないわ」って言われます。
これは違うエンディアンがあることの短所であって、違うエンディアンがある理由(長所)ではないでしょう。

異なるエンディアンがあるのは、それぞれに利点があるからでしょう。
リトルエンディアンは「異なる大きさの整数にするとき、下位バイトに触らず上位バイトのみ伸ばしたり縮めたりすればよい」
ビッグエンディアンは「メモリダンプを見た時、十六進数そのままの順番で表示されるので人間にとってわかりやすい」
などの利点があります。

[search=google]エンディアン なぜ[/search]
[search=google]リトルエンディアン 利点[/search]
[search=google]ビッグエンディアン 利点[/search]

↓数学的な美しさや、ビッグエンディアンで上から受信したほうが位置が決めやすいなどの特長が述べられています。
memo0024 - K-kiwi

Re: 16進数の下位2桁を取り出す処理について

Posted: 2016年12月01日(木) 11:38
by C6b14
いま VC2015 に アセンブラ と 逆アセンブラ をさせてみると 明らか WORD 単位 で 逆さまに 入ってます。
すみません。BYTE 単位 と WORD単位 の 勘違い みたいです。

コード:

/*
以下のプログラムは「入力された整数の16進数下2ケタを表示する」プログラムである。
例・0x12345678 → 78  0x3456 → 56
「空欄」と記された部分を埋めてプログラムを完成させよ。
なお、このプログラムが動作するコンピュータのバイトオーダーはリトルエンディアンとする。
*/
int main()
{
	int x = 0x12345678;
	short y = 0x3456;
	short z = 0x4A5B;
	return 0;
}

コード:

]
; Listing generated by Microsoft (R) Optimizing Compiler Version 19.00.24215.1 

	TITLE	D:\csi\_c\c1.c
	.686P
	.XMM
	include listing.inc
	.model	flat

INCLUDELIB LIBCMT
INCLUDELIB OLDNAMES

PUBLIC	_main
; Function compile flags: /Odtp
_TEXT	SEGMENT
_x$ = -12						; size = 4
_z$ = -8						; size = 2
_y$ = -4						; size = 2
_main	PROC
; File d:\csi\_c\c1.c
; Line 8
	push	ebp
	mov	ebp, esp
	sub	esp, 12					; 0000000cH
; Line 9
	mov	DWORD PTR _x$[ebp], 305419896		; 12345678H
; Line 10
	mov	eax, 13398				; 00003456H
	mov	WORD PTR _y$[ebp], ax
; Line 11
	mov	ecx, 19035				; 00004a5bH
	mov	WORD PTR _z$[ebp], cx
; Line 12
	xor	eax, eax
; Line 13
	mov	esp, ebp
	pop	ebp
	ret	0
_main	ENDP
_TEXT	ENDS
END

コード:

Microsoft (R) COFF/PE Dumper Version 14.00.24215.1
Copyright (C) Microsoft Corporation.  All rights reserved.


Dump of file c1.exe

File Type: EXECUTABLE IMAGE

  00401000: 55                 push        ebp
  00401001: 8B EC              mov         ebp,esp
  00401003: 83 EC 0C           sub         esp,0Ch
  00401006: C7 45 F4 78 56 34  mov         dword ptr [ebp-0Ch],12345678h
            12
  0040100D: B8 56 34 00 00     mov         eax,3456h
  00401012: 66 89 45 FC        mov         word ptr [ebp-4],ax
  00401016: B9 5B 4A 00 00     mov         ecx,4A5Bh
  0040101B: 66 89 4D F8        mov         word ptr [ebp-8],cx
  0040101F: 33 C0              xor         eax,eax
  00401021: 8B E5              mov         esp,ebp
  00401023: 5D                 pop         ebp
  00401024: C3                 ret

Re: 16進数の下位2桁を取り出す処理について

Posted: 2016年12月01日(木) 11:51
by Egg
>みけCATさん
確かにそのとおりですね。

>sadora3さん
みけCATさんが記述されているのが、『エンディアンが二つ存在する原因』で
私の記述は『二つ存在する結果として、上記のような処理を入れる必要がある例』です。

Re: 16進数の下位2桁を取り出す処理について

Posted: 2016年12月01日(木) 12:57
by C6b14
>C言語上ではバイトオーダーは気にしなくてもいいのですね。
>では、なぜリトルとビッグがあるのでしょうか?
>実行速度が若干変わったりするのでしょうか?
そのとうりです。 インテル が 最初に CPU (x86のもと) を 作った時 日本人 の 嶋正利さん が 中心になってつくられたのですが。
リトルエンデイァン のほうが 実行速度 で 有利だったのと なにか 利点があったはず。IBM 、モトローラ、Sun は ビッグエンデイァン
の アーキテクチャ で CISCとRISCの 違い だった と思います。 

Re: 16進数の下位2桁を取り出す処理について

Posted: 2016年12月01日(木) 13:33
by C6b14
エンディアンの 話 は 記憶 違い でした。ごめんm(__)m。CISC  と RISC の違いも あったのでしょうか。

Re: 16進数の下位2桁を取り出す処理について

Posted: 2016年12月01日(木) 13:44
by C6b14
みけCAT さんが書きました:
C6b14 さんが書きました:バイト の 中身 が 逆 ( 答え 5B なら B5 )です。
いいえ。バイトの中身ではなく、バイトを配置する順番が違います。
例えば、0xDEADBEEFという値は、(バイト単位でアドレスがついている)メモリ上のデータは
リトルエンディアンだとEF BE AD DE
ビッグエンディアンだとDE AD BE EF
となります。

エンディアン - Wikipedia
バイトオーダ - ビッグエンディアン/リトルエディアン
ごめんなさい。間違いです。

Re: 16進数の下位2桁を取り出す処理について

Posted: 2016年12月05日(月) 00:36
by C6b14
[追記]この問題の回答を書くの忘れてたので書いておきます。

コード:

/*
以下のプログラムは「入力された整数の16進数下2ケタを表示する」プログラムである。
例・0x12345678 → 78  0x3456 → 56
「空欄」と記された部分を埋めてプログラムを完成させよ。
なお、このプログラムが動作するコンピュータのバイトオーダーはリトルエンディアンとする。
*/
#include<stdio.h>

//空欄1
void DispSimo(long* temp);
//空欄1

void main() {
	short a;
	long b;

	printf("1つ目の整数を16進数で入力:");
	scanf("%hx", &a);
	DispSimo(&a);       //変数aの16進数下2ケタを表示

	printf("2つ目の整数を16進数で入力:");
	scanf("%lx", &b);
	DispSimo(&b);       //変数bの16進数下2ケタを表示

	rewind(stdin);
	getchar();
}

//空欄2
void DispSimo(long* temp) {
	*temp = *temp & 0xFF;
	printf("%x\n", *temp);
}
//空欄2

Re: 16進数の下位2桁を取り出す処理について

Posted: 2016年12月05日(月) 01:01
by みけCAT
C6b14 さんが書きました:

コード:

void DispSimo(long* temp) {
	*temp = *temp & 0xFF;
	printf("%x\n", *temp);
}
unsigned int型のデータを渡されることを期待する%xにlong型のデータを渡したので、未定義動作です。
さらに、short型よりlong型が大きい環境の場合、確保された範囲の外の読み書きを行ってしまい、危険です。

対抗して解答例を書いておきます。

コード:

/*
以下のプログラムは「入力された整数の16進数下2ケタを表示する」プログラムである。
例・0x12345678 → 78  0x3456 → 56
「空欄」と記された部分を埋めてプログラムを完成させよ。
なお、このプログラムが動作するコンピュータのバイトオーダーはリトルエンディアンとする。
*/
#include<stdio.h>

//空欄1
void DispSimo(const void* temp);
//空欄1

void main() {
	short a;
	long b;

	printf("1つ目の整数を16進数で入力:");
	scanf("%hx", &a);
	DispSimo(&a);       //変数aの16進数下2ケタを表示

	printf("2つ目の整数を16進数で入力:");
	scanf("%lx", &b);
	DispSimo(&b);       //変数bの16進数下2ケタを表示

	rewind(stdin);
	getchar();
}

//空欄2
void DispSimo(const void* temp) {
	printf("%02x\n", (unsigned int)(*(const unsigned char*)temp & 0xff));
}
//空欄2
Wandboxでの実行結果

コード:

1つ目の整数を16進数で入力:56
2つ目の整数を16進数で入力:78

Re: 16進数の下位2桁を取り出す処理について

Posted: 2016年12月05日(月) 08:56
by Egg
void main()やrewind(stdin)を含む気持ち悪いプログラムは潰してしまえばいいでしょう。
void main()やrewind(stdin)を使わない正しい解答を提示したほうがよろしいと思われますが。

Re: 16進数の下位2桁を取り出す処理について

Posted: 2016年12月05日(月) 09:05
by C6b14

Re: 16進数の下位2桁を取り出す処理について

Posted: 2016年12月05日(月) 09:22
by C6b14
>void main()やrewind(stdin)を使わない正しい解答を提示したほうがよろしいと思われますが
すみません。rewind(stdin)は消すべきでした。void main() 正しくはint main()とかくべしと思いますが。いまの規則ではvoid main() と書いてあってもint main()と同じ機械語が生成されるので一概には間違いとは言えないです。ただしC言語を教えるひとがvoid main() と書くのはやはりどうかなとおもうのでint main()が正しいとはおもいます。http://www.6809.net/tenk/html/cgokai/int_main.htm

Re: 16進数の下位2桁を取り出す処理について

Posted: 2016年12月05日(月) 10:03
by C6b14
あ、それと”問題文に、「「空欄」と記された部分を埋めてプログラムを完成させよ。」とあるように、空欄以外の部分は触ってはいけない決りとなっているためその方法は取れません”と質問者様の返信にあったのです。しかしrewind(stdin)やvoid main()を使って教えるのは意味不明だし、何らかの前提条件があったように思います。(出題者が変といえば、そうです)

Re: 16進数の下位2桁を取り出す処理について

Posted: 2016年12月05日(月) 10:43
by C6b14
ここを読むとhttp://keicode.com/winprimer/wp06.phpmainである必然性はなくてFooから始まるプログラムもVS2015では作れるので問題はC++17,14,11など規則だけの問題に見えます。Windows10,VS2015の処理系だけしか無いので規則の問題はよくわかりません。

Re: 16進数の下位2桁を取り出す処理について

Posted: 2016年12月05日(月) 11:43
by C6b14

Re: 16進数の下位2桁を取り出す処理について

Posted: 2016年12月05日(月) 12:10
by みけCAT
Egg さんが書きました:
void main()やrewind(stdin)を含む気持ち悪いプログラムは潰してしまえばいいでしょう。
void main()やrewind(stdin)を使わない正しい解答を提示したほうがよろしいと思われますが。
確かにそうですね。
「プログラムを完成させる」という趣旨に反する気がしたので避けたのですが、よく考えたらただDispSimo関数を定義するだけなら本来空欄2なんて必要ないので、わざわざ空欄2があるということは不適切なプログラムをプリプロセッサで消し去る方が正しいと考えられるでしょう。

コード:

/*
以下のプログラムは「入力された整数の16進数下2ケタを表示する」プログラムである。
例・0x12345678 → 78  0x3456 → 56
「空欄」と記された部分を埋めてプログラムを完成させよ。
なお、このプログラムが動作するコンピュータのバイトオーダーはリトルエンディアンとする。
*/
#include<stdio.h>

//空欄1
void DispSimo(int n) {
	unsigned long a;
	printf("%dつ目の整数を16進数で入力:", n);
	if (scanf("%lx", &a) == 1) {
		printf("%02x\n", (unsigned int)(a & 0xff));
	} else {
		puts("入力エラー");
		scanf("%*s"); /* ゴミがあると予想されるので取る */
	}
}

int main(void) {
	int i;
	for (i = 1; i <= 2; i++) {
		DispSimo(i);
	}
	return 0;
}

#if 0
//空欄1

void main() {
	short a;
	long b;

	printf("1つ目の整数を16進数で入力:");
	scanf("%hx", &a);
	DispSimo(&a);       //変数aの16進数下2ケタを表示

	printf("2つ目の整数を16進数で入力:");
	scanf("%lx", &b);
	DispSimo(&b);       //変数bの16進数下2ケタを表示

	rewind(stdin);
	getchar();
}

//空欄2
#endif
//空欄2