C言語において、関数ポインタの型をtypedefで作ると、

typedef int (*MyFunc)(int*,int*);

と宣言でき、関数ポインタの変数は、

int FuncA(int* a, int* b)
{

}

void main_loop()
{
MyFunc pf = FuncA;

(*pf)(pa,pb);
}

というように使うと思います。

ここで疑問なのですが、この実際に呼び出される関数、FuncAの定義に、typedef(ここではMyFunc)を使えないものでしょうか?

同じことを2回やっているようで、無駄に思えてしまいます。

このQ&Aに関連する最新のQ&A

A 回答 (5件)

C では、式の中の関数名だけが関数を指すポインタに読み替えられます。


# これは、コンパイラが勝手に読み替えます。

関数定義やプロトタイプ宣言といった、式の中にない関数名はポインタに読み替えられることはありません。

ですので、ご質問の中にある

> typedef int (*MyFunc)(int*,int*);



> int FuncA(int* a, int* b)
> {
> ~
> }

は、別の型ということになります。

FuncA( pa, pb ); // FuncA はポインタに読み替えられている。

と関数を式の中に記述した場合にのみ、コンパイラがこの FuncA をポインタとして読み替えるんです。

式の中という意味では、以下の場合も同様です。

MyFunc pf = FuncA; // FuncA はポインタに読み替えられている。

実際、pf に FuncA を代入する場合、以下のようにしても正常に動作します。

MyFunc pf = &FuncA; // アドレス演算子 & をつけてみる。

ついでに、(*pf)() コールの箇所も、以下のようにすることができます。

pf(pa,pb); // 間接参照演算子 * をとってみた。

つまり、関数を指すポインタに「限って」いえば、間接参照演算子はあってもなくても良い存在です。
というわけで、こんなことをしてもコンパイルエラーにも実行エラーにもなりません。

(**********pf)(pa,pb); // どうせ * は何もしないし。。。

このように、関数のポインタ周りの仕様はかなり混乱しています。
配列とポインタが違うものであるように、関数と関数ポインタも別物です。
どちらも、C のコンパイラが自分の都合でポインタに読み替えているだけです。

こんな感じでいかがでしょうか。
    • good
    • 0

関数ポインタに代入する関数が、1つで決まってるなら無駄といえば無駄ですね。


この場合なら
int FuncA(int* a, int* b){~}
void main_loop(){
 FuncA(pa,pb);
}
で十分です。

関数ポインタが必要になるような例は。

typedef int (*MyFunc)(int*,int*);
int FuncA(int* a, int* b){ ~ }
int FuncB(int* a, int* b){ ~ }

void main_loop(){
 MyFunc pf;
 if (flag) {
  pf = FuncA; // flagが真であればFuncAを呼び出す
 } else {
  pf = FuncB; // flagが偽であればFuncBを呼び
 }
 (*pf)(pa,pb);
}
こうゆう使い方なら納得できるとかと思います。
    • good
    • 0

多分, できないと思います.


該当する例は見付ていないのですが,
The identifier declared in a function definition (which is the name of the function) shall have a function type, as specified by the declarator portion of the function definition.
とあって, ここに対する脚注として
The intent is that the type category in a function definition cannot be inherited from a typedef.
と書かれており, その例として以下が規格に挙げられています:
typedef int F(void);
F f, g; // f and g both have type compatible with F
F f { /* ... */ } // WRONG: syntax/constraint error
F g() { /* ... */ } // WRONG: declares that g returns a function
脚注部分で「the type category in a function definition cannot be inherited from a typedef」と書かれているので,
typedef int (*PF)(void);
でも
PF *f { /* ... */ }
はアウトだと思います.
    • good
    • 0
この回答へのお礼

こういうものだと思うことにします^^;
ご丁寧にありがとうございました。

お礼日時:2006/06/27 20:59

おそらく参考書を読みながら質問しているのかと思いますが、参考書では関数のポインタを手短に説明するために質問にあるようなコードが提示されているんだろうと思います。



もう少し発展させて・・・
MyFunc pf;
ではなく、単純なリスト構造にするために
MyFunc pf[100];
とかだったら、(配列の終わり判定を含めて)100個までの処理を並べることができますよね。
あとは添え字をインクリメントしていけば、バッチ言語処理のようなことが出来そうな気がしてくれば、C言語のプログラミングを勉強した甲斐があったというものでしょう。

