指針的概念

指針入門 ******

 int i = 123;
       //一般計算機中用16進制數(shù)來表示一個內存地址 
       printf("%#x\n",&i); 
       //int* int類型的指針變量  pointer指針  指針變量只能用來保存內存地址
       //用取地址符&i 把變量i的地址取出來 用指針變量pointer 保存了起來
       //此時我們可以說 指針pointer指向了 i的地址 
       int* pointer = &i;   
       printf("pointer的地址 = %#x\n",pointer);
       printf("*pointer的值%d\n",*pointer);
       *pointer = 456;//修改pointer的值
       printf("i的值是%d\n",i);
       system("pause"); 

由于pointer存的是i的內存地址,多以對pointer的操作就是對變量i的操作*pointer在等號左邊就是賦值操作,在等號右邊是取值操作

java zhong 兩個值的交換操作
![IJUK6LYQGDJ_2]~D10%X0.png](http://upload-images.jianshu.io/upload_images/2648920-33ec6258097a0db3.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

  • 指針常見錯誤
    • 聲明了指針變量后 未初始化直接通過*p 進行賦值操作 運行時會報錯
        • 未賦值的指針稱為野指針
    • 指針類型錯誤 如int* p 指向了double類型的地址, 通過指針進行讀取操作時,讀取值會出錯
#include<stdio.h>    
#include<stdlib.h>    
/**
*/
main(){  
         //野指針   指針使用之前要初始化 賦給它一個自己程序中聲明的變量的地址
         //指針使用的時候要注意 int類型的指針要指向int類型的內存地址, double類型的指針要指向double類型的地址 ....
          //如果亂指會出bug 
         int i; 
         double d = 3.1415;
       int* pointer = &d;
       printf("pointer的值=%#x\n",pointer);
       printf("*pointer = %d\n",*pointer);
       system("pause"); 
       } 

指針的練習

Paste_Image.png
  • 值傳遞和引用傳遞(交換兩個數(shù)的值)
    • 引用傳遞本質是把地址傳遞過去

    • 所有傳遞其實本質都是值傳遞,引用傳遞其實也是傳遞一個值,但是這個值是一個內存地址

        void swap(int* p, int* p2){
            int temp = *p;
            *p = *p2;
            *p2 = temp; 
        }
        main(){
            int i = 123;
            int j = 456;
            //將i, j的地址傳遞過去
            swap(&i,&j);
            printf("i = %d, j = %d", i, j);
        }
      
Paste_Image.png
  • 返回多個值
    • 把地址作為參數(shù)傳入函數(shù)中,當函數(shù)執(zhí)行完畢時,參數(shù)的值就已經(jīng)被修改了
#include<stdio.h>    
#include<stdlib.h>    
/**
"*" 的幾個含義   int*  聲明一個int類型的指針變量
            x * y  乘法運算
            int* pointer;
            *pointer; 取出指針變量pointer 中保存的內存地址對應的內存中的值 
*/
 function(int* pointer, int* pointer2){
     *pointer *= 2;
     *pointer2 *=2;
    }
main(){    
      int i =1;
      int j = 2;
      //char c;
      function(&i,&j);
      printf("i = %d,j = %d\n",i,j);
       system("pause"); 
       } 

多級指針

  • int* p; int 類型的一級指針 int** p2; int 類型的二級指針

  • 二級指針變量只能保存一級指針變量的地址

  • 有幾個* 就是幾級指針 int*** 三級指針

  • 通過int類型三級指針 操作int類型變量的值 ***p

          int i = 123;
          //int類型一級指針 
          int* p = &i;
          //int 類型 二級指針 二級指針只能保存一級指針的地址 
          int** p2 = &p;
          //int 類型 三級指針  三級指針只能保存二級指針的地址 
          int*** p3 = &p2;
          //通過p3 取出 i的值
          printf("***p3 = %d\n", ***p3);
    
  • 多級指針案例 取出子函數(shù)中臨時變量的地址

Paste_Image.png
#include<stdio.h>    
#include<stdlib.h>    
/**
多級指針 數(shù)星星  有幾個星就是幾級指針 取值通過三級指針拿到最初的變量的值 ***point3 
*/
main(){    
      int i = 123;
      //int類型的一級指針 
      int* pointer = &i;
      //int類型的二級指針 二級指針只能保存一級指針的地址 
      int** pointer2 = &pointer; 
      //int類型的三級指針 
      int*** pointer3 = &pointer2; 
      printf("***pointer3 = %d\n",***pointer3);
       system("pause"); 
       } 

數(shù)組和指針的關系

  • 數(shù)組占用的內存空間是連續(xù)的
  • 數(shù)組變量保存的是第0個元素地址,也就是首地址
  • *(p + 1):指針位移一個單位,一個單位是多少個字節(jié),取決于指針的類型
#include<stdio.h>    
#include<stdlib.h>    
/**
數(shù)組實際上就是一塊連續(xù)的內存空間 
*/
main(){
         
  // char array[] = {'a','b','c','d','\0'};
   int array[] = {1,2,3,4};
   printf("array[0]的地址%#x\n",&array[0]);
   printf("array[1]的地址%#x\n",&array[1]);
   printf("array[2]的地址%#x\n",&array[2]);
   printf("array[3]的地址%#x\n",&array[3]);
   printf("array的地址%#x\n",&array);
   //數(shù)組變量名的地址實際上是第一個元素的地址
   char* pointer = &array;
    //int* pointer = &array;
    char array2[] =  "hello from c"
//c語言當中的char類型的數(shù)組就是c語言當中的字符串,現(xiàn)在*pointer存的是數(shù)組的首地址,printf("%s\n",pointer2);是字符串的輸出,所以從char數(shù)組的首地址開始輸出字符串
   char* pointer2="hello from c";
   //printf("%s\n",pointer2);
   /*
   printf("*(pointer+0)=%c\n",*(pointer+0));
   printf("*(pointer+0)=%c\n",*(pointer+1));
   printf("*(pointer+0)=%c\n",*(pointer+2));
   printf("*(pointer+0)=%c\n",*(pointer+3));
   */
   printf("*(pointer+0)=%d\n",*(pointer+0));
   printf("*(pointer+1)=%d\n",*(pointer+1));
   printf("*(pointer+2)=%d\n",*(pointer+2));
   printf("*(pointer+3)=%d\n",*(pointer+3));
    
       system("pause"); 
       } 

指針的長度

  • 不管變量的類型是什么,它的內存地址的長度一定是相同的
  • 類型不同只決定變量占用的內存空間不同
  • 32位環(huán)境下,內存地址長度都是4個字節(jié),所以指針變量長度只需4個字節(jié)即可
  • 區(qū)分指針類型是為了指針位移運算方便
#include<stdio.h>    
#include<stdlib.h>    
/**
32位操作系統(tǒng)地址總線是32位   4個字節(jié)的變量來保存32位操作系統(tǒng)的內存地址 1byte 8位  4*8=32 
32位操作系統(tǒng) 指針變量占4個字節(jié)
64位操作系統(tǒng) 指針變量占8個字節(jié) 
*/
main(){    
      int* pointer;
      double* pointerD; 
      printf("int類型的指針變量占%d個字節(jié)\n",sizeof(pointer));
      printf("double類型的指針變量占%d個字節(jié)\n",sizeof(pointerD));
       system("pause"); 
       } 

#include<stdio.h>    
#include<stdlib.h>    
/**
main函數(shù)獲取子函數(shù)中臨時變量的地址 
*/
function(int** pointer){
   int i = 123;
    *pointer = &i;  
    printf("i的地址%#x\n",&i);    
          }

main(){    
      int* pointer1;
      function(&pointer1);
      printf("pointer1的值%#x\n",pointer1);
       system("pause"); 
       } 

Paste_Image.png

堆棧概念 靜態(tài)內存分配 動態(tài)內存分配

  • 棧內存
    • 系統(tǒng)自動分配
    • 系統(tǒng)自動銷毀
    • 連續(xù)的內存區(qū)域
    • 向低地址擴展
    • 大小固定
    • 棧上分配的內存稱為靜態(tài)內存
  • 靜態(tài)內存分配
  • 子函數(shù)執(zhí)行完,子函數(shù)中的所有局部變量都會被銷毀,內存釋放,但內存地址不可能被銷毀,只是地址上的值沒了



#include<stdio.h>    
#include<stdlib.h>    
/**
棧內存 系統(tǒng)統(tǒng)一分配統(tǒng)一回收  
靜態(tài)內存分配 棧內存大小固定的 內存地址是連續(xù)的 
*/
int* getData(){
     int array[] ={1,2,3,4,5};
     printf("%#x\n",&array);
     return &array;
     }
int* getData2(){
     int array[] ={5,4,3,2,1};
     printf("%#x\n",&array);
     return &array;
     }

main(){    
     int* pointer = getData();
     getData2();
     printf("%d,%d,%d\n",*(pointer+0),*(pointer+1),*(pointer+2));
     printf("%d,%d,%d\n",*(pointer+0),*(pointer+1),*(pointer+2));
     printf("%#x\n",pointer);
       system("pause"); 
       } 
  • 堆內存
    • 程序員手動分配
      • java:new
      • c:malloc
    • 空間不連續(xù)
    • 大小取決于系統(tǒng)的虛擬內存
    • C:程序員手動回收free
    • java:自動回收
    • 堆上分配的內存稱為動態(tài)內存
#include<stdio.h>    
#include<stdlib.h>    
/**
java new對象就會申請一塊堆內存
c   malloc memory allocation 內存分配 
c的堆內存 程序員手動申請手動釋放  malloc
free 
申請一塊堆內存 動態(tài)內存分配 
堆內存 不連續(xù)的 
堆內存大小不固定 取決機器的狀態(tài) 
*/
main(){ 
        //malloc 接收的參數(shù) 申請內存大小 返回一個內存地址值 申請到的也是一塊連續(xù)的內存空間   
      int* pointer = malloc(sizeof(int)*5);
      *(pointer+0) = 1;
      *(pointer+1) = 2;
      *(pointer+2) = 3;
      *(pointer+3) = 4;
      *(pointer+4) = 5;
      //C for 循環(huán) 循環(huán)的臨時變量i 要先聲明再使用 
      int i;
      for(i = 0;i<5;i++){
              printf("第%d個元素的值= %d\n",i,*(pointer+i));
              }
      free(pointer);
      printf("第一個元素的值%d\n",*(pointer+0));
       system("pause"); 
       } 

#學生管理系統(tǒng)#
#include<stdio.h>    
#include<stdlib.h>    
/**
保存班級人數(shù)
申請一塊堆內存保存學生的學號
來了幾個插班生
擴展一下堆內存
保存插班生的學號 
realloc re- 
*/
main(){ 
       printf("請輸入班級的人數(shù):");
       int count;
       scanf("%d",&count);
       //申請一塊堆內存
       int* pointer = malloc(sizeof(int)*count);
       int i;
       for(i = 0;i<count;i++){
             printf("請輸入第%d個學生的學號:",i+1);
             scanf("%d", pointer+i);
             }  
       for(i = 0;i<count;i++){
             printf("第%d個學生的學號是:%d\n",i+1,*(pointer+i));  
             } 
       printf("請輸入插班生的人數(shù):");
       //聲明一個變量increment用來保存 插班生的人數(shù) 
       int increment;
       //接受用戶的輸入 
       scanf("%d",&increment);
       //重新申請一塊足夠大的內存 
       //如果 malloc申請到的內存后面還有足夠的空間 realloc會在malloc申請的內存空間后繼續(xù)申請足夠大的內存空間
       //如果 malloc申請到的內存后面沒有足夠的空間 realloc會找到一塊足夠大的堆內存 并且把 malloc申請到的內存中的值復制過來 
      pointer = realloc(pointer,sizeof(int)*(count+increment));
      for(i = count;i<count+increment;i++){
             printf("請輸入第%d個學生的學號:",i+1);
             scanf("%d", pointer+i);
            }
      for(i = count;i<count+increment;i++){
            printf("第%d個學生的學號是:%d\n",i+1,*(pointer+i));  
            }
       system("pause"); 
       } 

結構體

  • 結構體中的屬性長度會被自動補齊,這是為了方便指針位移運算
  • 結構體中不能定義函數(shù),可以定義函數(shù)指針
  • 程序運行時,函數(shù)也是保存在內存中的,也有一個地址
  • 結構體中只能定義變量
  • 函數(shù)指針其實也是變量,它是指針變量
  • 函數(shù)指針的定義 返回值類型(*變量名)(接收的參數(shù));
  • 函數(shù)指針的賦值: 函數(shù)指針只能指向跟它返回值和接收的參數(shù)相同的函數(shù)
#include<stdio.h>    
#include<stdlib.h>    
/**
c結構體 類似java的class  struct來聲明c的結構體 
結構體的大小大于等于結構體中每一變量的占字節(jié)數(shù)的和
 結構體的大小是最大的那個變量所占字節(jié)數(shù)的整數(shù)倍 
 C結構體中不能定義函數(shù)  
 
 函數(shù)指針的定義   返回值(*函數(shù)指針變量名字)(返回值); 
 -> 間接引用運算符   
*/
void study(){
           printf("good good study!\n");
           }
typedef struct Student{
      int age;  //8
      int score;  // 4
      char sex;   //1
      void(*studypointer)();
      } stud;
main(){    
 stud stu = {18,100,'f'};
 stu.studypointer = &study;
 stu.studypointer();
 struct Student* stuPointer = &stu;//結構體指針
 printf("*stuPointer.age = %d\n",(*stuPointer).age);
 (*stuPointer).sex ='m';
 printf("stu.sex = %c\n",stu.sex);
 printf("stuPointer->age = %d",stuPointer->age);
 //printf("stu.age = %hd\n",stu.age);
 //printf("stu.score = %d\n",stu.score);
 //printf("stu.sex = %c\n",stu.sex);
// printf("結構體student占%d個字節(jié)\n",sizeof(stu));
       system("pause"); 
       } 

聯(lián)合體

  • 長度等于聯(lián)合體中定義的變量當中最長的那個
  • 聯(lián)合體只能保存一個變量的值
  • 聯(lián)合體共用同一塊內存
#include<stdio.h>    
#include<stdlib.h>    
/**
聯(lián)合體占字節(jié)數(shù)取決于 其中成員 占內存空間最大的那一個 
*/
union u{
      int num; //4
      double d; //8
      }
main(){    
   union u u1;
   u1.num = 123;
   u1.d = 123.456;
   printf("union占%d個字節(jié)\n",sizeof(u1));
   printf("u1.num = %d\n",u1.num);
       system("pause"); 
       } 

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

  • 指針是C語言中廣泛使用的一種數(shù)據(jù)類型。 運用指針編程是C語言最主要的風格之一。利用指針變量可以表示各種數(shù)據(jù)結構; ...
    朱森閱讀 3,606評論 3 44
  • 1.語言中變量的實質 要理解C指針,我認為一定要理解C中“變量”的存儲實質, 所以我就從“變量”這個東西開始講起吧...
    金巴多閱讀 1,972評論 0 9
  • 如何訪問、如何引用、如何存儲???? 問題:1、如何訪問變量?通過變量名稱來訪問變量2、如何訪問指針變量?通過指針...
    全無閱讀 835評論 0 4
  • 前言:指針是 C語言一個重要概念,也是C 語言的一個重要特色。使程序簡潔、緊湊、高效。指針乃是C之精華。 數(shù)據(jù)在內...
    瀟湘候晨雪閱讀 843評論 0 0
  • 制定目標是為了更好的指導自己的行動,而有效的行動才是成長的關鍵,它決定著我們能成為一個什么樣的人。因此,制定目標是...
    劍俠火羽閱讀 338評論 0 2

友情鏈接更多精彩內容