C語言函數指針,數組指針,數組引用用法

void main()//關於指針的擴展理解
{
int ar[10] = {};//ar時整型數組
int a = 1;
int b = 2;
int c = 3;
int *br[10] = { &a, &b, &c };//br不是指針而是一個存放地址的數組
int(*cr)[10]=&ar;//cr是一個存放數組的首指針,cr後面括號的值必須和所存放數組的 大小一樣,這是cr+1時,會移動整個數組大小,它的識別能力爲整個數組
//int(*xr) = &br;這樣無法編譯通過,因爲在這條語句中xr是一個存放整型數組的指 針,然而br是一個存放地址的數組,所以類型不同
int *(xr)[10]=&br;//xr也是一個指向數組的首地址,但是xr所指的數組是存放地址的
//同理,當qr要指向br時需要加

int *(&qr)[10] = br;
int(&qr)[10] = ar;//引用
//int &cr[10] 這樣的寫法是錯誤的,因爲引用是不開闢空間的,然而給的方括號中10,又讓系統去開闢空間,造成了矛盾
//同理 int &(&cr)[10]自然也無法通過編譯
}

下面是函數指針的介紹

int Add(int x, int y)
{
	return x + y;
}
int dis(int x, int y)
{
	return x - y;
}
int *App(int x,int y)
{
	int z = x + y;
	return &z;
}

void printdis(int x, int y, int(*pfun)(int, int))//printdis(int x, int y, int pfun(int, int)),這樣也是正確的,當函數的聲明在形參時,是當做函數指針使用的
{
	if (pfun != NULL)
	{
		int z = (*pfun)(x, y);
		cout << z;
	}
}
void main2()
{
	int pfub(int, int);//是函數聲明
	int(*pfun)(int, int);//pfun是一個指針,而最前面的int表示所調用函數的返回類型
	int *(*pfum)(int, int);//同理int *知識表示調用函數的類型,(*pfun)表示pfun是一個指針
	//上面兩種方式是定義函數指針的唯一方式

	int(*pfun)(int, int) = NULL;//是將pfun的值賦爲NULL,而不是將函數的值賦值爲NULL;
	pfun = Add;//表示將add函數的地址賦值給pfun
	int x = 1;
	int y = 2;
	int z;
	int z = (*pfun)(x,y);
	pfum = App;
	int *p;
	p = (*pfum)(x, y);
	sizeof(pfun);//結果爲4,就是指針的大小
	//sizeof(*pfun)是無法計算的,因爲無法計算出函數的大小
	//同理函數指針pfun+=1也是無法進行的,因爲無法計算函數的大小所以也無法用過+1來跳到下一個函數;

	printdis(x, y, Add);//這就是函數指針的調用方式,至於函數指針的定義是在printdis函數中進行的

}

//下面的函數內容是使用一個指針,將多個類型的數組進行輸出,qsort,bsearch



struct Student
{
	char s_id[20];
	char s_name[20];
	char s_sex;
	int s_age;
};
void * PrintInt(void *p)
{
	int *s = (int*)p;
	printf("%d \n", *s);
	return s + 1;
}
void * PrintDouble(void *p)
{
	double *s = (double*)p;
	printf("%f \n", *s);
	return s + 1;
}
void * PrintStudent(void *p)
{
	Student *s = (Student *)p;
	printf("%s  ", s->s_id);
	printf("%s  ", s->s_name);
	printf("%c  ", s->s_sex);
	printf("%d \n", s->s_age);
	return s + 1;
}
void PrintArray(void *ar, int n, void * (*pfun)(void*))
{
	if (ar == NULL || n < 1 || pfun == NULL)
		return;
	for (int i = 0; i<n; ++i)
	{
		ar = pfun(ar);
	}
	printf("\n");
}

struct node{
	int(*p)(int);
	void(*q)(double);
};
int app(int){}
void diss(double){}
int main3()
{
	int ar[] = { 12, 23, 34, 45, 56, 67, 78, 90 };
	int arlen = sizeof(ar) / sizeof(ar[0]);

	double dr[] = { 1.2, 2.3, 3.4, 5.6, 7.8 };
	int drlen = sizeof(dr) / sizeof(dr[0]);

	Student sr[] = { "201901001", "yhping", 'm', 23,
		"201901002", "lilingjie", 'f', 15,
		"201901003", "zhanghuan", 'f', 18
	};
	int studlen = sizeof(sr) / sizeof(sr[0]);

	PrintArray(ar, arlen, PrintInt);
	PrintArray(dr, drlen, PrintDouble);
	PrintArray(sr, studlen, PrintStudent);

	int x = 1, y = 2;
	int(*pfunm[2])(int, int) = { Add, dis };//用數組的方式來使用函數指針,(*pfunm[2])中的pfunm是一個存放地址的數組不是指針
	node n = { app, diss };
	int di;                                 //但是使用數組存放函數指針是必須要求每個函數的類型相同
	cin >> di;                              //但是爲了是解決這個難題,可以使用結構體來初始化
	switch (di)
	{
	case 0:
		cout<<(*pfunm[0])(x, y); break;
	case 1:
		cout<<(*pfunm[1])(x, y); break;
	default:break;
	}
	return 0;


	//如果給出了函數的地址,需要我們調用函數,這是我們需要先將地址給強轉爲函數指針類型,再調用函數
	//比如地址爲0x00412db0
	//調用的方式爲int z = (*(int(*)(int,int)0x00412db0)(x,y)
	typedef int(*gun)(int, int);//這是類型聲明,不是宏替換,這是gun就是函數指針類型
#define sun int*
	sun a, b;//相當於int *a,*b
	typedef int *sum;
	sum a, b;//也相當於 int *a,*b
		//在typedef中*sum就已經說明了他爲指針類型,然後經過typedef後確定了他是一個int類型的指針類型
		//所以typedef的意義和#define是不同的

}

舉一個例題
要求數組指針向下移動,在從數組裏面向下移動,輸出ar2中的第三個
在這要說明的數組的地址和數組的首元素地址的值是一樣的,但是意義不同
在數組的地址前加*號就變爲了數組的首元素地址如&ar0是數組的地址,
*&ar就變爲了數組首元素的地址

	int ar0[4];
	int ar1[4];
	int ar2[4] = { 1, 2, 4, 5 };
	int(*s)[4] = &ar0;
	s += 2;
	cout<<*(*s+2);
	//也可寫作
	cout<<*(*(s+2)+2);
	cout<<*(s[2]+2);
	cout<<s[2][2];
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章