if関数?をヘッダに定義したい場合

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

if関数?をヘッダに定義したい場合

#1

投稿記事 by zxc » 12年前

 非常に簡単なことかもしれませんが、「if」と関数について質問させてください。
環境はXPのPentium4、Visual C++2008Express Editionです。

そもそもifやwhileは関数ということであっていますでしょうか?
関数ならばヘッダにプロトタイプ宣言?して、そのヘッダを#includeした上で
関数を書けば動くと思うのですが、その場合「if();」などと書いては
間違いなく動かないと思います。

 そこでまず 他と区別可能なようにしようと思ったのですが、

コード:

//A.cpp
if( DxLib_Init() == -1 ) return -1;
という処理と

コード:

//B.cpp
int Function(){
                      if( DxLib_Init() == -1 ) {
                       return -1;
                       }
}
という処理は別物なのか解らないので教えてください。
(この下の処理では、コンパイルが上手くいっても強制的に
終了したので再現しないほうが良いかと思います。)
  また、動かない理由も出来ればで良いので
教えてください。

アバター
bitter_fox
記事: 607
登録日時: 13年前
住所: 大阪府

Re: if関数?をヘッダに定義したい場合

#2

投稿記事 by bitter_fox » 12年前

zxc さんが書きました:「if」と関数について質問させてください。

そもそもifやwhileは関数ということであっていますでしょうか?
C言語ではifやwhile, forなどは関数ではありません。制御文という特別に解釈される存在です。
http://www9.plala.or.jp/sgwr-t/c/sec06.html
zxc さんが書きました:  そこでまず 他と区別可能なようにしようと思ったのですが、

コード:

//A.cpp
if( DxLib_Init() == -1 ) return -1;
という処理と

コード:

//B.cpp
int Function(){
                      if( DxLib_Init() == -1 ) {
                       return -1;
                       }
}
という処理は別物なのか解らないので教えてください。
(この下の処理では、コンパイルが上手くいっても強制的に
終了したので再現しないほうが良いかと思います。)
  また、動かない理由も出来ればで良いので
教えてください。

コード:

if (...) ...;

コード:

if (...)
{
	...;
}
は上の書き方は単文にしか適用できなくて、下は単文・複文に使用できるという点を除いては同等の表記です。
なので{}で囲むと落ちるなどということはありません。他の場所に原因があると思います。

non
記事: 1097
登録日時: 13年前

Re: if関数?をヘッダに定義したい場合

#3

投稿記事 by non » 12年前

zxc さんが書きました: 関数ならばヘッダにプロトタイプ宣言?して、そのヘッダを#includeした上で
関数を書けば動くと思うのですが、その場合「if();」などと書いては
間違いなく動かないと思います。
何度読んでも、意味がわかりません。何を質問したいのか、もう少し説明してください。
もしかしたら if(); ってのはプロトタイプのつもりでしょうか?
であれば、予約語ですから、識別子として使えません。
non

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

Re: if関数?をヘッダに定義したい場合

#4

投稿記事 by box » 12年前

non さんが書きました:
zxc さんが書きました: 関数ならばヘッダにプロトタイプ宣言?して、そのヘッダを#includeした上で
関数を書けば動くと思うのですが、その場合「if();」などと書いては
間違いなく動かないと思います。
何度読んでも、意味がわかりません。
if()が関数ならば、という前提がそもそも間違っているのですから、
それ以降の文章を読むことにはあまり意味がないように思います。
バグのないプログラムはない。
プログラムは思ったとおりには動かない。書いたとおりに動く。

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

Re: if関数?をヘッダに定義したい場合

#5

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

識別子()の形であるものが全て関数ではありません。
まず、C言語の基本構成要素であるステートメント(文)と関数呼び出しを区別して下さい。if()、switch()、while()は全てステートメント(文)です。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

naohiro19
記事: 256
登録日時: 13年前
住所: 愛知県

Re: if関数?をヘッダに定義したい場合

