指標,c入門

未之iii發表於2020-12-27

第六章c語言指標!!

zhizhen
在這裡插入圖片描述
在這裡插入圖片描述
在這裡插入圖片描述
在這裡插入圖片描述
在這裡插入圖片描述
在這裡插入圖片描述
在這裡插入圖片描述
注意:int pointer不是取值操作符,只是一個宣告指標的操作符號
下邊
pointer才是取值操作符
在這裡插入圖片描述
指標變數是變數,指標是地址
在這裡插入圖片描述
在這裡插入圖片描述

*號表示從p的記憶體單元中所指的地址中讀取內容
定義格式:型別識別符號 *指標變數名
說明
1)號用於定義指標變數,但指標變數名不包括
2)一個指標變數只能指向同一型別的變數
3)指標變數本身是整型的,指標變數本身也有自己的地址,佔四個位元組
取地址運算:用&變數名可以取得該變數的實體地址

取內容運算:用*指標表示式取得指標變數記憶體單元儲存中存的另一個記憶體地址裡的值給指標變數賦值
1)指標變數使用前必須要有值
2)指標變數的數值必須是地址值,不能直接用一個整型賦值
3)定義格式:int a, *p =&a;或int a,*p; p=&a; 4)可以給指標賦空值,此時指標不指向任何變數:p=NULL;

在這裡插入圖片描述
*只是表示它是指標
在這裡插入圖片描述
這裡需要和陣列一起理解。 C中的陣列實際上定義的是一個指標為首元素地址向後依次移動元素資料大小的位元組,取得該元素的地址所以必須規定指標所指資料型別,從而保證對資料訪問的完備性在這裡插入圖片描述
在這裡插入圖片描述
在這裡插入圖片描述
在這裡插入圖片描述
在這裡插入圖片描述
在這裡插入圖片描述
在這裡插入圖片描述
在這裡插入圖片描述
在這裡插入圖片描述
在這裡插入圖片描述
在這裡插入圖片描述
在這裡插入圖片描述
在這裡插入圖片描述
在這裡插入圖片描述
在這裡插入圖片描述
在這裡插入圖片描述
在這裡插入圖片描述

#include <stdio.h>
void exchange(int *q1,int *q2,int *q3)//int *q1=p1
{
	void swap(int *pt1,int *pt2);//如果a<b<c
	//去呼叫函式 ,用於交換&……&% 
	if(*q1<*q2)
	{
		swap(q1,q2);
	}
	if(*q1<*q3)
	{
		swap(q1,q3); 
	}
	if(*q2<*q3)
	{
		swap(q2,q3);
	}
}
void swap(int *pt1,int *pt2)
{
	int pt;
	if(*pt1<*pt2){
		pt=*pt1;
		*pt1=*pt2;
		*pt2=pt;//記得加*號只有在取地址和定義函式裡邊的時候不用加星號 
	}
	
}
int main()
{
	void exchange(int *q1,int *q2,int *q3);//使得a>b>c 
	int a,b,c,*p1,*p2,*p3;
	scanf("%d,%d,%d",&a,&b,&c);
	p1=&a;
	p2=&b;
	p3=&c;
	exchange(p1,p2,p3);
	printf("%d>%d>%d",a,b,c);
	return 0;
} 

在這裡插入圖片描述
在這裡插入圖片描述
取p=&a【3】,即為取了第三個陣列
我去試了下,p++是a的地址+4,不知道就動手 哈~
整型地址加了4,就相當於陣列的下一個元素了
在這裡插入圖片描述
在這裡插入圖片描述
+i表示指向第i個元素
p=a等價於p=&a【0】
在這裡插入圖片描述
在這裡插入圖片描述
在這裡插入圖片描述

