【C語言】07-指針

此筆記由個人整理

塞上蒼鷹_fly

課程來自:尚觀C語言

一、指針基礎知識

變量與地址的關係

  • 變量名:是用戶對某一個內存空間的抽象表示
  • 地址:固定不變的值,不會因爲變量名的改變而改變。等價於指針

指針與指針變量

  • 指針:具有指向作用的地址就是指針,地址是常量
  • 指針變量:能夠保存地址的變量就是指針變量,指針變量是可以被改變的

直接訪問與間接訪問

  • 直接訪問:直接通過地址值訪問得到此地址存放的內容

  • 間接訪問:通過指針變量所存放的地址值訪問的到此地址存放的內容

  • 不管你的指針是什麼類型,是幾級指針,在相同的編譯環境中,所佔的內存空間都是一致的。

  • 案例

#include "stdio.h"
#include "stdlib.h"

int main()
{
    int i = 1;
    int *p = &i;
    
    printf("i = %d\n",i);
    printf("&i = %p\n",&i);
    printf("p = %p\n",p);
    printf("&p = %p\n",&p);
    printf("*p = %d\n",*p);
    exit(0);
}
  • 結果

image-20200615155636722

空指針與野指針

  • 空指針:一開始不知道這個指針要具體存放啥時,就先將其設爲空指針
  • 野指針:當前這個指針所指向的空間是不確定的,但還要直接使用
#include "stdio.h"
#include "stdlib.h"

int main()
{
    int *p = NULL;//空指針
    int *q;//野指針
    
    exit(0);
}

空類型

  • 在不確定類型時使用

  • 任何類型的值都可以把值賦給空類型指針,空類型指針也可以將內容賦給任何類型的指針

void *q;

二、定義與初始化的書寫

一級指針

定義

  • 類型 *變量名
int *p;

初始化

  • 類型 *變量名 = 值
int *p = 123;

二級指針

定義

  • 類型 **變量名
int **q;

初始化

  • 類型 **變量名 = 一級指針取地址
int *p = &i;
int **q = &p;//二級指針

指針運算

  • &(取地址)
  • *(取值)
  • 關係運算(地址值大小相比較)
  • 案例
#include "stdio.h"
#include "stdlib.h"

int main()
{
    int a[6] = {5,1,7,3,8,3};
    int y;
    int *p = &a[1];
    
    y = (*--p)++;//在p地址的基礎上地址自減一個元素,所以y的值爲a[0]=5
    			 //在執行完取值的操作後,a[0]所存放的值自增1
    
    printf("y = %d\n",y);
    printf("a[0] = %d\n",a[0]);
    exit(0);
}
  • 結果

image-20200616232048351

三、指針與數組的關係

指針與一維數組

a[i]:a[i] = *(a+i) = *(p+i) = p[i]
&a[i]&a[i] = a+i = p+i = &p[i]
  • 案例1
#include "stdio.h"
#include "stdlib.h"

int main()
{
    int a[3] = {1,2,3};
    int i;
    int *p = a;
    
    for(i = 0;i < 3;i++)
    {
    	printf("%p-->%d\n",a+i,a[i]);
    	printf("%p-->%d\n",p+i,a[i]);
    	printf("%p-->%d\n",p+i,*(p+i));
    }
    printf("/n");
    exit(0);
}
  • 結果

image-20200616154142951

  • 案例2
#include "stdio.h"
#include "stdlib.h"

int main()
{
    int a[3];
    int i;
    int *p = a;
    for(i = 0;i < sizeof(a)/sizeof(*a);i++)
    	printf("%p-->%d\n",&a[i],a[i]);
    
    for(i = 0;i < sizeof(a)/sizeof(*a);i++)
    	scanf("%d",p++);
    	//scanf("%d",&a[i]);
    	//scanf("%d",&p[i]);
    
    p = a;//將自增完的地址重新賦值
    
    for(i = 0;i < sizeof(a)/sizeof(*a);i++,p++)
    	printf("%p-->%d\n",p,*p);
    printf("/n");
    exit(0);
}
  • 結果

image-20200616230552838

指針與二維數組

  • 案例1
#include "stdio.h"
#include "stdlib.h"

int main()
{
    int a[2][3] = {1,2,3,4,5,6}; 
    int i,j;
    int *p;
	    
    p = &a[0][0];
    
    printf("a	-->	%p\n",a);   
    printf("a+1	-->	%p\n",a+1);//a+1:地址增加一個行元素
	printf("p	-->	%p\n",p);   
    printf("p+1	-->	%p\n",p+1);//p+1:地址增加一個元素
    printf("\n");


    for(i = 0;i < 6;i++)
        printf("%d ",p[i]);
    printf("\n");
    
    for(i = 0;i < 2;i++)
    {
        for(j = 0;j < 3;j++)
        {
            printf("%p	-->	%d\n",*(a+i)+j,*(*(a+i)+j)); 
            //printf("%p	-->	%d\n",&a[i][j],a[i][j]);            
        }
		printf("\n");
    }
    exit(0);
}
  • 結果