#6

投稿記事 by naohiro19 » 12年前

苦しんで覚えるC言語」の熟読をしてください。

zxc

Re: if関数?をヘッダに定義したい場合

#7

投稿記事 by zxc » 12年前

  解釈しづらい書き方をしたようで申し訳ありませんでした。

コード:

if(a>0) return -1;
というものと

コード:

int Func(){
        if(a>0) return -1;
}
このプログラムは同じ働きをしませんか? と質問すべきでした。
bitter_fox さんが書きました: C言語ではifやwhile, forなどは関数ではありません。
制御文という特別に解釈される存在です。
http://www9.plala.or.jp/sgwr-t/c/sec06.html
上記サイトの3つの構造を作るために必要な命令
であって関数ではないのですね。
解りました。
bitter_fox さんが書きました:

コード:

if (...) ...;

コード:

if (...)
{
	...;
}
は上の書き方は単文にしか適用できなくて、下は単文・複文に使用できるという点を除いては同等の表記です。
なので{}で囲むと落ちるなどということはありません。他の場所に原因があると思います。
 解りましたが、私はif文を関数に入れてしまえば関数として使えますか?
と聞きたかったのです。なので下のほうのプログラムは

コード:

//B.cpp
int Function(){
                      if( DxLib_Init() == -1 ) {
                       return -1;
                       }
}
と書いたつもりです。それと落ちる原因はまだわかりませんが、
ここの変更が原因であることは確かなので重点的に調べます。

non さんが書きました: 何度読んでも、意味がわかりません。何を質問したいのか、もう少し説明してください。
もしかしたら if(); ってのはプロトタイプのつもりでしょうか?
であれば、予約語ですから、識別子として使えません。
 おっしゃるとおり、プロトタイプのつもりでした。
ですが、関数であってもこれでは他のif()と区別できないので
動きませんよね?と聞きたかったのです。
softya(ソフト屋) さんが書きました:識別子()の形であるものが全て関数ではありません。
まず、C言語の基本構成要素であるステートメント(文)と関数呼び出しを区別して下さい。if()、switch()、while()は全てステートメント(文)です。
  ステートメント() はif,switch()等の()内(もしくは{})の数値や真偽を調べて
値を返す、C++に予め組み込まれている命令文の一種であり、関数と異なるもの
 ということなんですね?戻り値の型の定義がないのも関数で無いからですね。
naohiro19 さんが書きました:苦しんで覚えるC言語」の熟読をしてください。
  ありがとうございます。参考にさせていただきます。

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

Re: if関数?をヘッダに定義したい場合

#8

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

zxc さんが書きました:  解釈しづらい書き方をしたようで申し訳ありませんでした。

コード:

if(a>0) return -1;
というものと

コード:

int Func(){
        if(a>0) return -1;
}
このプログラムは同じ働きをしませんか? と質問すべきでした。
少なくとも同じ働きはしません。
returnは関数の呼び出しの直後に戻るので最初のがmainに書いてあるならaが0より大きければmainを抜けてOSに戻ります。つまり終了します。
後のはaが0より大きければFunc()関数の呼び出しに戻り値-1で戻ります。
こういうプログラムを試してみてください。まず動かす前に予想を立てて、予想と同じかどう違ったかを書いてみてください。

コード:

#include <stdio.h>

int Func(int a){
	if(a>0) return -1;
	return 0;
}

int main(void)
{
	printf( "Func(1)=%d\n", Func(1) );
	printf( "Func(0)=%d\n", Func(0) );
	
	return 0;
}
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

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

Re: if関数?をヘッダに定義したい場合

#9

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

zxc さんが書きました:  解釈しづらい書き方をしたようで申し訳ありませんでした。

コード:

if(a>0) return -1;
というものと

コード:

int Func(){
        if(a>0) return -1;
}
このプログラムは同じ働きをしませんか? と質問すべきでした。
同じ働きはしません。
前者は、それが書かれている関数のローカル変数にaがあれば、その値と0が比較されます。
後者は、グローバル変数のaと0が比較されます。
グローバル変数にaがなければ、コンパイルエラーになるでしょう。

