C语言指针4

1.

#define _CRT_SECURE_NO_WARNINGS 1
#include

int main()
{
	int a = 10;
	int* p = &a;//一级指针
	int** pp = &p;//二级指针
	return 0;
}

上述代码中p的类型是int*

pp的类型是int**

2.int* arr[5];

数组arr的每个元素是整形指针

3.定义一个变量时,去掉变量名,剩下的就是变量的类型

4.用二级指针模拟二维数组:

#define _CRT_SECURE_NO_WARNINGS 1
#include

int main()
{
	int arr1[5] = { 1,2,3,4,5 };//5列
	int arr2[5] = { 2,3,4,5,6 };//5列
	int arr3[5] = { 3,4,5,6,7 };//5列
	int* arr[] = { arr1,arr2,arr3 };
	int i = 0;
	int j = 0;
	for (i = 0; i < 3; i++)
	{
		for (j = 0; j < 5; j++)
		{
			printf("%d ", *(arr[i] + j));
			printf("%d ", arr[i][j]);
			//上述两行代码等效
			//因为arr[i][j] == *(arr + i)[j] == *(*(arr + i) + j)
		}
		printf("\n");
	}

	return 0;
}

5.char* p = "abcdef";

p存放的是首字符a的地址

6.可以把字符串想象为一个字符数组,但是这个数组是不能被修改的.

当常量字符串出现在表达式中的时候,他的值是第一个字符的地址.

例:

printf("%c", "abcdef"[3]);

char* p = "abcdef";

打印的是d,而且p[3] == "abcdef"[3];

7."abcdef" + 3拿到的是'd'的地址

8.数组指针和指针数组的区别示例:

#define _CRT_SECURE_NO_WARNINGS 1
#include

int main()
{
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	int(*pa)[10] = &arr;//pa的类型是int(*)[10],p是一个指针,指向的是具有10个元素且每个元素的类型是int的数组
	int a = 10;
	int b = 20;
	int c = 10;
	int* p[3] = { &a,&b,&c };//pa的类型是int* [10],p是具有10个元素且每个元素的类型是int*的数组

	return 0;
}

9.

int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
//&arr 的类型是int (*)[10]  

10.*p == arr;

#define _CRT_SECURE_NO_WARNINGS 1
#include

int main()
{
	int arr[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
	int(*p)[10] = &arr;
	int i = 0;
	int sz = sizeof(arr) / sizeof(arr[0]);
	for (i = 0; i < sz; i++)
	{
		printf("%d", arr[i]);
		printf("%d", (*p)[i]);
		//上述两行代码等效
		//因为p == &arr
		//所以*p == *&arr == arr
	}
	return 0;
}

11.数组名都是首元素的地址,二维数组也不例外

12.二维数组传参传过去的也是首元素的地址,那么就可以用数组指针来接受那个一维数组,这也就是二维数组传参的本质

13.二维数组解引用一次的的话是找到了一维数组,而此时一维数组是该一维数组的数组名,即该数组首元素的地址,再对它进行解引用就拿到了某个数据

14.可以这样再函数内部查看主函数内部的数组

arr,长度

例:

C语言指针4_第1张图片

15.int (*)[10] == int [10]*

16.若parr是数组指针,则parr里面存的是这个数组的地址,解引用拿到的是首元素的地址

17.函数名同时也是函数名的地址,&函数名也一样

18.

#define _CRT_SECURE_NO_WARNINGS 1
#include

void print(int arr[3][5], int r, int c)
{
	int i = 0;
	for (i = 0; i < 3; i++)
	{
		int j = 0;
		for (j = 0; j < 5; j++)
		{
			printf("%d ", arr[i][j]);
		}
		printf("\n");
	} 
}

int main()
{
	void(*p)(int[3][5], int, int) = &print;
	return 0;
}

上述的p是函数指针变量

而int*p(int[3][5], int, int);是函数的声明

pf == print

*pf == print

上述的p也可以这样初始化:

void(*p)(int[3][5], int, int) = print;

19.使用函数指针的例子:转移表的创建:

#define _CRT_SECURE_NO_WARNINGS 1
#include

void menu()
{
	printf("***********************\n");
	printf("*****1.Add   2.Sub*****\n");
	printf("*****3.Mul   4.Div*****\n");
	printf("*****0.exit       *****\n");
	printf("***********************\n");
}

int Add(int x, int y)
{
	return x + y;
}

int Sub(int x, int y)
{
	return x - y;
}

int Mul(int x, int y)
{
	return x * y;
}

int Div(int x, int y)
{
	//x = (float)x;
	return x / y;
}

int cal(int x, int y, int(*p)(int, int))
{
	return p(x, y);
}


int main()
{
	//函数指针数组
	int(*p[5])(int, int) = { 0,Add,Sub,Mul,Div };//重点!!!
	int input = 1;
	menu();
	scanf("%d", &input);
	while (input != 0)
	{
		if (input <= 4)
		{
			int a = 0;
			int b = 0;
			printf("请输入两个数:\n");
			scanf("%d %d", &a, &b);
			printf("%d\n", cal(a, b, p[input]));
		}
		else
		{
			printf("输入错误!请重新输入\n");
		}
		menu();
		scanf("%d", &input);
	}



	return 0;
}

20.(*(void (*)())0)();是调用地址为0的函数

21.void  (* signal(int, void(*)(int) ) )(int);

这是一个函数的声明,函数名是signal,参数类型是(int, void(*)(int) ),返回类型是void  (*)(int)

22.typedef可以将复杂的类型名字简单化

原名字还是可以用的

但是对于数组指针类型和函数指针类型就有点不一样

例:

#define _CRT_SECURE_NO_WARNINGS 1
#include

typedef int m;

typedef int(*parr)[10] ;

typedef int(*ppp)(int, int);

int Add(int x, int y)
{
	return x + y;
}
int main()
{
	m a = 10;
	//上述代码等价于
	//int a = 10;

	int arr[10] = { 0 };
	parr a = &arr;
	//上述代码等价于
	//int(*a)[10] = &arr;

	ppp aaa = &Add;
	//上述代码等价于
	//int(*aaa)(int, int) = &Add;

	return 0;
}

你可能感兴趣的:(C语言复习,c语言,c++)