もっと詳しく知りたいのならば、
「実用Cプログラミング生 粋のCプログラマへ」H.シュルト著
http://www.fukkan.com/vote.php3?no=19161
とか
「エキスパートCプログラミング - 知られざるCの深層 -」Peter van der Linden著
などといった、K&Rを卒業した中級以上のスキルを対象にする本を眺めてみることです。
    • good
    • 0

MyFunc pf = FuncA;



代入(メモリ上に値を記憶するための必要な領域を確保)

(*pf)(pa,pb);

演算処理?
    • good
    • 0

このQ&Aに関連する人気のQ&A

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人はこんなQ&Aも見ています

このQ&Aを見た人が検索しているワード

このQ&Aと関連する良く見られている質問

QLNK2019: 未解決の外部シンボルのエラーが出る

Microsoft Visual Studio 2008
Version 9.0.21022.8 RTM
Microsoft .NET Framework
Version 3.5 SP1
----------------------------------------------------------------
新しいプリジェクト→Win32 コンソール アプリケーション(ソリューションのディレクトリを作成 チェック外す)→Windows アプリケーション(空のプロジェクト チェック外す)
----------------------------------------------------------------
 プログラム

 mymain.cpp
#include "myhelper.h"
#include "mymain.h"

//自キャラのデータ
Point2D g_jikipos = {40, 400};//自キャラの座標

//画像ハンドル
int g_jikiimage[11];

//色々なファイルの読み込み
int LoadFiles(){
//画像ファイル読み込み
if(LoadDivGraph("media\\player01.bmp",
11,11,1,64,64,g_jikiimage) == -1) return -1;

return 1;
}


 mymain.h
//他から呼び出させるMyMainの関数
void MyMain();
int LoadFiles();


 myhelper.h(サンプルなので打ちミスはない)
#include "DxLib.h"
#include <limits.h>
#include <math.h>

//構造体宣言
//座標またはベクトルを記録する構造体
struct Vector{
float x,y;
};
typedef Vector Point2D;
//線を記録する構造体
struct Line2D{
Point2D startpos, endpos;
float katamuki;//傾きをラジアン値で記録
Vector speed;//移動している場合は速度をセット
};
//球体を記録する構造体
struct Ball2D{
Point2D position;
float hankei;//半径
};
//四角形を記録する構造体
struct Rect2D{
Point2D lefttop;
Point2D rightbottom;
float width;
float height;
};


//ライブラリ関数
Point2D PosInView(Point2D in);
int XInView(float inx);
int YInView(float iny);
void ScrollToLeft(float jikiposx);
void ScrollToRight(float jikiposx);
void ScrollToUp(float jikiposy);
void ScrollToDown(float jikiposy);
void DrawLineInView(float x1, float y1, float x2, float y2, int Color, int Thickness);
void DrawCircleInView(float x, float y, float r, int Color, int FillFlag);
void DrawAnimation(float x, float y, double ExtRate, double Angle,int TurnFlag,
int *imgarray, int allframe, float fps);
//ベクトル関数
Vector CreateVector(Vector in, float veclen);
Vector AddVector(Vector v1, Vector v2);
Vector SubVector(Vector v1, Vector v2);
Vector AddVectorInFrameTime(Vector pos, Vector speed);
Vector AddVectorInFrameTime2(Vector pos, Vector speed, Vector accel);
Vector Normalize(Vector in);
Vector RotateVector(Vector in, float radian);
float VectorLengthSquare(Vector in);
float DotProduct(Vector v1, Vector v2);
float CrossProduct(Vector v1, Vector v2);
void SetLine2DKatamuki(Line2D *in);
void DrawLine2D(Line2D in, int Color, int Thickness);
void DrawBall2D(Ball2D in, int Color, int Fill);
//当たり判定関数
bool HitTestLineAndBall(Line2D linein, Ball2D ballin);
bool IsPointAtLineFace(Line2D linein, Point2D ptin);
bool HitTestLineAndLine(Line2D line1, Line2D line2);
bool HitTestBallAndBall(Ball2D a, Ball2D b);
bool HitTestPointAndBox(Rect2D rect, Point2D pt);
//タイマー関数
void SetSimpleTimer(int idx, int time);
int GetPassedTime(int idx);