指標本質也是個變數,在自己的實體地址裡存的是別人的實體地址 實體地址是個數字,所以可以對指標進行算數運算

	/*a+10是指向a[10];的
    p<(a+10)就是p的地址通過p+=1;依次往後加,但要小於a[10]的地址
    實際上for(p=a ; p<(a+10) ; p+=1) 就相當於
    for( i=0; i<10; i++ )
    printf("%d ", a[i] );
    現在相當於是將指標p指向a[0],然後p指向的地址依次變成a[1]……a[9];*/ 
    //p=a等價於p=&a【0】 陣列名存放的就是首元素的實體地址
	//a+10是地址範圍 
	//將*p指向陣列的首地址 ,此處將p這個指標指向了a的首地址 
	//p++表示每次指向下一個單元的位置 
	 int main()
{
	int *p,i,a[10];
	p=a;
	for(i=0;i<10;i++)
	{
		scanf("%d",p++);
	}
	printf("\n");
	p=a; 
	/*因為第一個for迴圈將p的值增加了十次,
	即指標P不再指向原來的陣列,
	所以輸出的不是你輸入的10個數 
	也可以改成p =p-10;*/
	for(i=0;i<10;i++,p++);
	{
		printf("%d\n",*p); 
	 } 
	 return 0;
 } 
 //出問題了,我也不知道哪裡出問題了,和rt的程式設計明明一模一樣qaq

在這裡插入圖片描述
在這裡插入圖片描述
在這裡插入圖片描述
在這裡插入圖片描述
在這裡插入圖片描述
之前呼叫使用陣列下標來做索引,現在改為用指標來做索引

#include <stdio.h>
int reverse(int *x,int n)//獲取的是一個指標變數 
{
	int *p,temp,*i,*j,m;
	m=(n-1)/2; 
	i=x;    //i指向陣列的第一個元素(地址) 
	j=x+n-1;  //j指向陣列的最後一個元素
	//因為這個陣列是從零開始索引的,所以需要減一 
	p=x+m;   //m等於中間的值 ,指向中間配對 
	for(;i<=p;i++,j--)
	{
		temp=*i;
		*i=*j;
		*j=temp;
	}
}
int main()
{
	int i,a[10]={3,7,9,11,0,6,7,5,4,2};
	printf("The original array:\n");
	for(i=0;i<10;i++)
	{
		printf("%d",a[i]);
	}
	printf("\n");
	reverse(a,10);//作用使得陣列重新倒敘排放 
	//傳遞的依舊是這個陣列的陣列名 
	printf("the array has been inverted:\n");
	for(i=0;i<10;i++)
	{
		printf("%d",a[i]);
	}
	printf("\n");
	return 0;
}
/*陣列0,4,9三個地址,然後進行值交換.主函式陣列首地址傳過去相當於
陣列首地址傳過去程式自動識別為指標指向了陣列的首地址
兩種方法都是穿的地址過去的兩個變數分別是陣列首地址和陣列個數
*/

在這裡插入圖片描述
在這裡插入圖片描述在這裡插入圖片描述
陣列名a相當於此陣列的地址。。。
在這裡插入圖片描述
在這裡插入圖片描述
a[0]的地址傳給指標變數*p,此時*p為定義,不是取值
在這裡插入圖片描述
在這裡插入圖片描述
在這裡插入圖片描述

#include <stdio.h>
void sort(int x[],int n) 
 {int i,j,k,t;
 for(i=0;i<n-1;i++)
 {
 	k=i;
 	for(j=i+1;j<n;j++)
 	{
 		if(x[j]>x[k])
 		{
	
 		t=x[j];
 		x[j]=x[k];
 		x[k]=t;
}
}
	 }
 }
int main()
{
	int *p,i,a[10]={3,7,9,11,0,6,7,5,4,2};
	printf("The original array:\n");
	for(i=0;i<10;i++)
	{
		printf("%d ",a[i]);
	}
	printf("\n");
	p=a;
	sort(p,10);
	printf("the result is:\n");
	for(p=a,i=0;i<10;i++)
	{
		printf("%d ",*p);
		p++;
	}
	printf("\n");
 } 

