C語(yǔ)言學(xué)習(xí)之--容易混淆部分

第二部分C語(yǔ)言重難點(diǎn)部分的理解

一.指針

  1. 指針定義的理解

         #include<stdio.h>
         int main(void){
         
         //定義一個(gè)char類型的指針,和int類型的變量 
         char * pc;
         int num =4;
         
         //此時(shí)的含義是pc指向了num的首地址 ;
         //指針的類型決定了取值的時(shí)候訪問(wèn)多少內(nèi)存
         
         // 0000 0001 0000 0001
         // char * 獲取數(shù)據(jù), 0000 0001
         // short * 獲取數(shù)據(jù), 0000 0001 0000 0001 
         pc =  &num;
         
         
         // 指針可以參與運(yùn)算,但是僅限于+和-
         // p+1表示指針向后移動(dòng)類型單位長(zhǎng)度
         
         return 0;
     }
    
  2. 指針的用處

    1. 用函數(shù)實(shí)現(xiàn)兩個(gè)變量值的交換,注意只是交換了地址也并不能交換值,必須交換兩個(gè)地址下的值才可實(shí)現(xiàn):

       //只交換兩個(gè)變量的地址,也不能實(shí)現(xiàn)交換
       void swap2(int *px,int *py){
       
           int *ptemp;
       
           ptemp = px;
           px = py;
           py = ptemp;
       }
      
      
       //通過(guò)指針改變了兩個(gè)值的內(nèi)容,實(shí)現(xiàn)了交換
       void swap3(int *px,int *py){
       //px -->a     py---->b
       int ptemp;
      
       ptemp = *px;    // ptemp = 3;
       *px = *py;      // a = b;      a = 5,b = 5
       *py = ptemp;    // b = 3;     b = 3;
       }       
      
    2. 通過(guò)指針能夠讓函數(shù)有多個(gè)返回值----所謂的多個(gè)返回值并不是多個(gè)return,而是一次性的修改多個(gè)變量的值

        /實(shí)現(xiàn)計(jì)算器
        void calculator(int x,int y,int *psum,int *pjian,int *pcheng,float *pchu){
        
            //把x+y的結(jié)果放到主調(diào)函數(shù)中 sum變量中
            *psum = x+y;
            *pjian = x-y;
            *pcheng = x*y;
            *pchu = x/(float)y;  
        }
  1. 二級(jí)指針---其實(shí)二級(jí)指針就是指向指針的指針

         //定義一個(gè)變量
         int a = 0;
         //定義一個(gè)一級(jí)指針指向a,假設(shè)a的地址為0xf2
         int *p = &a;
         p == 0xf2;
         *p == *0xf2 == a;
         //定義一個(gè)二級(jí)指針指向p
         int* *p1 = &p;
         //此時(shí)p1的內(nèi)存單元中存放的是p的地址,假設(shè)p的地址為0xf0
         p1 == 0xf0;
         *p1 == *0xf0這個(gè)地址所指向的內(nèi)容 == 0xf2
         **p1 == **0xf0 == *0xf2 == a;
    
  2. 數(shù)組指針

    1. 指向數(shù)組元素的指針

      1. 指針pa進(jìn)行+1或-1操作時(shí)不是內(nèi)存地址的加減,而是指向下一個(gè)數(shù)組元素或上一個(gè)

      2. 同一個(gè)數(shù)組中的兩個(gè)指針相減表示的是這兩個(gè)指針之間差多少個(gè)元素

         //定義一個(gè)數(shù)組
         int a[] = {1,2,3,4,5};
         //定義一個(gè)指針指向數(shù)組a
         int *ap = a;
         //利用該指針遍歷數(shù)組a
         for (int i = 0; i < 5; i++){
             printf("a[%d] = %d\n",i,*(ap+i));
         }
        
    2. 指針變量之間的運(yùn)算

      1. 表示兩個(gè)指針之間相隔了幾個(gè)元素 ,真實(shí)地地址差:(p1-p) * sizeof(int) //12
  3. 函數(shù)指針與指針函數(shù)的區(qū)別

    1. 函數(shù)指針是返回值是指針的函數(shù); 如:char * getDay(int n){……}

    2. 指針函數(shù)是指向函數(shù)的指針;

       //格式:被指向的函數(shù)的返回值類型  (*函數(shù)指針變量名)(被指的函數(shù)的參數(shù));
       //定義了一個(gè)函數(shù)指針,指針變量名是pmax,它只能指向返回值是int 并且有兩個(gè)int類型參數(shù)的函數(shù)
       int (*pmax)(int x,int y);
       // 形參的名可以省略
       int (*pmax2)(int ,int );
      