//グローバル変数
extern float g_frametime;
extern Rect2D g_framerect;//画面領域(当たり判定)
extern Point2D g_current_field_pos;//現在の左上座標
extern Rect2D g_stagesize;//ステージサイズ

//定数宣言
const float ZEROVALUE = 1e-10f;
const float PIE = 3.1415926f;
const int SCROLL_LIMIT = 200;
----------------------------------------------------------------
 エラー内容
1>myhelper.obj : error LNK2019: 未解決の外部シンボル "void __cdecl MyMain(void)" (?MyMain@@YAXXZ) が関数 _WinMain@16 で参照されました
1>C:\Documents and Settings\Owner\My Documents\Visual Studio 2008\Projects\my\Debug\my.exe : fatal error LNK1120: 外部参照 1 が未解決です
1>my - エラー 2、警告 0
ビルド: 0 正常終了、1 失敗、0 更新不要、0 スキップ
----------------------------------------------------------------
画像を貼り付けときます
(見えにくい場合→http://www.dotup.org/uploda/www.dotup.org154142.jpg.html)
初心者なのでわかりやすくお願いします

Microsoft Visual Studio 2008
Version 9.0.21022.8 RTM
Microsoft .NET Framework
Version 3.5 SP1
----------------------------------------------------------------
新しいプリジェクト→Win32 コンソール アプリケーション(ソリューションのディレクトリを作成 チェック外す)→Windows アプリケーション(空のプロジェクト チェック外す)
----------------------------------------------------------------
 プログラム

 mymain.cpp
#include "myhelper.h"
#include "mymain.h"

//自...続きを読む

Aベストアンサー

ファイル構成から推測するに
mymain.cpp というファイルに
void MyMain(void) {
// ここに処理を書く
}
という関数が必要なようです。

Q関数ポインタを返す関数の型をtypedefする方法

C言語について質問します。

ある関数を定義するとします。
その関数は引数としてintを一つ取り、返値としてその関数と同じ型の関数へのポインタを返すようにしたいのですが、どのように書けばよいのでしょうか?
そして、その関数の型をtypedefで定義したいです。

例えば、FNをtypedefしたいその関数の型だとすると、

typedef FN (*FN)(int);

のようなFNを定義したいのですが、上のように書いても当然コンパイラ(VC9)に怒られます。
最悪、

typedef void* (*FN)(int);

とvoidポインタを返すように定義しておいて、そのポインタを返値として受け取った側でFNにキャストし直す方法で対処できなくもないですが、ちょっと強引過ぎる気がします。
何かいい方法はあるのでしょうか?

boost::functionあたりを使えばできそうな、そうでもないような気がしますが、できれば純粋なCでの解決法を望みます。
よろしくお願いします。

Aベストアンサー

こんばんは。
More Exceptional C++の213~214ページにそっくりそのままの用途の内容がありますね。

まず
typedef FN (*FN)(int);
と言ったこと自体は確かに不可能です。

ということで、これに似た事がやりたい場合はどうするか
という方向性の話ですが


問題なのは
typedef void* (*FN)(int);
この形式では

void*は関数ポインタ以外のポインタ(オブジェクトのポインタ)はどんなものでも保持できる十分な大きさが保証されているが、関数ポインタに対してはその限りではなく

sizeof(void*) < sizeof(FN)

となるプラットフォームも存在するし、別のコンパイラにしたり、バージョンアップするだけで、動作しなくなる可能性がある
とのことです。

そう言う点だけであれば関数ポインタを使ってキャストすれば可能ではある
とは書かれています。

↓以下若干変えつつ引用、その1

/////////////////

typedef void (*VoidFP)();
typedef VoidFP (*FP)();

VoidFP f(){ return (VoidFP)f; } //VoidFPへのキャスト。

FP p = (FP)f; //VoidFPからのキャスト。
p();


このコードは技術的に正しい。

しかし、型システムを故意に破っている点で危険であり、f()の全ユーザにキャストの使用を強制する点で望ましくない。

/////////////////

とのことです。

そしてC++のコードになりますが
「正しく、かつ移植性のある方法」と銘打たれている方法は

若干変えつつ引用、その2
/////////////////

class FP_;
typedef FP_ (*FP)();

class FP_ {
FP p_;
public:
FP_( FP p ) : p_(p){}
operator FP(){ return p_; }
};

これで、FPオブジェクトの宣言、定義、および自然な呼び出しが可能になる。

FP_ f(){ return f; }

int main(){
FP p = f(); //自然な呼び出しのシンタックス
p();
}

/////////////////

とのことですね。

こんばんは。
More Exceptional C++の213~214ページにそっくりそのままの用途の内容がありますね。

まず
typedef FN (*FN)(int);
と言ったこと自体は確かに不可能です。

ということで、これに似た事がやりたい場合はどうするか
という方向性の話ですが


問題なのは
typedef void* (*FN)(int);
この形式では

void*は関数ポインタ以外のポインタ(オブジェクトのポインタ)はどんなものでも保持できる十分な大きさが保証されているが、関数ポインタに対してはその限りではなく

sizeof(void*) < sizeof(FN)

と...続きを読む

Qファイルやディレクトリの存在確認を行う方法

ファイルをオープンするのはfopenでOKですが、ファイルやディレクトリの存在確認を行う方法が知りたいです。

何か組み合わせて作るものなのでしょうか?
perlとか便利な演算子があるのですが、C/C++って器用ではないですね。
これは処理系?依存の内容ですか?

私の環境は VC6, VC2005 Windows2000です。

Aベストアンサー

int access(const char* path, int mode);
int stat(const char* path, struct stat* sb);

かな?
MSDN を引くと _access_s() を使えとか書いてあるけど。

Q#defineの定数を文字列として読み込む

#define A "xxx"
#define B "yyy"
と定義しておいて

scanf("%s", str)
で読み込んだ文字列strが
"xxx"だった場合、"yyy"だった場合のように分岐したいのですが
このとき

if(str == "xxx")
のように中身を指定するのではなく

if(str == AA)
のように定数で分岐させることってできますか?

上記のままではできませんが、何か特別な関数とかでできるのでしょうか?

Aベストアンサー

こんにちは。

やりたいことの解釈ですが、(※勘違いの場合はすみません。)

1)マクロの名前(定義名)が文字列として格納された文字列 str があるとする。
 例)
   #define A "xxx"  //マクロ名=A
   char str[] = "A";   //"A"はマクロ名