在這裡插入圖片描述
在這裡插入圖片描述
在這裡插入圖片描述
在這裡插入圖片描述

{
	int a[3][4]={0,1,2,3,4,5,6,7,8,9,10,11};
	printf("a=%d\n",a);//a的地址,a【0 】【0】的地址,也是此二維陣列的地址 
	printf("*a=%d\n",*a);//表示的是這一個指標變數,與下邊的a【0】相同 
	printf("a[0]=%d\n",a[0]);//不是0哦!!!! 
	printf("&a[0]=%d\n",&a[0]);
	printf("&a[0][0]=%d\n",&a[0][0]);//前五個都指向同一個地址,只是表達不相同 
	printf("a+1=%d\n",a+1);//指第二行的第一個地址 
	printf("*(a+1)=%d\n",*(a+1));
	printf("a[1]=%d\n",a[1]);
	//只有在輸出a【1】【0】的時候才會輸出4,就是要把名稱寫全 
	printf("&a[1]=%d\n",&a[1]);
	printf("&a[1][0]=%d\n",&a[1][0]);
	printf("a+2=%d\n",a+2);//指向a【2】【0】的地址 
	printf("a[2]=%d\n",a[2]);//同上 
	printf("a[1]+1=%d\n",a[1]+1);//指向a【1】【1】的地址 
	printf("*(a+1)+1=%d\n",*(a+1)+1); //同上 
	printf("*(a[1]+1)=%d\n",*(a[1]+1));//取a【1】【1】的地址 
	printf("*(*(a+1)+1)=%d\n",*(*(a+1)+1));//取此值
	return 0;
}

在這裡插入圖片描述
在這裡插入圖片描述
所以多維陣列指的是在一維陣列上邊的擴充套件,並不是真正的多維陣列
在這裡插入圖片描述
對二維陣列,如果不出現降維符“【】”或“*”,指向二維陣列出現一個降維符號指向一維陣列,出現兩個則指向元素即數值,而a【1】【2】則是元素值
在這裡插入圖片描述
在這裡插入圖片描述
在這裡插入圖片描述
在這裡插入圖片描述
在這裡插入圖片描述
在這裡插入圖片描述
在這裡插入圖片描述
小心別忘了\0這個元素
在這裡插入圖片描述
在這裡插入圖片描述
在這裡插入圖片描述
在這裡插入圖片描述
在這裡插入圖片描述
在這裡插入圖片描述
在這裡插入圖片描述
在這裡插入圖片描述

#include <stdio.h>
 void copy_string(char *from,char *to)
 {
 	while((*to=*from)!='\0')
 	{
 		to++;
 		from++;
	  } 
	  *to='\0';
}
	 /*錯因::while(*(from+i)!='\0')
 	{
 		*(to+i)=*(from+i);
 		i++;
	 }
	 *to='\0';
 }*/ 
int main()
{
	void copy_string(char *from,char *to);
	char *a="im a student";
	char b[]="you are a liar";//*b就不能執行 
	/*因為是b背寫(被copy了) ,
	如果使用指標變數來存放一段字串,
	他是直接將一段字串的偏移地址存放,是整句整句的存放
	而陣列是一個字元一個字元的存放。
	指標存放地址是一個常量區,我們不能去改變常量區的值*/ 
	printf("string a == %s\nstring b=%s\n",a,b);
	printf("copy string a to string b:\n");
	copy_string(a,b);
	printf("\nstring a=%s\nstring b=%s\n",a,b);
	return 0;
 } 

