C語言之指針一

一個程序程序載入內存,代碼數據都有地址,外掛就是調用函數修改數據,函數就是代碼。變量就是數據
函數名就是地址
內存地址是連續的,相鄰內存單元間的地址差1,可以把內存看成一個平坦的一維空間
內存與CPU讀寫速度快,容量比較小   ROM

程序:
代碼區 數據區 堆棧


指針與指針變量
    指針:一個變量的地址,
指針變量:專門存放變量地址的變量,指針變量的值是地址    

指針類型 : char*    short*      int*     float*        double*

指針除了首地址以外還有類型,類型決定了指向的數據大小,決定了數據的解析方式,指針的類型必須要和指針的指向類型一致
否則一定會出現偏差,地址相同

&取地址
*根據地址取出內容  ——>     num 等價於 *(&num)
int *p = #        p是指針變量存放num的地址,*p 是對num的解引用,p可以是任何變量的地址
//(int *)是一個指向int類型的指針變量 容納int變量的地址,p僅僅是一個開始地址,int決定截取多長,裏面的數據按照int來解析
//  *p 與int 對稱 ,*p 就是int類型數據

指針在函數內部可以改變外部變量


一個exe不可以隨意讀取另一個exe的內存,
聲明指針變量時必須初始化指針變量
無論什麼類型的指針變量(32位),大小是固定的,就是4個字節,指針變量是用來存儲地址的,什麼類型就是按照什麼類型來解析
指針的類型決定從地址開始有太長,這段數據如何解析

地址和指針的差別, 地址單單是一個內存區域,指針知道地址從哪裏開始哪裏結束,不同類型解析長度不同,解析方式並不同    

空指針 NULL  
int *p = NULL; //指針爲空,null是0,不指向任何變量

直接訪問:按變量地址存取變量值
間接訪問:通過存放變量地址的變量去訪問變量 (通過指針變量)
%p 按照地址打印,可顯示地址的位數

scanf初始化一個指針,可以指明一個指針指向的內存

C語言要改變外部數據只有傳地址,Java C++有引用,但是C語言沒有

!!!數據當做參數的時候,傳遞的是指針,改變的是原來的數組,數組數據拷貝非常浪費內存,除了數組以外,都是副本機制,傳數組名相當於傳指針


//數組作爲參數時
#include <stdio.h>
#include <stdlib.h>

//void showa(int a[10]);   形參a相當於一個指針
void showa(int *p)				//一維數組可用如此使用指針
{
	for (int i = 0; i < 10; i++)
		printf("%d\n",p[i]);
}

void  showb(int (*p)[4])		//二維數組,這樣使用指針
{
	for (int i = 0; i < 3; i++)
	{
		for (int j = 0; j < 4; j++)
		{
			printf("%02d  ",**(p + i)+j);  //兩個**
		}
		printf("\n");
	} 
	
}

int main()
{
	int a[10] = {1,2,3,4,5,6,7,8,9,10};
	int b[3][4] = {1,2,3,4,5,6,7,8,9,10,11,12};

	showa(a);
	showb(b);

	system("pause");
}


指向指針的指針(二級指針)
函數的形式參數,除了數組以外,傳遞任何數據,變量,都會新建一個變量接受傳入變量的值,不影響原來的變量

要想改變外部參數,如果是一個數據,傳遞數據的地址,
如果是一個指針,傳遞指針的地址,函數內部改變外部指針變量,這就是二級指針的用處
double *p = &num;   //指向num的指針變量p
double **pp = &p;  //聲明二級指針 *pp ,指向 雙精度指針變量p的地址
double* 指明是4個字節,*pp 是 double*類型的數據

可以通過用“**”聲明一個二級指針,間接改變指針的指向
指針類型儘量一致,類型不一致,會少讀取或者多讀取
#include <stdio.h>
#include <stdlib.h>
/*
指向指針的指針(二級指針)
函數的形式參數,除了數組以外,傳遞任何數據,變量,都會新建一個變量接受傳入變量的值,不影響原來的變量

要想改變外部參數,如果是一個數據,傳遞數據的地址,
如果是一個指針,傳遞指針的地址,函數內部改變外部指針變量,這就是二級指針的用處
double *p = #   //指向num的指針變量p
double **pp = &p;  //聲明二級指針 *pp ,指向 雙精度指針變量p的地址
可以通過用“**”聲明一個二級指針,間接改變指針的指向
*/
int a = 10, b = 11, c = 12;

void change(int *p)			//不能改變p的指向
{
	p = &b;
}

void changep(int **p)		//傳遞pa的地址才能改變pa的指向,二維指針
{
	*p = &c;
}

int main()
{

	int *pa = &a;			//聲明指向a的指針
	int **p = &pa;			//聲明指向pa的二級指針
	printf("%d\n",*pa);
	changep(p);
	printf("%d\n", *pa);
	change(p);
	printf("%d\n", *pa);
	system("pause");
}



同類型的指針賦值同一個變量,用於數據通信,三個數據一個改變全部改變
整數和指針最好不要直接運算
*指針就是指針指向的數據類型
#include<stdio.h>
#include<stdlib.h>

//指針的賦值運算,一般就是傳遞地址,根據地址內容進行操作
//三個數值,有一個變化,全部變化
//地址的比較是沒有意義的

//*p++ 和 *(p++)等價,結合方向從自右向左

//數組中,指針之差,可以判斷誰的編號在前面,誰的編號在後面
//可以判斷兩個指針之間相隔多少個元素


int main()
{
	int num = 13;
	int *p = #
	int *pa = p;
	printf("%d  %d   %d\n\n",num,*p,*pa);

	num = 23;	//直接賦值
	printf("%d  %d   %d\n\n", num, *p, *pa);

	*p = 26;	//間接賦值
	printf("%d  %d   %d\n\n", num, *p, *pa);

	*pa = 37;	//間接賦值
	printf("%d  %d   %d\n\n", num, *p, *pa);

	system("pause");
}










指針和二維數組
#include <stdio.h>
#include <stdlib.h>

int main()
{
	int a[3][4] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 };
	///int (*p)[4] = a; 二維數組的指針就是一個指向一維數組的指針,元素是確定的
	//a[i][j] = *(*(a+i)+j)	 &a[i][j]=*(a+i)+j
	for (int x = 0; x < 3; x++)
	{
		for (int y = 0; y < 4; y++)
		{
			printf("%2d   %p    ",a[x][y],&a[x][y]);
		}
		printf("\n");
	}

	printf("%p  %p  %p\n",a,a+1,a+2);//a是行指針,指向的數據一行有4個int類型
	printf("%p  %p  %p\n", *a, *a + 1, *a + 2);//*a是一個指向第一行第一個元素的指針
	printf("%p  %p  %p\n", *(a+1), *(a+1) + 1, *(a+1) + 2);//*(a+1)是一個指向第二行第一個元素的指針
	//a[i][j] = *(*(a+i)+j)			&a[i][j]=*(a+i)+j
	//a[i]代表行指針,等價 a+1

	system("pause");
}

int main9()
{
	int a[3][4] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 };
	printf("%p,%p,%p\n",a,&a,*a);		//地址相同
	//a是一個行指針,指向一個有四個元素的數組,			16
	//&a是一個指向二維數組的指針,二維數組有12個元素,	48
	//*a是一個指向int類型數據的指針						 4
	printf("%d,%d,%d\n", sizeof(*a), sizeof(*&a), sizeof(**a));//16 48 4

	system("pause");
}















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