二.程序的編譯及運(yùn)行

  1. C 語(yǔ)言程序從編寫(xiě)源代碼到運(yùn)行經(jīng)歷哪些階段?
    1. 編寫(xiě)源文件(源代碼)就是新建一個(gè)文本文件,然后編寫(xiě)C語(yǔ)言源代碼int main() {...}
    2. 編譯(cc -c 文件名)利用命令cc -c 源文件名.c編譯源文件,然后生成目標(biāo)文件"原文件名.o"該編譯過(guò)程需要檢查語(yǔ)法等內(nèi)容,該文件是二進(jìn)制格式文件但是不能執(zhí)行
    3. 鏈接(cc 目標(biāo)文件) 將目標(biāo)文件與庫(kù)函數(shù)等鏈接到一起,使得程序可以執(zhí)行使用命令:cc 目標(biāo)文件名.o會(huì)默認(rèn)生成 a.out(assembly output(來(lái)源于Unix), 表示二進(jìn)制(binary)輸出文件)cc 1.c
  2. 注意事項(xiàng):

注意:在編寫(xiě)程序,編譯的時(shí)候,如果檢查語(yǔ)法有錯(cuò)誤,就會(huì)報(bào)錯(cuò),阻止編譯繼續(xù)進(jìn)行但是函數(shù)比較特殊,如果函數(shù)調(diào)用,但是沒(méi)有提供函數(shù)的定義,那么會(huì)隱式的提供函數(shù)聲明.但是鏈接的時(shí)候,如果沒(méi)有提供函數(shù)體,那么就會(huì)報(bào)錯(cuò),阻止的鏈接的進(jìn)行,進(jìn)而不會(huì)生成可執(zhí)行文件;

三.宏的概念及無(wú)參宏定義方法

  1. 宏的定義: 宏: 預(yù)處理指令,所有的以"#" 都是預(yù)處理指令,宏是一個(gè)特殊標(biāo)識(shí)符,代表一個(gè)字符串、數(shù)字、表達(dá)式
  2. 宏的分類:
    1. 有參數(shù)的宏
    2. 無(wú)參數(shù)的宏
  3. 定義方式
    1. 無(wú)參數(shù)的宏的定義方式
      • 格式: #define 宏名 宏所代表的內(nèi)容
      • 注意:
        1. 不需要使用分號(hào)結(jié)束,宏是一個(gè)預(yù)處理指令,不是語(yǔ)句
        2. 宏的名稱一般是大寫(xiě),以便區(qū)別普通變量
        3. 宏,一般我們寫(xiě)在文件的開(kāi)頭部分
    2. 有參數(shù)的宏的定義方式
      1. 格式:#define 宏名(形參) 宏代表的字符串
           #define  M(y) y*y+3*y
           #define  SUM(a,b) a+b
    2. 使用注意事項(xiàng)
        1. 有參宏的參數(shù)不會(huì)被分配內(nèi)存空間,不需要指定類型
        2. 有參宏展開(kāi)的時(shí)候:
            1. 把實(shí)參帶入到宏的字符串中  
            2. 在出現(xiàn)宏名的地方用宏代表的字符串取替換
  1. 使用方式
    1. 宏可以參與運(yùn)算可以成為表達(dá)式的一部分
    2. 使用的注意事項(xiàng):
      1. 宏的替換 在程序編譯之前,預(yù)處理程序 會(huì)把源代碼中所有出現(xiàn)宏名的地方就用用宏代表的內(nèi)容去替換,例外:當(dāng)宏名出現(xiàn)在字符串中,此時(shí)不會(huì)替換
      2. 宏定義的時(shí)候,可以嵌套
      3. 在程序中出現(xiàn)宏名的地方,僅僅使用宏代表的值做替換
  2. 注意事項(xiàng)
    1. typedef和#define的區(qū)別

               //定義一個(gè)宏
               #define INT2 int *
               //這是給 int* 起個(gè)別名 INT
               typedef int * INT;
               
               int main(int argc, const char * argv[]) {
                   int num = 2;
                   //使用宏定義指針變量
                   INT2 p,p5;
                   // int *p,p5;
                   //p是一個(gè)指針變量
                   //p5 就是一個(gè)整形變量
      
                   //用typedef(定義)方式,定義指針變量
                   INT p1,p6;
                   //INT 原型 int *
                   //int *p1,*p6;
                   //p1 是指針變量
                   //p6也是指針變量
                   return 0;
               } 
      

