1·指针数组 与 数组指针 概念
(1)指针数组:就是指针的数组,数组里面的元素就是一个个数组。
(2)数组指针:就是数组的指针,是一个指向数组的指针。
2· 表达式
(1)int *p[5]
// 指针数组,p的方括号结合,那就是一个数组,所以为指针数组
// 这个数组有5个元素,每个元素都是指针,
// 指针指向的元素类型是 int类型。
(2) int (*p)[5]
// 数组指针,p先与星号结合,那就是一个指针,所以为数组指针
// 这个指针指向的是一个有5个元素(每个元素是int类型)的数组
(3) int *(p[5])
// 小括号其实没意义,与第一种相同
int main(void)
{
int *p;
int a[5];
p = a;//类型是匹配的
// p = &a; 类型不匹配,p是int *类型,
// &a是 int (*)[5]类型的,也就是数组指针.
int (*p1)[5];
p1 = &a;//这是可以的
return 0;
}
3· 函数指针 与 typedef
3·1 函数指针的实质:还是指针变量,本身占4个字节,与普通的指针一致,只是函数指针所指向的是一个函数的第一句代码的地址(C语言中用函数名表示)。
3·2 函数指针的书写 和分析方法
void func1 (void)
{
printf("test for function pointer.\n");
}
int main (void)
{
voiod (*pFunc)(void);
pFunc = func1;// 左边是一个函数指针变量,右边是一个函数名。
//与pFunc = &func1 表示意义一致,这就是与数组的数组名不同
pFunc();// 用函数指针的解引用来调用该函数【这里没有理解到】
return 0;
}
这是一篇关于指针函数与函数指针的博客!!!请多多观看
4·typedef 关键字
4·1 typedef关键字是用来定义。重定义的是数据的类型,而不是变量 。
5·函数指针实战
// 函数指针实战
#include<stdio.h>
int add(int a,int b);
int sub(int a,int b);
int mul(int a,int b);
int dev(int a,int b);
// 定义了一个函数指针pFunc,指针指向的是int,int类型的传参和int类型返回值的函数
typedef int (*pFunc)(int,int);
int main (void)
{
pFunc p1 = NULL;
char c = 0;
int a = 0,b = 0,result = 0;
printf("请输入操作类型:+ — * /\n");
scanf("%c",&c);
switch(c)
{
case '+':p1 = add;break;
case '-':p1 = sub;break;
case '*':p1 = mul;break;
case '/':p1 = dev;break;
default:p1 = NULL;break;
}
printf("请输入要操作的两个整数:\n");
scanf("%d %d",&a,&b);
result = p1(a,b);
printf("%d %c %d = %d.\n",a,c,b,result);
return 0;
}
int add(int a,int b)
{
return a + b;
}
int sub(int a,int b)
{
return a - b;
}
int mul(int a,int b)
{
return a * b;
}
int dev(int a,int b)
{
return a / b;
}
6·再论typedef
6·1 C语言的2种类型:内建类型 与用户自定义类型
内建类型ADT,自定义类型UDT
6·2 typedef定义的是类型而不是变量(就是重定义)
(1)类型是一个数据模板,变量是一个实在的数据。类型是不占内存的,而变量是占内存的。
(2)面向对象的语言中,类型就是类class,变量就是对象。
6·3 typedef 与 #define 的区别
typedef char *pChar;
#define pChar char *
6·4 typedef 与结构体
(1)结构体先定义类型,再去定义结构体变量
// 第一种
struct student // 对应的结构体指针:struct student *p1;
{
char name[4];
int age;
};
// 第二种
typedef struct student // 重定义结构体类型 为 student_t
{
char name[4];
int age;
}student_t;
// 对应的结构体指针:student_t *p2;
// 第三种 定义结构体指针
typedef struct teacher
{
char name[4];
int age;
}teeacher, *pTeacher;// 重定义了两个类型,第一个是结构体,第二个是结构体指针类型,其变量是pTeach
int main(void)
{
struct student S1;// struct student 是类型,S1是变量
student.name = cao;
student_t S2;
student.name = jiao;
return 0;
}
(2)typedef 与 const
typedef int * PINT;
const PINT p2; // 相当于是int *const p2;
typedef int * PINT;
PINT const p2; // 相当于是int *const p2;
如果就是想得到 const int *p;只能 typedef const int *CPINT;CPINT p1;
7· 二重指针
7·1 二重指针与普通一重指针的区别
二重指针与一重指针本质上都是指针变量,并且一重指针变量与二重指针变量都是占4个字节的内存空间大小。
char ** 类型就是指针指向的变量是char *类型(二重指针指向的是一个一重指针 ),char *类型就是这种指向的变量是char类型。
int main(void)
{
int *p1[5];
int *p2;
int **p3;
// p2 = p1;
// 这句代码是错误的
p3 = p1;
return 0;
}
*代码理解:p1是指针数组名,本质上就是数组名,数组名的做右值表示首元素的首地址。数组的元素是 int 类型,所以p1做右值就表示一个int 类型变量的地址,所以p1就是一个int类型变量的指针的指针,所以 p1就是一个二重指针。(我是这样理解指针数组的:因为指针数组的元素是int类型(也就是一重指针),如果用指针数组名来访问这个指针数组的首元素,而首元素又是一重指针,那么指针数组名就是二重指针了)。
总结:
1·二重指针用的少,一般就是和 指针数组 纠缠。
2·一重指针的地址就是和二重指针相匹配。(上面的代码:p3 = &p2,可以理解&符号)
8·二维数组
例如二维数组a[2][5],我是这样理解的:一维数组a[2]里面的两个元素也是一个一维数组a[5];
8·1 数组的下标式访问 与 指针式访问
(1)一维数组:
以 int b[10]为例子,int p = b;b[0] 就等同于(p+0);b[5]等同于*(p+9);b[i]等同于*(b+i)。
(2)二维数组:
以int a[3][5]为例子,int *p = a;a[1][2]等同于((p+1)+2)。
a[i][j]等同于((p+i)+j)。
我的理解是:里面的那一层(p+i)表示确定矩阵的行(第一维),外面的指针确定矩阵的列(第二维)。