2)上記の文字列 str を関数 func に渡す際に、マクロ名ではなくそのマクロで
  定義された文字列を渡したい。
 例)
   func( str );    //←この場合
    ↓
   func( "xxx" );  //←として展開される

ということで宜しいでしょうか?

だとした場合、少し回りくどいやり方かもしれませんが、以下のような文字列
変換用のマクロを定義してみては如何でしょうか?
※基本的には、他の回答者の方と同じように strcmp関数 を使用します。

■マクロ例
==============================
//文字列を定義したマクロ …※1
#define A "xxx"
#define B "yyy"

//引数を文字列として取得するマクロ
#define GETSTR(x) #x

//引数をマクロ名としてそのマクロで定義された文字列を取得するマクロ …※2
//注)<string.h>がインクルードされていることを前提とする
#define STR2MAC(str) \
!strcmp(str,GETSTR(A))? A : \
!strcmp(str,GETSTR(B))? B : str
==============================

上記マクロを使用して、関数 func にマクロ名が格納された文字列 str を
渡す場合は、
   func( STR2MAC( str ) );
のような記述になります。

前提として、※2のマクロ内でstrcmp関数を用いて文字列の照合を行って
いますので、<string.h>のインクルードが必要になります。

また、※1の文字列を定義するマクロの種類(パターン)を増やす場合、
※2のマクロの判定文もそれに合わせて増やす必要があります。

上記のマクロを使用したサンプルソースを下記に掲載致します。
注)エラー処理は行っていません。

■サンプルソース
==============================
#include <stdio.h>
#include <string.h>

//文字列を定義したマクロ
#define A "xxx"
#define B "yyy"

//引数を文字列として取得するマクロ
#define GETSTR(x) #x

//引数をマクロ名としてそのマクロで定義された文字列を取得するマクロ
//注)<string.h>がインクルードされていることを前提とする
#define STR2MAC(str) \
!strcmp(str,GETSTR(A))? A : \
!strcmp(str,GETSTR(B))? B : str

//プロトタイプ
void funcHoge( const char *str );

