【c語言基礎】關於指針和變量的思考

/**!
   2018年1月30日14:18:00
   Author: xiyuan255
   Purpose: c語言基礎
*/

/**(1) 函數類型強制轉換示例代碼***start***/
void SelectMainFrame( char tmf )
{ 
   assert( (tmf==0x01) || (tmf==0x02) );
   if (0x01 == tmf) {
      // execute to AfMain1 frame
   } else if (0x02 == tmf) {
      // execute to AfMain2 frame
   }
}

void AfMain( void( *MainFrameFunc )(void) )
{
   char tmf = 0x01;   
   
   if ( MainFrameFunc != NULL ) {
   	  /* 該語句的含義是將MainFrameFunc函數強制轉換爲返回值爲void
   	   * 形參爲char型的函數,然後將tmf作爲它的實參,傳遞給該函數 */
      ( (void ( * )(char) )MainFrameFunc )( tmf );
   }
}

int main( void )
{
 /* (void( * )(void)) SelectMainFrame 的含義是將SelectMainFrame
   * 函數的類型轉換爲返回值爲void,形參爲void的類型,然後作爲實參
   * 傳遞給AfMain函數 */
   AfMain( (void( * )(void))SelectMainFrame ); 
   /* 同理,該語句同上, 其中pNode是一個鏈表節點指針而已 */
   (( void( * )(int*, int) )pNode->function)(buffer, length);
   
   return 0;
}
/**(1) 函數類型強制轉換示例代碼***end***/


/**(2) 指針與變量的解析***start***/
typedef void (*fun3)(int a, int b);

void fun2(int a, int b);

int main(void) 
{
   while(1) {
      int i = 0;     // 在c語言中定義變量i並賦值,其實等價與彙編中的直接尋址;
      int* p = NULL; // 在c語言中定義指針變量p,其實等價與彙編中的間接尋址;
      /* 解釋: 當我們定義一個指針變量p和變量i時,其實是向操作系統申請兩塊內存單元來使用,
		     即我們能夠對所申請的內存單元進行讀寫使用。一塊內存單元的別名叫做i,一塊內存單元
		     的別名叫做p。而i所代表的內存單元裏面存放的是數據,且是int類型的數據。而p所代表的
		     內存單元裏面存放的是地址,且是int類型數據的地址。 */
		     
		  fun3 q = fun2; 
      /** 解釋:typedef void (*fun3)(int a, int b);的含義是:定義的一種類型,叫做fun3類型,
         該類型是void X(int a, int b)這種類型函數的指針。即用fun3定義的變量q存放的是這種
      void fun2(int a, int b)函數的地址。 */
   }
   
   return 0;
}

/**
   C語言中的變量分爲指針變量和常規變量,它其實等價於內存中的某一塊存儲單元:
   (1) 指針變量,通常我們簡稱爲指針。它與常規變量最大的不同點在於,它所代表的內存單元
       存放的是地址類型,即void*類型(由於void*可以接收所以類型的指針,所以這裏用它代表
       所有的指針類型)。它的存在可以實現彙編中的間接尋址功能。
   (2) 常規變量,通常我們簡稱爲變量。它所代表的內存單元存放的是數據類型,即int、char和
       short等類型。它的存在可以實現彙編中的直接尋址功能。
   總結: 我們的所有面向對象或面向過程的語言,主要研究的就是對內存的使用,即物理內存條;
     當我們定義一個變量i,其實是向操作系統申請一塊內存單元來使用,即我們能夠對所申請的
     內存單元進行讀寫使用;而該內存單元所對應的首地址就是變量i,即該首地址的另外一個名
     稱叫做i(原因程序員不可能記住每個物理的具體地址,而且操作系統不允許軟件直接對硬件
     操作,內存分配統一由操作系統管轄);
   (3) 函數指針的說明:C語言函數指針與此類似,函數名即變量名,當我們完成一個一個函數的
       定義,該函數的方法就將在內存中的某塊區域存放,該區域的地址用函數名錶示。
       而 int(*fun)( ) —— fun是一個指針,它指向一個沒有形式參數的函數,這函數返回一個int值.
          int* fun()——fun是個函數,它沒有形式參數,返回一個int *型指針。
*/
/**(2) 指針與變量的解析***end***/


/**(3) 字節對齊的示例***start***/
		/**
		  字節對齊的注意點:在32位操作系統上,默認是按4 bytes對齊。
			* (1) 基本類型對齊,即char按一個字節對齊,short按兩個字節對齊,int按4個,float按4個和
			      double按8個。所爲的對齊就是存放的地址能被類似所佔的字節數整除。
			* (2) 結構體類型對齊,是按結構體成員中佔最大字節數的那個成員的字節數來對齊的。
		*/
		typedef struct {
			  /* 枚舉類型按int類型來存放,即4 bytes */
			  NetvoxAfReportingDirection_e direction;  // 0000H~0003H  4 BYTES
			  char endpoint;                           // 0004H  1 BYTES
			                                           // 0005H  // 補零
			  unsigned short clusterId;                // 0006H~0007H  2 BYTES
			  unsigned short attributeId;              // 0008H~0009H  2 BYTES
			  char mask;                               // 000AH  1 BYTES
			                                           // 000BH  // 補零
			  unsigned short manufacturerCode;         // 000CH~000DH  2 BYTES
			  union {                                  // reported和received是共用體data的兩個成員,共用體取成
				                                       // 員所佔字節總數最大的作爲共用體data所佔的字節數即本例
				                                       // 中 reported:8 bytes > received:6 bytes 取8個字節。
				                                       // 且對結構體/共用體拆分,則該結構體的中佔字節數最多的是
				                                       // reportableChange:4 bytes。所以對齊data需從:0010H~0017H。
				                                       // 其中000EH~000FH都補零原因在於000EH~000FH不能被4整除,
				                                       // 0010H可以被4整除,所以從該地址開始存放。
					struct {
					  unsigned short minInterval;    // 2 BYTES
					  unsigned short maxInterval;    // 2 BYTES // 共8個字節,8能被結構體reported(4bytes:最大字節數)整除,
					  unsigned int reportableChange; // 4 BYTES // 所以結構體對齊後就是8個字節
					} reported;
					struct {
					  unsigned short source;  // 2 BYTES 
					  char endpoint;          // 1 BYTES // 共5個字節,5不能被結構體received(2bytes:最大字節數)整除,
					  unsigned short timeout; // 2 BYTES // 所以補一個字節,即結構體對齊後是6個字節
					} received;
			  } data;  
		} NetvoxAfReportingEntry_t; // 0017H-0000H+1 = 24byte 因24byte可以被最大成員4byte對齊,所以不需要給結構體
		                            // 對齊補零,所以24byes即爲最終所佔的字節數

		cout << "\nsizeof(NetvoxAfReportingEntry_t): " << sizeof(NetvoxAfReportingEntry_t) << endl;  // 24 bytes


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章