コード:

#include <stdio.h>

int a=1;

int Func(){
	if(a>0) return -1;
}

int test() {
	int a=-1;
	printf("Func:%d\n",Func());
	if(a>0) return -1;
	return 0;
}

int main(void) {
	printf("test:%d\n",test());
	return 0;
}
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

zxc

Re: if関数?をヘッダに定義したい場合

#10

投稿記事 by zxc » 12年前

softya(ソフト屋) さんが書きました: 少なくとも同じ働きはしません。
returnは関数の呼び出しの直後に戻るので最初のがmainに書いてあるならaが0より大きければmainを抜けてOSに戻ります。つまり終了します。
後のはaが0より大きければFunc()関数の呼び出しに戻り値-1で戻ります。
こういうプログラムを試してみてください。まず動かす前に予想を立てて、どう違ったかを書いてみてください。
 同じ働きはしないのですね。解りました。
一応書いていただいた関数は予想と同じ結果を出しました。
みけCAT さんが書きました: 同じ働きはしません。
前者は、それが書かれている関数のローカル変数にaがあれば、その値と0が比較されます。
後者は、グローバル変数のaと0が比較されます。
グローバル変数にaがなければ、コンパイルエラーになるでしょう。
 同じ働きはしないのですね。解りました。
グローバル変数とローカル変数の件で混乱しましたが解決しました。

  皆さんの質問への回答で自身が勉強不足であると痛感いたしました。
張っていただいたサイト等利用し勉強してきます。
お答えいただき、ありがとうございました。
  このあたりで解決ということにしてもよろしいでしょうか。

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

Re: if関数?をヘッダに定義したい場合

#11

投稿記事 by beatle » 12年前

ちなみに的な話ですが参考になるかもしれませんから書いておきます.

ifが関数なら良かったのにと思うことがときどきあります.こんな感じにifを使いたいときです.

コード:

int result = my_if(a > b, a, b);
aとbを比較して,大きな方をresultに格納すると.

my_ifという関数を以下のように定義すれば上記のことができます.

コード:

int my_if(int cond, int then_value, int else_value)
{
    if (cond)
    {
        return then_value;
    }
    else
    {
        return else_value;
    }
}
ではもう一つ,こんなことをしたいとします.

コード:

char *str = my_if2(data != NULL, data->str, NULL);
dataというのがstrというメンバを含む構造体へのポインタであり,dataを経由してstrの値を取得したいとします.
でも,dataがNULLの場合にdata->strにアクセスするのはダメですから,data != NULLのときだけdata->strにアクセスしたいのです.
my_if2の定義を以下のようにしたとします.

コード:

char *my_if2(int cond, char *then_value, char *else_value)
{
    if (cond)
    {
        return then_value;
    }
    else
    {
        return else_value;
    }
}
実は,どんなふうに定義してもmy_if2関数の呼び出しはエラーになってしまいます.何でかというと,(C言語では)関数を呼び出す前に引数がすべて評価されるからです.つまり,第一引数「data != NULL」の値にかかわらず,第二引数「data->str」と第三引数「NULL」のどちらも評価されます.結局,dataがNULLの場合は必ず関数呼び出しの直前でダメになります.

ということで,ifを関数にすると破綻するケースが出てきます.

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

Re: if関数?をヘッダに定義したい場合

#12

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

beatle さんが書きました:ちなみに的な話ですが参考になるかもしれませんから書いておきます.

ifが関数なら良かったのにと思うことがときどきあります.こんな感じにifを使いたいときです.

コード:

int result = my_if(a > b, a, b);
aとbを比較して,大きな方をresultに格納すると.

my_ifという関数を以下のように定義すれば上記のことができます.

コード:

int my_if(int cond, int then_value, int else_value)
{
    if (cond)
    {
        return then_value;
    }
    else
    {
        return else_value;
    }
}
これって、

コード:

int result = ( a > b ? a : b );
ではダメなのですか?
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

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

Re: if関数?をヘッダに定義したい場合

#13

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

beatle さんが書きました:ではもう一つ,こんなことをしたいとします.

コード:

char *str = my_if2(data != NULL, data->str, NULL);
dataというのがstrというメンバを含む構造体へのポインタであり,dataを経由してstrの値を取得したいとします.
でも,dataがNULLの場合にdata->strにアクセスするのはダメですから,data != NULLのときだけdata->strにアクセスしたいのです.
my_if2の定義を以下のようにしたとします.

コード:

char *my_if2(int cond, char *then_value, char *else_value)
{
    if (cond)
    {
        return then_value;
    }
    else
    {
        return else_value;
    }
}
実は,どんなふうに定義してもmy_if2関数の呼び出しはエラーになってしまいます.何でかというと,(C言語では)関数を呼び出す前に引数がすべて評価されるからです.つまり,第一引数「data != NULL」の値にかかわらず,第二引数「data->str」と第三引数「NULL」のどちらも評価されます.結局,dataがNULLの場合は必ず関数呼び出しの直前でダメになります.

ということで,ifを関数にすると破綻するケースが出てきます.
この書き方なら問題ありません。

コード:

#include <stdio.h>
 
typedef struct {
        char* str;
} test_t;
 
int main(void) {
        test_t zikken;
        test_t* data;
        char *str;
        zikken.str="test";
        data=&zikken;
        str = (data != NULL ? data->str : NULL);
        printf("%p\n",str);
        data=NULL;
        str = (data != NULL ? data->str : NULL);
        printf("%p\n",str);
        return 0;
}
マクロにしておくといいでしょう。

コード:

#define my_if(cond,then_value,else_value) ((cond)?(then_value):(else_value))
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

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

Re: if関数?をヘッダに定義したい場合

#14

投稿記事 by beatle » 12年前

みけCAT さんが書きました:
beatle さんが書きました:ちなみに的な話ですが参考になるかもしれませんから書いておきます.

ifが関数なら良かったのにと思うことがときどきあります.こんな感じにifを使いたいときです.

コード:

int result = my_if(a > b, a, b);
aとbを比較して,大きな方をresultに格納すると.

my_ifという関数を以下のように定義すれば上記のことができます.

コード:

int my_if(int cond, int then_value, int else_value)
{
    if (cond)
    {
        return then_value;
    }
    else
    {
        return else_value;
    }
}
これって、

コード:

int result = ( a > b ? a : b );
ではダメなのですか?
もちろんそれでOKですよ.僕が言いたかったのは,ifを関数にするとダメなときがある,ということです.

zxc

Re: if関数?をヘッダに定義したい場合

#15

投稿記事 by zxc » 12年前

  返答するのが大変遅くなりました。すいませんでした。
beatle さんが書きました:ちなみに的な話ですが参考になるかもしれませんから書いておきます.

実は,どんなふうに定義してもmy_if2関数の呼び出しはエラーになってしまいます.何でかというと,(C言語では)関数を呼び出す前に引数がすべて評価されるからです.つまり,第一引数「data != NULL」の値にかかわらず,第二引数「data->str」と第三引数「NULL」のどちらも評価されます.結局,dataがNULLの場合は必ず関数呼び出しの直前でダメになります.

ということで,ifを関数にすると破綻するケースが出てきます.
  まず引数が評価されることはまったく知りませんでした。
ifが関数であるとエラーとなるケースの原因となるのですね。
参考になります。ありがとうございます。
みけCAT さんが書きました: これって、

コード:

int result = ( a > b ? a : b );
ではダメなのですか?
  そういえばこういうものもありました。
これで代用可能もしれないのでやってみます。
一応これで解決とさせていただきます。
お答えしてくださった皆さんありがとうございました。

閉鎖

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