在這裡插入圖片描述
在這裡插入圖片描述
在這裡插入圖片描述
在這裡插入圖片描述
字串在記憶體中儲存在常量裡面。這樣寫相當於把常量的地址給陣列,然而陣列的地址是不可以修改的。而非單純的亂碼等價的問題
在這裡插入圖片描述
在這裡插入圖片描述
這個字元陣列已經是定義好了的了,我們完全可以把輸入的字存放到這個字串裡邊去
正解: 錯誤原因是:未初始化就使用了區域性指標變數a !
在這裡插入圖片描述
在這裡插入圖片描述
在這裡插入圖片描述
在這裡插入圖片描述
想要輸出字串後邊的部分,直接+相應的數目即可,不用*,這樣去的僅僅只是一個字元的地址。
在這裡插入圖片描述
在這裡插入圖片描述
在這裡插入圖片描述
在這裡插入圖片描述
在這裡插入圖片描述
在這裡插入圖片描述

#include <stdio.h>
int main()
{
	int max(int,int);
	int min(int,int);
	int add(int,int);
	void process(int x,int y,int(*fun)(int,int));
	int a,b;
	printf("endter a and b:");
	scanf("%d%d",&a,&b);
	printf("max=");
	process(a,b,max);
	printf("min=");
	process(a,b,min);
	printf("sum=");
	process(a,b,add);
	return 0;
}
int max(int x,int y)
{
	int z;
	if(x>y)
	{
		z=x; 
	}
	else
	{
		z=y;
	}
	return z;
}
int min(int x,int y)
{    
    int  w;
    
    w=x<y?x:y;
    return w;
} 
int add(int w,int z)
{
          int x;
          x=w+z;
          return x;
}
void process(int x,int y,int (*fun)(int,int))
{
          int result;
          result=(*fun)(x,y);
          printf("%d\n", result);
          
          
}

process函式不需要用if判斷指標指向的函式,int main主函式裡面已經給指標賦予了一個新函式,直接用指標函式就行
在這裡插入圖片描述
在這裡插入圖片描述
在這裡插入圖片描述
在這裡插入圖片描述

#include <stdio.h>
int *search(int (*stu)[4]);         //定義搜尋函式
int main()
{
    int stu[3][4], i, j, *p;
    for (i=0; i<3; i++)
        for (j=0, printf("Please enter No.%d student score: ", i+1);
		j<4; scanf("%d", &stu[i][j++]));  //輸入全部學生成績
		
    for (i=0; i<3; i++){                            //迴圈判斷3個學生的成績
        p=search(stu+i);                           //呼叫搜尋函式
        if (p==*(stu+i)){
            for(j=0, printf("No.%d student is fail!\nScore: ", i+1); 
			j<4; printf("%d ", *(p+j)), j++); //輸出不及格成績的學生成績及學生號。
            printf("\n");
        }
    }
    return 0;
}
//搜尋函式
int *search(int (*stu)[4])
{
    int *fail, i;
    for (i=0, fail=NULL; i<4; *(*stu+i)<60 ? fail=*stu, i++ : i++);
    return fail;
}

法二:

#include <stdio.h>
int main(void)
{
float score[][4]={{60,70,80,90},{56,89,67,88},{34,78,90,66}};
float *search(float (*p1)[4]);
float *p;
int i,j;
for(i=0;i<3;i++)
{
	p=search(score+i);//如果不及格就返回score[i][0]的地址,否則返回null
	if(p==*(score+i))//如果沒有小於60的就返回null 
	{
		printf("%d\tscore:",i);
		for(j=0;j<4;j++)
		{
			printf("%f\t",*(p+j));
		}
		printf("\n");
	}
	
}
return 0;
}
float *search(float (*p1)[4])//判斷成績是否及格
{
int i=0;
float *pt;
pt=NULL;
for(;i<4;i++)
{
	if(*(*p1+i)<60)
	{
		pt=*p1;
	}
		
}
return pt;
}

在這裡插入圖片描述
重點通常在後邊
在這裡插入圖片描述
在這裡插入圖片描述
在這裡插入圖片描述
在這裡插入圖片描述
在這裡插入圖片描述
在這裡插入圖片描述
在這裡插入圖片描述
在這裡插入圖片描述