int main(void)
{
char sArg[128];

printf( "A or B ?>" );
scanf( "%s", sArg );

printf( "string1: %s\n", sArg );
funcHoge( STR2MAC(sArg) );

return 0;
}

void funcHoge( const char *str )
{
printf( "string2: %s\n", str );
}
==============================

■上記サンプルの実行結果
≫実行その1≪
A or B ?>A
string1: A
string2: xxx

≫実行その2≪
A or B ?>B
string1: B
string2: yyy

≫実行その3≪
A or B ?>hoge
string1: hoge
string2: hoge

以上です。

こんにちは。

やりたいことの解釈ですが、(※勘違いの場合はすみません。)

1)マクロの名前(定義名)が文字列として格納された文字列 str があるとする。
 例)
   #define A "xxx"  //マクロ名=A
   char str[] = "A";   //"A"はマクロ名

2)上記の文字列 str を関数 func に渡す際に、マクロ名ではなくそのマクロで
  定義された文字列を渡したい。
 例)
   func( str );    //←この場合
    ↓
   func( "xxx" );  //←として展開される

ということで宜しいでしょう...続きを読む

Qunsigned long long 型のフォーマット指定子

unsigned long long 型の変数の値を表示したいのですが、
フォーマット指定子は%ldですか?
よろしくおねがいします。

Aベストアンサー

規格上は、%llu のように ll を付けます。(unsigned long longなので、%lld ではなく %llu です。)
ただし、C99に準拠した処理系ではなく、単に独自拡張としてlong long型をサポートしている場合には、%Lu とか %qu とかになる場合もあります。場合によっては、long long型が存在する処理系でも、printf系関数で正しく書式化する方法が存在しないこともあり得ます。

Qfatal error LNK1120: 外部参照 1 が未解決です

またわからないことが・・・
教えて下さい。
以下をVC++2005でコンパイルすると、

MSVCRTD.lib(crtexew.obj) : error LNK2019: 未解決の外部シンボル _WinMain@16 が関数 ___tmainCRTStartup で参照されました。
C:\Documents and Settings\tomato\My Documents\Visual Studio 2005\Projects\a\Debug\a.exe : fatal error LNK1120: 外部参照 1 が未解決です。

と警告がでて通りません。
何のことでしょうか。

#include<stdio.h>
#include<process.h>

struct meibo{
  char name[20];
  char tel[20];
  char address[20];
};

void message( void );
void input( FILE *fp, int cnt , struct meibo *a, int *end );

void main( void )
{
  struct meibo a[20];
  FILE *fp;
  int cnt, end;

  if( (fp=fopen( "meibo.dat", "w" ) ) == NULL ){
    printf( "Can not open the meibo.dat.\n" );
    exit( 1 );
  }

  message();

  fprintf( fp, "番号, 名前, TEL, 住所\n" );
  fflush( fp );

  cnt = 0;
  end = 0;
  while( end == 0 ){
    input( fp, cnt, &a[cnt], &end );
    cnt++;
    fflush( fp );
    if( cnt == 20 ){
      printf( "人数が一杯です.終了します.\n" );
      end = 1;
    }
  }
  fclose( fp );
}

void message( void )
{
  printf( "名前, TEL, 住所, endを入力してください.\n" );
  printf( "継続の時はend=0," );
  printf( "中止の時は,end=1と入力してください.\n" );
}

void input( FILE *fp, int cnt, struct meibo *a, int *end )
{
  printf( "名前-->" );
  scanf( "%s", a->name );
  printf( "TEL -->" );
  scanf( "%s", a->tel );
  printf( "住所-->" );
  scanf( "%s", a->address );
  printf( "Exit? Continue:0 Exit:1 -->" );
  scanf( "%d", end );
  printf( "\n" );
  fprintf( fp, "%2d, %s, %s, %s\n",
    cnt+1, a->name, a->tel, a->address );
}

またわからないことが・・・
教えて下さい。
以下をVC++2005でコンパイルすると、

MSVCRTD.lib(crtexew.obj) : error LNK2019: 未解決の外部シンボル _WinMain@16 が関数 ___tmainCRTStartup で参照されました。
C:\Documents and Settings\tomato\My Documents\Visual Studio 2005\Projects\a\Debug\a.exe : fatal error LNK1120: 外部参照 1 が未解決です。

と警告がでて通りません。
何のことでしょうか。

#include<stdio.h>
#include<process.h>

