__xとか¥記号とか宣言していないものも多く、皆目見当がつきません。
- `ast_test_flag`関数は、ソースコード中の`flags`フィールドの特定のフラグがセットされているかどうかをチェックするために使用されます。
- この関数の内部では、`flags`フィールドの値を一時変数`__p`に保存し、`__x`というダミー変数を使用して`__p`と`__x`の型が一致しているかどうかをチェックします。
- その後、`(p)->flags`と`flag`の論理積を計算し、特定のフラグがセットされているかどうかを判定します。
- ベストアンサー
解説をお願いします。
#define ast_test_flag(p,flag) ({ \ typeof ((p)->flags) __p = (p)->flags; \ typeof (__unsigned_int_flags_dummy) __x = 0; \ (void) (&__p == &__x); \ ((p)->flags & (flag)); \ }) あるソースコードを読んでいると上のような記述に当たりました。 何をしているのか解説していただけませんか。 __xとか¥記号とか宣言していないものも多く、皆目見当がつきません。
- C・C++・C#
- 回答数5
- ありがとう数4
- みんなの回答 (5)
- 専門家の回答
質問者が選んだベストアンサー
p->flags は恐らく複数のフラグを保持するビット列です。 パラメータ flag は、ビット列からフラグを抽出するためのビットマスクでしょう。 2~4行目は置いておいて、 5行目のビット演算、p->flags と flag の AND が、 最終的にこのマクロ全体の結果値となります。 すなわち p->flags に flag で指定したビットが 立っているか否かを返すためのコードであると考えられます。 2~4行目ですが、 p->flags と同じ型のコピー __p を用意し、 次に __unsigned_int_flags_dummy と同じ型の __x を用意します。 これらのアドレスを比較し、その結果を捨てています。 p->flags が __unsigned_int_flags_dummy と同じ型で定義されているかを コンパイル時にチェックするためのコードだと思われます。 p->flags が __unsigned_int_flags_dummy と異なる型を持つ場合、 コンパイル時に「型が違うポインタの比較」に関するエラーが出ます。 同じ型であれば、無意味なコードとなります。 (コンパイラの最適化により無視される可能性が高いです)。 何らかの理由で p->flags が想定外の型で定義されているケースを コンパイル時に検出する必要があるのでしょう。 typeof は GCC Extension です。
その他の回答 (4)
- wormhole
- ベストアンサー率28% (1619/5653)
>・(p)->flagsとはなんでしょうか?どこでも宣言してない マクロなので、そこだけ見て判断しないでくださいな。 マクロ ast_test_flag(p,flag) は、第1引数にflagsというメンバを 持つ構造体のポインタがくることを仮定してるんです。 typedef struct { unsigned int flags; } Foo; int bar(Foo *fooPtr) { if (ast_test_flag(fooPtr, 1)) { ~ } ~ }
お礼
解答ありがとうございました。
- Tacosan
- ベストアンサー率23% (3656/15482)
これがどこから出てきたもので「なぜ内容を理解しなければならないのか」が皆目見当もつかないのだが, こういうのはたいてい これで何ができるのか を把握できれば十分. こんな古いソースに現時点でどれほどの価値があるかは知らんが....
お礼
解答ありがとうございます。 オープンソースを追っているときに出てきました。
- TT414
- ベストアンサー率18% (72/384)
>調べてみたのですが、私のCの本には書いていません。 当然です、C言語にはtypeofはありません。 ≻(p)->flags & (flag) ≻・単にビット積をとるだけならなぜ(p)&(flags)と書かないのでしょうか? 「(p)->flags & (flag)」と「(p)&(flags)」は違います。
- wormhole
- ベストアンサー率28% (1619/5653)
この場合の行末の \ は「次の行に続く。」という意味です。 なので #define ast_test_flag(p,flag) ({ typeof ((p)->flags) __p = (p)->flags; typeof (__unsigned_int_flags_dummy) __x = 0; (void) (&__p == &__x); ((p)->flags & (flag)); }) と同じ。 >typeof ((p)->flags) __p = (p)->flags; \ >typeof (__unsigned_int_flags_dummy) __x = 0; \ >(void) (&__p == &__x); \ この3行はやってることに意味ないので省略 (概略だと__pという変数と__xという変数を定義してそれらのアドレスが等しいか調べ結果は捨てる) 最終的には #define ast_test_flat(p,flag) ((p)->flags & (flag)) かな。
お礼
丁寧な解答ありがとうございます。 重ねて質問なのですが、 ・typeof とは何を行っているのでしょうか。 ・(p)->flagsとはなんでしょうか?どこでも宣言してない ・単にビット積をとるだけならなぜ(p)&(flags)と書かないのでしょうか? 調べてみたのですが、私のCの本には書いていません。 どなたか教えてくれませんか?
関連するQ&A
- #defineについて
#define STATIC_ASSERT(expr) { \ char __STATIC_ASSERTION[(expr) ? 1 : -1]; \ (void)__STATIC_ASSERTION; \ } /* 符号付き整数の右シフトが算術シフトかどうか */ #define SHIFT_LEFT_SINGNED_USES_SAL \ (((signed int)0xffffffff >> 1) == 0xffffffff) /* 符号無し整数の右シフトが論理シフトかどうか */ #define SHIFT_LEFT_UNSIGNED_USES_SHL \ (((unsigned int)0xffffffff >> 1) == 0x7fffffff) とは一体どういう意味なのでしょうか? なぜ、ブロックの中にchar型が宣言されているのでしょうか? なぜ、(void)とキャストされているのでしょうか? できたらわかりやすくご教授よろしくお願いします。
- ベストアンサー
- C・C++・C#
- PIC12F683を用いたCapture実験
いま、PIC12F683を用いてCCPモジュールのCapture機能の実験をしています。一応、ビルドはできたので書き込んで動かしてみましたが、思ったとおり(スイッチを押したときにLEDを点灯させる)に動作しませんでした 動作はとしては、押しボタンスイッチを押したときにキャプチャーして LEDを点灯させるという簡単なものです。 下に使用しているプログラムを掲載しますので、どうしたらいいか教えてください。 // CaptureTest.c #include <pic.h> #include "delay.h" #include "CCP.h" __CONFIG( FCMDIS & IESODIS & BORDIS & WDTDIS & UNPROTECT & UNPROTECT & MCLRDIS & PWRTEN & INTIO); __IDLOC(0x00); unsigned char temp; ioport(); main(void) { //ポートの初期化、入出力設定など ioport(); //Captureモード、立ち上がりエッジに設定 setCcpMode(CCP_CAPUTURE_PGE); //フラグ(CCP1IF)を「0」にセット ResetCcpFlag(); //CCP割り込み許可 setCcpEnable(ENABLED); //TIMER1のプリスケーラを「1/8」に設定 T1CKPS1=1; T1CKPS0=1; //外部回路を動作させない T1OSCEN=0; //TIMER1を同期モードにセット T1SYNC=0; //TIMER1のクロックは内部クロックを使用 TMR1CS=0; //全割り込み、周辺割り込み許可 GIE=1; PEIE=1; //TIMER1をリセット(0セット) ResetTMR1(); //TIMER1スタート T1_START(); //CCP割り込みフラグが立つまでチェック while(ChkCcpFlag()==0); //CCP割り込みフラグクリア ResetCcpFlag(); //GP3をハイレベルに設定してLEDを点灯 temp=1; GPIO3=temp; } ioport() { ANSEL=0x00; TRISIO=0x04; } //CCP.c #include <pic.h> void setCcpMode(unsigned char mode) { CCP1CON= mode; } void setPwmPeriod(unsigned char T) { PR2=(T-1); } void setPwmDuty(unsigned int duty) { DC1B0 = 0x01&duty; DC1B1 = 0x02&duty; CCPR1L = 0xFC &duty; } void setCcpEnable(unsigned char flag) { CCP1IE=flag; } void ResetCcpFlag(void) { CCP1IF=0; } unsigned char ChkCcpFlag(void) { unsigned char ret=0; if(CCP1IF==1) return ret=1; return ret; } void ResetTMR1(void) { TMR1H=0x00; TMR1L=0x00; } void T1_START(void) { TMR1ON=1; } void T1_STOP(void) { TMR1ON=0; } //CCP.h #define ENABLED 1 #define DISABLED 0 #define CCP_OFF 0x00 #define CCP_CAPUTURE_NGE 0x04 #define CCP_CAPUTURE_PGE 0x05 #define CCP_CAPUTURE_4th_PGE 0x06 #define CCP_CAPUTURE_16th_PGE 0x07 #define CCP_COMPARE_SET_ON_MATCH 0x08 #define CCP_COMPARE_CLR_ON_MATCH 0x09 #define CCP_COMPARE_INT 0x0A #define CCP_COMPARE_RESET_TIMER 0x0B #define CCP_PWM 0x0C extern void setCcpMode(unsigned char); extern void setPwmPeriod(unsigned char); extern void setPwmDuty(unsigned int); extern void setCcpEnable(unsigned char); extern void ResetCcpFlag(void); extern unsigned char ChkCcpFlag(void); extern void ResetTMR1(void); extern void T1_START(void); extern void T1_STOP(void);
- 締切済み
- その他(プログラミング・開発)
- secが・・確認お願いできませんか?
秒数が出ないのですがどこが違うのでしょうか? #define TCNT0 (*(volatile unsigned int *)0xffff68) #define GRA0 (*(volatile unsigned int *)0xffff6a) #define GRB0 (*(volatile unsigned int *)0xffff6c) #define TCR0 (*(volatile unsigned char *)0xffff64) #define TIOR0 (*(volatile unsigned char *)0xffff65) #define TIER0 (*(volatile unsigned char *)0xffff66) #define TSR0 (*(volatile unsigned char *)0xffff67) #define TSTR (*(volatile unsigned char *)0xffff60) #define ITU_CLOCK8 3 #define ITU_CLEAR_GRA 32 #define ITU_IE_IMFA 1 #define DI asm( "orc.b #0xc0,ccr" ) #define EI asm( "andc.b #0x3f,ccr" ) void start_itu0(); void int_imia0(void) __attribute__ ((interrupt_handler)); int cnt = 0, sec = 0, min = 0, hour = 0; char str[] = "timer 00:00:00"; int main(void) { lcd_init(); lcd_puts(str); start_itu0(); EI; for(;;) { if (cnt >=100) { cnt = 0; sec++; if (sec >=60) { sec = 0; min++; if (min >= 60) { min = 0; hour++; if (hour >= 24) hour = 0; } str[6] = '0' + hour /10; str[7] = '0' + hour %10; str[9] = '0' + min /10; str[10] = '0' + min %10; str[12] = '0' + sec /10; str[13] = '0' + sec %10; lcd_home(); lcd_puts(str); } } } return 0; }
- ベストアンサー
- C・C++・C#
- H8 外部バスのデータアクセス
H8 外部バスのデータアクセス ルネサスのH8マイコン初心者です。(C言語も初心者です) 外部バスのCS1(0x200000)に512KBのSRAMが繋がっているのですが、 HEWのセクションを変更せず、直接SRAMに対して読み書きしたいと思っています。 バスコントローラは設定済みという前提で以下の(A)~(C)のように 宣言すればデータの読み書きは出来ると思うのですが、 (A)~(C)を配列や構造体として扱いたい場合、どのように宣言すれば 良いのでしょうか? (A) #define SRAM1 (*(volatile unsigned int*)(0x200000)) (B) #define SRAM2 (*(volatile unsigned int*)(0x200002)) (C) #define SRAM3 (*(volatile unsigned int*)(0x200004)) (D) SRAM1 = 1; (E) SRAM2 = 2; (F) SRAM2 = 3; よろしくお願いします。
- ベストアンサー
- その他(プログラミング・開発)
- 【C言語】別関数でポインタの値を変えたのに変わらない。
【C言語】別関数でポインタの値を変えたのに変わらない。 メイン関数のポインタの値を、別関数で書き換えるプログラムを作りました。 以下がそのプログラムになります。 そのままだと、ダブルポインタを操作する必要があるので分かり辛いです。なので、ダブルポインタをシングルポインタにしてからポインタの書き換えを行うようにしました。その結果、きちんとポインタの書き換えが出来なくなってしまいました。 なぜ出来なくなってしまったのでしょうか。 2つのプログラムの違いは、 > *pp = &dummy; が > p = *pp; // ダブルポインタをシングルポインタにした > p = &dummy; に変わっただけです。 【参考】http://www.kouno.jp/home/c_faq/c4.html#8 -----------------正しいプログラム---------------- // 以下プログラムは、正しく動作する // 実行結果は、 // p = 5 // と表示される void func( int **pp ); int main (void){ int *p; int a = 0; p = &a; func( &p ); printf("p = %d\n", *p); return 0; } void func( int **pp ){ static int dummy = 5; *pp = &dummy; } ---------------------------------------------- -----------------間違いプログラム---------------- // 以下プログラムは、正しく動作しない // 実行結果は、 // p = 0 // と表示される void func( int **pp ); int main (void){ int *p; int a = 0; p = &a; func( &p ); printf("p = %d\n", *p); return 0; } void func( int **pp ){ static int dummy = 5; int *p; p = *pp; // ダブルポインタをシングルポインタにした p = &dummy; } ----------------------------------------
- 締切済み
- C・C++・C#
- 構造体ポインタ、及び、戻り値のあるマクロ関数の作成方法について
●開発環境 [OS] Linux 2.6.9 [コンパイラ] GCC 3.4.6 ●質問 以下のプログラム中のTEST関数を、 マクロ関数(#define)にしたいのですが、 やり方がわかりません。 ご存知の方がいらっしゃいましたら、ご教授願います。 -------------------------------- #include <stdio.h> typedef struct t_str_abc { unsigned int x; unsigned int y; } str_abc; unsigned int TEST( str_abc *kou ); void main(void) { str_abc kouzou; unsigned int ret; kouzou.x = 1; kouzou.y = 2; ret = TEST(&kouzou); printf("ret = %d\n", ret); } unsigned int TEST( str_abc *kou ) { unsigned int state; state = kou->x + kou->y; return state; } --------------------------------
- ベストアンサー
- Linux系OS
- USART通信で文字化け
__CONFIG( WDTDIS & UNPROTECT & BORDIS & MCLRDIS & PWRTEN & HS & LVPDIS ); // // test.c 2009/07/30 HI-TECH C Compiler // プリスケーラ1/256 セラミック発振子10MHz使用 1命令当り102us // unsigned char buff[10]; unsigned int RecCnt=0; main(){ /*Port initalizeなど .................... */ RCSTA = 0x90; TXSTA = 0x24; SPBRG = 0x40; //BaudRate 9600 FOCS 10MHz unsigned int i; while(1){ putch('A'); for(i=0; i<60000; i++); putch('K'); for(i=0; i<60000; i++); } } ヘッダーファイル #ifndef _SERIAL_H_ #define _SERIAL_H_ #define BAUD 9600 #define FOSC 10000000L #define NINE 0 // Use 9bit communication? FALSE=8bit #define DIVIDER ((int)(FOSC/(16UL * BAUD) -1)) #define HIGH_SPEED 1 #if HIGH_SPEED == 1 #define SPEED 0x04 #else #define SPEED 0 #endif #define RX_PIN TRISB1 #define TX_PIN TRISB2 /* Serial initialization */ #define init_comms()\ RX_PIN = 1; \ TX_PIN = 1; \ SPBRG = DIVIDER; \ RCSTA = (NINE_BITS|0x90); \ TXSTA = (SPEED|NINE_BITS|0x20) void putch(unsigned char); unsigned char getch(void); unsigned char getche(void); #endif void putch(unsigned char byte) { unsigned int i; /* output one byte */ while(!TXIF) /* set when register is empty */ continue; TXREG = byte; } unsigned char getch() { /* retrieve one byte */ while(!RCIF) /* set when register is not empty */ continue; return RCREG; } 上記が自分で作成したUSART通信を使用したプログラムです。AとKを送信しています。ですがハイパーターミナルで受信した文字列を見てみるとまったく異なる文字や空白など文字化けをしていました。 前に作成した時は正常に表示されたのですが、今また流用してみると文字化けしていました。 発振子に10MHz使用でBRGH=1(高速)と9600bps→SPBRG=0x40 原因はここだと思うのですが、、、謎です。 丸投げな感じですが、どうか分かる方回答をお願いします。
- ベストアンサー
- C・C++・C#
- debugエラーについて
VisualC++初心者です。 力を貸してください。 内容はDEBUG ERRORで Stack around the variable "rp" was corrupted Stack around the variable "res" was corrupted とでてしまいます。 構造体等は省略しました。 #include <stdio.h> #include <stdlib.h> #define N 8 typedef struct{ int maxi,maxj,akarusa[N][N]; unsigned char *data; }RESULT; int bunkatsu(BMP *rp,BMP *wp); int keisan(BMP *rp,BMP *wp); RESULT *max(RESULT *res); /* 画像の取込 */ int ReadHeader(BMP *p,FILE *fp){ unsigned int size; fseek(fp, 0, SEEK_END); size = ftell(fp); fseek(fp, 0, SEEK_SET); fread(&p->Bmpf.bfType, sizeof(unsigned short), 1, fp); fclose(fp); exit(1); } fread(省略) return 0; } int ReadBmp(BMP *p,FILE *fp){ int dummy, byte, i, j, pixel; unsigned char *ReadBody=0; ReadHeader(p,fp); byte = p->Bmpi.biBitCount/8; dummy = (p->Bmpi.biWidth%4)?(4-(p->Bmpi.biWidth*byte)%4) : 0; pixel = ((p->Bmpi.biWidth)*byte+dummy)*p->Bmpi.biHeight; ReadBody = (unsigned char*)calloc(pixel,sizeof(char)); p->body = (unsigned char*)calloc(pixel,sizeof(char)); p->blue = (unsigned char*)calloc((pixel/byte),sizeof(char)); p->green = (unsigned char*)calloc((pixel/byte),sizeof(char)); p->red = (unsigned char*)calloc((pixel/byte),sizeof(char)); fread(ReadBody,1,pixel,fp); if(p->Bmpi.biBitCount == 8){ printf("\n"); for(j=0;j<p->Bmpi.biHeight;j++){ for(i=0;i<p->Bmpi.biWidth;i++){ p->blue[(p->Bmpi.biWidth+dummy)*j+i] =p->Rgbq[ReadBody[(p->Bmpi.biWidth+dummy)*j+i]].rgbBlue; p->green[(p->Bmpi.biWidth+dummy)*j+i] =p->Rgbq[ReadBody[(p->Bmpi.biWidth+dummy)*j+i]].rgbGreen; p->red[(p->Bmpi.biWidth+dummy)*j+i] =p->Rgbq[ReadBody[(p->Bmpi.biWidth+dummy)*j+i]].rgbRed; } } for(j=0;j<p->Bmpi.biHeight;j++){ for(i=0;i<p->Bmpi.biWidth;i++){ p->body[(p->Bmpi.biWidth+dummy)*j+i]=ReadBody[(p->Bmpi.biWidth+dummy)*(p->Bmpi.biHeight-1-j)+i]; } } } else if(p->Bmpi.biBitCount == 24 || p->Bmpi.biBitCount == 32){ for(j=0;j<p->Bmpi.biHeight;j++){ for(i=0;i<p->Bmpi.biWidth;i++){ p->blue[(p->Bmpi.biWidth+dummy)*j+i] = ReadBody[(p->Bmpi.biWidth+dummy)*(p->Bmpi.biHeight-1-j)*byte+i*byte]; p->green[(p->Bmpi.biWidth+dummy)*j+i] = ReadBody[(p->Bmpi.biWidth+dummy)*(p->Bmpi.biHeight-1-j)*byte+i*byte+1]; p->red[(p->Bmpi.biWidth + dummy)*j+i] = ReadBody[(p->Bmpi.biWidth+dummy)*(p->Bmpi.biHeight-1-j)*byte+i*byte+2]; } } } else{ printf("失敗\n"); exit(1); } free(ReadBody); return 0; } /* 480×480にする */ int bunkatsu(BMP *rp,RESULT *res){ int x,y,a=0; for(y=0;y<rp->Bmpi.biHeight;y++){ for(x=79;x<rp->Bmpi.biWidth-80;x++){ res->data[a] = rp->blue[y*rp->Bmpi.biWidth+x]+rp->green[y* rp->Bmpi.biWidth+x]+rp->red[y*rp->Bmpi.biWidth+x]; a++; } } return 0; } /* ブロック分けして各ブロックの明るさを計算する */ int keisan(BMP *rp,RESULT *res){ int b,c,x,y,i=0,j=0; for(y=0;(y+60)<rp->Bmpi.biHeight;y+=60){ for(x=0;(x+60)<(rp->Bmpi.biWidth-160);x+=60){ for(b=0;b<60;b++){ for(c=0;c<60;c++){ res->akarusa[i][j]+=res->data[(y+b)*rp->Bmpi.biWidth+(x+c)]; } } j++; } i++; } max(res); return 0; } /* 一番明るいブロックの特定 */ RESULT *max(RESULT *res){ int MAX1=0,MAX2=0,i=0,j=0; for(i=0;i<8;i++){ for(j=0;j<8;j++){ printf("[%d][%d]=%d",i+1,j+1,res->akarusa[i][j]); if(MAX1<res->akarusa[i][j]){ MAX1=res->akarusa[i][j]; res->maxi=i; res->maxj=j; } } printf("\n"); } printf("一番明るいブロックは[%d][%d]です\n",res->maxi+1,res->maxj+1); return 0; } int main(void){ BMP rp={0}; RESULT res={0}; FILE *fp; /* 画像の取り込み */ fp=fopen("LED1.bmp","rb"); ReadBmp(&rp,fp); res.data = (unsigned char*)calloc(rp.Bmpi.biWidth*rp.Bmpi.biHeight,sizeof(char)); fclose(fp); fp=0; bunkatsu(&rp,&res); keisan(&rp,&res); return 0; } です。よろしくお願いします。
- ベストアンサー
- C・C++・C#
- 二分法のプログラム
関数x^3-7x^2-6x+2を二分法で解くプログラムを作ったのですが、エラーが出てコンパイルできません。訂正箇所を教えて下さい。 宜しくお願い致します。 #include<stdio.h> #include<math.h> #define EPSILON 0.1E-5 #define TURE 1 #define FALSE 0 int kansu(int x); void Nibunho(left,right,sol,flag); double left,right; int flag; int main(void) { printf("区間の左端と右端は?\n"); scanf("%lf %lf",&left,&right); flag=FALSE; Nibunho(left,right,&root,&flag); if(flag) printf("解 = %e (繰り返し回数 = %d)\n",root,k); else { printf("入力した範囲で解は求まりませんでした。\n"); printf("f(%e) = %e \n",root,k); } return 0; } int kansu(int x) { int f(double x) f(x)=x*x*x-7.0*x*x-6.0*x+2.0; return(f(x)); } void Nibunho(left,right,sol,flag) { double left,right,*sol; int *flag; double a,b,c,fa,fb,fc; k=0; a=left; b=right; do { k++; c=(a+b)/2.0; fc=f(c); fa=f(a); fb=f(b); if(fabs(fc)<1.0e-10) { a=c; b=c; *flag=TRUE; } else { if( (fa * fc < 0.0) || (fb * fc < 0.0) ) { *flag = TRUE; if( (fa*fc) < 0.0 ) b=c; else a=c; } else { if( fabs(fa) > fabs(fb) ) a=c; else b=c; } } } while((b-a)>EPSILON) *sol=(a+b)/2.0; }
- 締切済み
- C・C++・C#
- フローチャートについて
H8マイコンでスイッチS1(PORT4-4)が押された場合は、LED1(PORT5-0)、スイッチS2(PORT4-5)が押された場合は、LED2(PORT5-1)、スイッチS3(PORT4-6)が押された場合は、LED3(PORT5-2)、スイッチS4(PORT4-7)が押された場合は、LED4(PORT5-3)が、それぞれ点灯するようなプログラムをつくりました。 #define P4DDR (* (volatile unsigned char *) 0xfffc5) #define P4DR (* (volatile unsigned char *) 0xfffc7) #define P4PCR (* (volatile unsigned char *) 0xfffda) #define P5DDR (* (volatile unsigned char *) 0xfffc8) #define P5DR (* (volatile unsigned char *) 0xfffca) int main(void) { unsigned char sw,ssw; P4DDR = 0x00; /* P4全ビットを入力に設定 */ P4PCR = 0xff; /* P4 MOSプルアップをONにする */ P5DDR = 0xff; /* P5全ビットを出力に設定 */ while (1) { sw = ~P4DR; /* 入力を反転 */ ssw = sw >> 4; /* swを4ビット右にシフトしたものをsswに代入 */ P5DR = ssw; /* sswをP5に出力 */ } return 0; } というプログラムを作ったのですが、フローチャートがどのようになるのかがわからないです。またプログラムが間違っていたら教えてください。
- ベストアンサー
- C・C++・C#
お礼
丁寧な解答ありがとうございました。