四.代碼的練習(xí)

  1. 推箱子的小游戲
                #define kRows 10
        #define kCols 11
        #include<stdio.h>
        
        //定義一個(gè)函數(shù)實(shí)現(xiàn)地圖的繪制

        void drawMap(char map[kRows][kCols]) {
            for(int i = 0; i < kRows; i++){
                printf("%s\n",map[i]);
            }
        }
        
        //定義一個(gè)函數(shù)實(shí)現(xiàn)移動(dòng),當(dāng)前位置元素和下一個(gè)位置的元素互換
        void movel(char map[kRows][kCols],int oldX,int oldY,int newX,int newY){
            
            char temp;
            temp=map[oldX][oldY];
            map[oldX][oldY]=map[newX][newY];
            map[newX][newY]=temp;
        } 
        
        int main(int argc ,const char * argv[]){
            
             //1.定義二維數(shù)組,用來(lái)保存地圖
            char map[kRows][kCols]={
                "##########",
                "#O ####  #",
                "# X####  #",
                "#        #",
                "######   #",
                "#  ####  #",
                "#        #",
                "#   ######",
                "#         ",
                "##########"};
            //2.繪制地圖 
            drawMap(map);
            
            //3.提示游戲的玩法
            
            printf("請(qǐng)控制小人移動(dòng):w.上  s.下 a.左 d.右    q.推出\n");
            //4.定義一些變量,保存位置信息,保存玩家輸入的方向
            
             char direction;  //保存玩家輸入的方向
        
            // 保存用戶當(dāng)前的位置
            int personX = 1;
            int personY = 1;
            //初始化小人得下一個(gè)位置
            int nextX = personX;
            int nextY = personY;
            
             char street = ' ';
             char box = 'X';
             
              
            //保存箱子的當(dāng)前位置
            int boxX=2;
            int boxY=2;
             
             //5.編寫(xiě)循環(huán)控制程序
             
             while(1){
                //1)接受玩家輸入的方向 a\n  d\n
                 
                 scanf("%c",&direction);
                 getchar();
                 
                 //防止穿墻
                 
                 nextX=personX;
                 nextY=personY;
                 
                 //2)根據(jù)玩家輸入的方向,判斷將要移動(dòng)的方向
                 
                 switch(direction){
                    case 'w':
                    case 'W':
                        //記錄小人的下一個(gè)位置
                         nextX--;
                         break;
                    case 's':
                    case 'S':
                        //記錄小人的下一個(gè)位置
                         nextX++;
                         break;
                    case 'a':
                    case 'A':
                        //記錄小人的下一個(gè)位置
                         nextY--;
                         break;
                    case 'd':
                    case 'D':
                        //記錄小人的下一個(gè)位置
                         nextY++;
                         break;
                         
                    case 'q':
                    case 'Q':
                        printf("程序正在退出...\n");
                        printf("程序已經(jīng)退出...\n");
                        return 0;
                        
                    default:
                        break;
                 } 
                 
                 
                 // 3)判斷小人的將要移動(dòng)的位置是否是路
                 
                 if(map[nextX][nextY]==street){
                    
                    //如果是路,讓小人移動(dòng)
                     movel(map,personX,personY,nextX,nextY);
                     //重新保存小人的最新位置
                     
                     personX=nextX;
                     personY=nextY;
                 } else if(map[nextX][nextY]==box){
                 
                 
                //   再判斷小人的下一個(gè)位置是否是箱子
                //   如果是箱子:
                //        1) 計(jì)算箱子的下一個(gè)位置
                    int boxNextX = boxX+(boxX-personX);
                    int boxNextY = boxY+(boxY-personY);
                //        2)  再判斷 箱子的下一個(gè)位置是否是路
                 if (map[boxNextX][boxNextY] == street) {
        
                // 如果是路:
                //   1)箱子和箱子下一個(gè)位置交換
                        movel(map, boxX, boxY, boxNextX, boxNextY);
                //  2)小人和箱子的位置進(jìn)行交換
                        movel(map, personX, personY, boxX, boxY);
                //  3)重新保存小人的位置,箱子的位置
                        boxX = boxNextX;
                        boxY = boxNextY;
        
                        personX = nextX;
                        personY = nextY;
        
                    }
                 
                
                 }
                 
                 drawMap(map);
                 if(boxY==9){
                    printf("哇哦啊,你推出來(lái)!");
                     break;
                 }
             } 
            
            
        }
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 指針是C語(yǔ)言中廣泛使用的一種數(shù)據(jù)類型。 運(yùn)用指針編程是C語(yǔ)言最主要的風(fēng)格之一。利用指針變量可以表示各種數(shù)據(jù)結(jié)構(gòu); ...
    朱森閱讀 3,618評(píng)論 3 44
  • 一、框架 1、Mac系統(tǒng)及常用工具、進(jìn)制;C數(shù)據(jù)類型、常量變量、運(yùn)算符、表達(dá)式、格式化輸入輸出 2、關(guān)系運(yùn)算符、邏...
    師景福閱讀 850評(píng)論 0 2
  • 推薦指數(shù):???????? 推薦理由:有收縮毛孔的作用,我一般拿來(lái)濕敷,平時(shí)放冰箱里,濕敷時(shí)那酸爽~感覺(jué)毛孔都閉合...
    Swing阿姨閱讀 555評(píng)論 0 7
  • 1.1 JSON簡(jiǎn)單介紹001 什么是JSON(1)JSON是一種輕量級(jí)的數(shù)據(jù)格式,一般用于數(shù)據(jù)交互(2)服務(wù)器返...
    年輕在于折騰閱讀 516評(píng)論 1 3

友情鏈接更多精彩內(nèi)容