struct meibo{
  char name[20];
...続きを読む

Aベストアンサー

http://www.a.math.ryukoku.ac.jp/~hig/course/compsci2_2005/man/faq.html
にある現象と同じではないでしょうか、一度お試しください。

QC++ 構造体の一括初期化 {0}

構造体変数に {0} を代入すると、CString は空文字、 intは0に一括で初期化されるようです。
なんでこんなことが出来るのでしょう?
{0}は何?
仕組みを教えて下さい!!

Aベストアンサー

> 一括初期化関数でも作るしかなさそうですね
static変数を初期化用に用意しておくのはいかが?
http://oshiete.goo.ne.jp/qa/2658268.htmlより
>静的記憶域期間をもつオブジェクトを明示的に初期化しない場合、
>次の規定に従う。
>a) そのオブジェクトの型がポインタ型の場合、空ポインタに初期化する。
>b) そのオブジェクトの型が算術型の場合、(正または符号なしの)0に初期化する。
>c) そのオブジェクトが集成体の場合、各メンバにa)~d)の規定を(再帰的に)
>適用し初期化する。
>d) そのオブジェクトが共用体の場合、最初の名前つきメンバにa)~d)の規定を
>(再帰的に)適用し初期化する。

なので、zero初期化されていることが、規格で保証されます。

typedef struct hoge_struct
{
 int a;
 int b;
} hoge_struct;

static hoge_struct initializer; //初期化用変数。値は変えない。

int main(void)
{
 hoge_struct hoge;
 hoge = initializer;
 return 0;
}
真っ白に何度も初期化したいなら、こんな感じでどうでしょう?
関数を用意して初期化すると、構造体のメンバが増えると関数も修正しないといけない
ですが、これだと関数を変更しなくてすむし。

> 一括初期化関数でも作るしかなさそうですね
static変数を初期化用に用意しておくのはいかが?
http://oshiete.goo.ne.jp/qa/2658268.htmlより
>静的記憶域期間をもつオブジェクトを明示的に初期化しない場合、
>次の規定に従う。
>a) そのオブジェクトの型がポインタ型の場合、空ポインタに初期化する。
>b) そのオブジェクトの型が算術型の場合、(正または符号なしの)0に初期化する。
>c) そのオブジェクトが集成体の場合、各メンバにa)~d)の規定を(再帰的に)
>適用し初期化する。
>d) そのオブジェクトが共用...続きを読む

Q複数ファイルで使うグローバル変数の位置

メイン関数の処理で、関数A→関数B→関数Cという順序で関数が呼び出される場合(1関数1ファイルとします)、関数A,B,Cすべてで使用するグローバル変数の宣言を関数Bのファイルでおこなって、他のファイルではそれをexternするというのでも問題ないでしょうか?

Aベストアンサー

問題ありません。
が、しかし、そのような方法は、実務レベルの場合は、行いません。
以下のような方法をとります。

ファイル名:xxx_ext.c
変数のみを宣言したファイル。

ファイル名:xxx_ext.h
上記の変数のみを宣言したしものをexternで参照するファイル。

ファイル名:func_a.c
関数Aのファイル。
このファイルで、#include xxx_ext.h する

ファイル名:func_b.c
関数Bのファイル。
このファイルで、#include xxx_ext.h する

ファイル名:func_c.c
関数Cのファイル。
このファイルで、#include xxx_ext.h する

上記のようにすることで、externで参照する変数が1つのファイル内に閉じこめられるのでメンテナンス性がよくなります。たとえば、ある理由があって、変数Xの型をintからdoubleに変えることを想定してください。
xxx_ext.c とxxx_ext.hの2つのファイルのみが変更対象
となります。
上記のようにしない場合は、3つのファイル(あるいはそれ以上)を変えることになります。

問題ありません。
が、しかし、そのような方法は、実務レベルの場合は、行いません。
以下のような方法をとります。

ファイル名:xxx_ext.c
変数のみを宣言したファイル。

ファイル名:xxx_ext.h
上記の変数のみを宣言したしものをexternで参照するファイル。

ファイル名:func_a.c
関数Aのファイル。
このファイルで、#include xxx_ext.h する

ファイル名:func_b.c
関数Bのファイル。
このファイルで、#include xxx_ext.h する