image-20200617000319115

指針與字符數組

  • 案例1
#include "stdio.h"
#include "stdlib.h"

int main()
{
    char str[] = "I love china!";
    char *p = str+7;
    
    puts(str);
    puts(p);
    
    exit(0);
}
  • 結果

image-20200620210851589

  • 案例2
#include "stdio.h"
#include "stdlib.h"
#include "string.h"

int main()
{
    char str1[] = "hello";
    char *str2  = "hello";
    
    printf("str1:%d %d\n",sizeof(str1),strlen(str1));
    printf("str2:%d %d\n",sizeof(str2),strlen(str2));
    
    strcpy(str1,"world");
    str2 = "world";
    
    puts(str1);
    printf("\n");
    puts(str2);
    printf("\n");
    exit(0);
}
  • 結果

image-20200620213504296

四、const與指針

  • 可以將變量轉換爲常量,不會因爲後面的運算而改變(用指針間接訪問的方法可以改變,但丟失限制)
  • 先看到const則爲常量指針,先看到*則爲指針常量
  • const後加*p(p地址存放的具體值)–>用來保護這個值不被改變
  • *const後加p(p爲存放值的地址) -->用來保護這個地址不被改變
#include "stdio.h"
#include "stdlib.h"

int main()
{
	const float pi = 3.14;
    
    float *p = &pi;
    
    *p = 3.14159;
    
    printf("%f",pi);
    exit(0);
}
  • 結果

image-20200621172442738

  • 案例1
const int a;
int const a;

const int *p;
int const *p;//常量指針

int *const p;//指針常量

const int *const p;//即是常量指針又是指針常量

#define PI	3.14
	2 * PI * r;
     
const float pi = 3.14;
	2 * pi * r;

常量指針

  • 指針的指向可以發生變化,但指向的值不能變化
#include "stdio.h"
#include "stdlib.h"

int main()
{
    int i = 1;
    int j = 100;
    const int *p = &i;
	printf("before-->%d\n",*p);
	//i = 10;//可以修改
    //*p = 10;//報錯:向只讀位置“*p”賦值
    p = &j;
    printf("after-->%d\n",*p);
}//值不能變但指向可以變
  • 報錯
image-20200621192141948
  • 結果

image-20200621194145589

指針常量

  • 指針的指向不能變化,但指向的值可以變化
#include "stdio.h"
#include "stdlib.h"

int main()
{
    int i = 1;
    int j = 100;
    
    int *const p = &i;
    
    printf("defore-->%d\n",*p);
    i = 100;
    printf("after-->%d\n",*p);
   
    //p = &j;//報錯:向只讀位置“p”賦值
}
  • 報錯
image-20200621192141948
  • 結果

image-20200621195530280

即是常量指針又是指針常量

  • 指針的指向不能被改變,指向地址存放的值也不能被改變
#include "stdio.h"
#include "stdlib.h"

int main()
{
    int i = 1;
    int j = 100;
    const int *const p = &i;
    printf("before-->%d\n",*p);
    *p = 10;//報錯:向只讀位置“*p”賦值
    p = &j;//報錯:向只讀位置“p”賦值
}
  • 報錯
image-20200621192141948

五、指針數組與數組指針

數組指針

定義

  • 指向數組的指針

格式

  • [存儲類型] 數據類型 (*指針名) [下標] = 值
int (*p)[3];	-->		int[3] *p;
  • 案例
#include "stdio.h"
#include "stdlib.h"

int main()
{
    int a[2][3] = {1,2,3,4,5,6}; 
    int i,j;
    int *p = *a;
    int (*q)[3] = a;
    
    for(i = 0;i < 2;i++)
    {
        for(j = 0;j < 3;j++)
        {
            printf("%p	-->	%d\n",*(a+i)+j,*(*(a+i)+j)); 
            //printf("%p	-->	%d\n",*(q+i)+j,*(*(q+i)+j)); 
            //printf("%p	-->	%d\n",&a[i][j],a[i][j]);            
        }
		printf("\n");
    }
    printf("%p  %p\n",a,a+1);
    printf("%p  %p\n",q,q+1);
    exit(0);
}
  • 結果

image-20200617001634803

指針數組

定義

  • 存放指針的數組

格式

  • [存儲類型] 數據類型 * 數組名 [長度]
int *arr[3];	-->		int *[3] arr;
  • 案例
#include "stdio.h"
#include "stdlib.h"
#include "string.h"

int main()
{
    int i,j,k;
    char *tmp;
    char *name[5] = {"Fllow me","Basic","Great","Fortran","Computer"};
    
    for(i = 0;i < 4;i++)
    {
        k = i;
        for(j = i+1;j < 5;j++)
        {
            if(strcmp(name[k],name[j]) > 0)
                k = j;
        }
        if(k != i)
        {
            tmp = name[i];
            name[i] = name[k];
            name[k] = tmp;
        }
    }
    
    for(i = 0;i < 5;i++)
    	puts(name[i]);
    
    exit(0);
}
  • 結果

image-20200622212213612

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