#include <stdio.h>
#include <stdlib.h>

void main (int argc, char *argv[])
{
      int i;

      printf ("the number of string is : %d\n", argc-1);

      for(i=1; i < argc; i++)
      {
            printf ("the string %d is : %s\n", i, argv[i]);
      }
}

argc是int型的,它用來存放命令列引數的個數,argv是一個一維的一級指標陣列,它是用來存放命令列中各個引數和命令字的字串,這些都包含檔名
在這裡插入圖片描述

/* MEMCPY.C: Illustrate overlapping copy: memmove
 * handles it correctly; memcpy does not.
 */

#include <memory.h>
#include <string.h>
#include <stdio.h>

char string1[60] = "The quick brown dog jumps over the lazy fox";
char string2[60] = "The quick brown fox jumps over the lazy dog";
/*                           1         2         3         4         5
 *                  12345678901234567890123456789012345678901234567890
 */

void main( void )
{
   printf( "Function:\tmemcpy without overlap\n" );
   printf( "Source:\t\t%s\n", string1 + 40 );
   printf( "Destination:\t%s\n", string1 + 16 );
   memcpy( string1 + 16, string1 + 40, 3 );
   printf( "Result:\t\t%s\n", string1 );
   printf( "Length:\t\t%d characters\n\n", strlen( string1 ) );

   /* Restore string1 to original contents */
   memcpy( string1 + 16, string2 + 40, 3 );

   printf( "Function:\tmemmove with overlap\n" );
   printf( "Source:\t\t%s\n", string2 + 4 );
   printf( "Destination:\t%s\n", string2 + 10 );
   memmove( string2 + 10, string2 + 4, 40 );
   printf( "Result:\t\t%s\n", string2 );
   printf( "Length:\t\t%d characters\n\n", strlen( string2 ) );

   printf( "Function:\tmemcpy with overlap\n" );
   printf( "Source:\t\t%s\n", string1 + 4 );
   printf( "Destination:\t%s\n", string1 + 10 );
   memcpy( string1 + 10, string1 + 4, 40 );
   printf( "Result:\t\t%s\n", string1 );
   printf( "Length:\t\t%d characters\n\n", strlen( string1 ) );
}

在這裡插入圖片描述
在這裡插入圖片描述
在這裡插入圖片描述
在這裡插入圖片描述
在這裡插入圖片描述
在這裡插入圖片描述

#include <stdio.h>

void main(void)
{
      const char *str= "Welcome to Fishc.com!\n\n";
      // 這個語句的含義是:宣告一個名為str的指標變數,
      // 它指向一個字元型常量,初始化str為指向字串
      // "Welcome to Fishc.com!\n\n"
      printf("\n\n%s", str);
#if (1)
      str[0] = 'w';       //這條語句是錯誤的,但可以改變str指標的值 
#endif

      str = "I love Fishc.com!\n\n";   //合法!

      printf("\n\n%s", str);
#include <stdio.h>

void main(void)
{
      char * const str = "Welcome to Fishc.com!\n\n";
      // 常量指標是一個固定的指標,不可以改變它的值,但它所指的資料可以改變。


      str[0] = 'w';       //合法!

#if( 1 )
      str = "I love Fishc.com!\n\n";   //非法!!
#endif

      printf("\n\n%s", str);
}

可以定義const常量,具有不可變性。例如:const int Max=100; Max++會產生錯誤
const在*後表示地址為變數,該地址指向的值是可變的

#include <stdio.h>

void main(void)
{
      const char * const str = "Welcome to Fishc.com!\n\n";
      // 常量指標是一個固定的指標,不可以改變它的值,但它所指的資料可以改變。


      str[0] = 'w';                   //非法!

      str = "I love Fishc.com!\n\n";  //非法!!


      printf("\n\n%s", str);
}

相關文章