ファイル名:func_c.c
関数Cのファイル。
このファイル...続きを読む

Qポインタのサイズ

ポインタのサイズは、

int型のポインタでも、char型のポインタでも、
doubleのポインタでも、構造体のポインタでも、
全部サイズは4バイトです。

というのを見かけましたが、ほんとうですか?
教えてください。

Aベストアンサー

PIC等のマイクロコンピュータでは、メモリモデルにより違いますが、16ビットと24ビットがポインタのサイズでした。
(参考URLをご覧下さい)

「C言語では」と聞かれると、処理系(CPU,アーキテクチャ,コンパイラ,OS)に依ってマチマチになりますし、
「これこれの処理系」と聞かれれば、こうです、と定まった答えが出ます。


C言語は高級言語の皮をかぶったアセンブラみたいなものですから、不親切に思える「なぜ、なに」がたくさん出てきます。
Cの言語仕様とライブラリAPIを超えた範囲にも目を向けて勉強していただきたいと思います。
(特にCPUとメモリ、スタックの使われ方など)

参考URL:http://ww1.microchip.com/downloads/en/DeviceDoc/51288C_JP.pdf

Q【gcc・cygwin】multiple definitionエラーの解決法

こんにちは。
C言語のプログラミングをしているのですが、
multiple definition of '関数名'と出てしまいます。

・コンパイルするファイル
program1.c(main文)
program2.c(関数)
program3.c(関数)
すべてのソースファイルが、
header.hをincludeしています。
header.hではすべての関数のプロトタイプ宣言がされています。
program2.cに書いてある関数、test()はすべてのソースファイルで使用しています。

・cygwin上で実行したコマンド
gcc -Wall program1.c program2.c program3.c -o test

・エラーの文章
(パス省略)/ccst1v2u.o:program2.c:(.text+0x0): mult
iple definition of `_test'
(パス省略)/ccyUr2Ku.o:program1.c:(.text+0x0): first defi
ned here

このような事態に陥った場合の解決方法はどのようにすればよいでしょうか?

先輩から引き継いだ、もともと一つのソースファイルに書かれていた多数の関数を、利便性のために分割したところこのようなエラーが発生しました。
先輩から引き継いだもののため、本当の関数名など細かいことをこちらに書き込めないのですが、
出来る範囲で補足いたします。
どうかよろしくお願いいたします。

こんにちは。
C言語のプログラミングをしているのですが、
multiple definition of '関数名'と出てしまいます。

・コンパイルするファイル
program1.c(main文)
program2.c(関数)
program3.c(関数)
すべてのソースファイルが、
header.hをincludeしています。
header.hではすべての関数のプロトタイプ宣言がされています。
program2.cに書いてある関数、test()はすべてのソースファイルで使用しています。

・cygwin上で実行したコマンド
gcc -Wall program1.c program2.c program3.c -o test

...続きを読む

Aベストアンサー

実際にサンプルを作って確認してみましたか?
以下、インデントに全角スペースを使っています。
ソースを公開できないということなので、アドバイスできるのはここまでです。

=======
header.h
=======
#ifndef _HEADER_H_
#define _HEADER_H_
#include <stdio.h>
#include <stdlib.h>
void test1(void);
void test2(void);
void test3(void);
#endif
=====
main.c
=====
#include "header.h"
int main(void)
{
  test1();
  test2();
  test3();
  return 0;
}
=====
test1.c
=====
#include "header.h"
void test1(void)
{
  printf("test1() called.\n");
}
=====
test2.c
=====
#include "header.h"
void test2(void)
{
  test1();
  printf("test2() called.\n");
}
=====
test3.c
=====
#include "header.h"
void test3(void)
{
  test1();
  test2();
  printf("test3() called.\n");
}

実際にサンプルを作って確認してみましたか?
以下、インデントに全角スペースを使っています。
ソースを公開できないということなので、アドバイスできるのはここまでです。

=======
header.h
=======
#ifndef _HEADER_H_
#define _HEADER_H_
#include <stdio.h>
#include <stdlib.h>
void test1(void);
void test2(void);
void test3(void);
#endif
=====
main.c
=====
#include "header.h"
int main(void)
{
  test1();
  test2();
  test3();
  return 0;
}
=====
test...続きを読む


このQ&Aを見た人がよく見るQ&A

人気Q&Aランキング

おすすめ情報