指针:
1、在C语言中,允许用一个变量来存放指针,这种变量称为指针变量。指针变量的值就是某份数据的地址,这样的一份数 据可以是数组、字符串、函数,也可以是另外的一个普通变量或指针变量。
2、定义指针变量与定义普通变量非常类似,不过要在变量名前面加星号*,格式为:
数据类型 * 变量名;
数据类型 * 变量名 = 值 ;
*表示这是一个指针变量,数据类型表示该指针变量所指向的数据的类型
3、定义指针变量时必须带*,给指针变量赋值时不能带*。
4、y=++*px; //px的内容加上1之后赋给y,++*px相当于++(*px)
y=*px++; //相当于y=*(px++)
5、假设有一个 int 类型的变量 a,pa 是指向它的指针,那么*&a和&*pa分别是什么意思呢?
*&a可以理解为*(&a),&a表示取变量 a 的地址(等价于 pa),*(&a)表示取这个地址上的数据(等价于 *pa),*&a仍然等价于 a。
&*pa可以理解为&(*pa),*pa表示取得 pa 指向的数据(等价于 a),&(*pa)表示数据的地址(等价于 &a),所以&*pa等价于 pa。
6、不能对指针变量进行乘法、除法、取余等其他运算,除了会发生语法错误,也没有实际的含义
7、数组中的所有元素在内存中是连续排列的,如果一个指针指向了数组中的某个元素,那么加 1 就表示指向下一个元素,减 1 就表示指向上一个元素。加减1都是跳的字节长度取决指针前面的定义类型;
8、数组指针:
int a[10];
int *p; p=a; a是a[0]的地址,是数组a[0]的首地址;
引入数组指针后,我们就有两种方案来访问数组元素了,一种是使用下标,另外一种是使用指针。
1) 使用下标也就是采用 a[i] 的形式访问数组元素。如果 p 是指向数组 a 的指针,那么也可以使用 p[i] 来访问数组元素,它等价于 a[i]。
2) 使用指针也就是使用 *(p+i) 的形式访问数组元素。另外数组名本身也是指针,也可以使用 *(a+i) 来访问数组元素,它等价于 *(p+i)。
数组名是常量,它的值不能改变,而数组指针是变量(除非特别指明它是常量),它的值可以任意改变。也就是说,数组名只能指向数组的开头,而数组指针可以先指向数组开头,再指向其他元素。
9、字符串指针:
C语言中没有特定的字符串类型,我们通常是将字符串放在一个字符数组中
C语言还支持另外一种表示字符串的方法,就是直接使用一个指针指向字符串,例如:
char *str = "hello";
这种方法不能修改字符串中的字符,只能将指针重新指向另一个字符串;
字符数组存储在全局数据区或栈区,第二种形式的字符串存储在常量区。全局数据区和栈区的字符串(也包括其他数据)有读取和写入的权限,而常量区的字符串(也包括其他数据)只有读取权限,没有写入权限。
10、二级指针:
一个指针指向的是另外一个指针,我们就称它为二级指针,或者指向指针的指针。
11、指针数组:
#include <stdio.h>
int main()
{
char *str[3] = {
"helloworld!", str[0]指向"helloword"
"I love c", str[1]指向"I love c"
"C Language" str[2]指向"C Language"
};
printf("%s\n%s\n%s\n", str[0], str[1], str[2]);
return 0;
}
12、二维数组指针:
int (*p)[4] = a;
括号中的*表明 p 是一个指针,它指向一个数组,数组的类型为int [4],这正是 a 所包含的每个一维数组的类型。
对指针进行加法(减法)运算时,它前进(后退)的步长与它指向的数据类型有关,p 指向的数据类型是int [4],那么p+1就前进 4×4 = 16 个字节,p-1就后退 16 个字节,这正好是数组 a 所包含的每个一维数组的长度。也就是说,p+1会使得指针指 向二维数组的下一行,p-1会使得指针指向数组的上一行。
1) p指向数组 a 的开头,也即第 0 行;p+1前进一行,指向第 1 行。
2) *(p+1)表示取地址上的数据,也就是整个第 1 行数据
3) *(p+1)+1表示第 1 行第 1 个元素的地址。*(p+1)单独使用时表示的是第 1 行数据,放在表达式中会被转换为第 1 行数据的首地址,也就是第 1 行第 0 个元素的地址,因为使用整行数据没有实际的含义,编译器遇到这种情况都会转换为指向该行第 0 个元素的指针;就像一维数组的名字,在定义时或者和 sizeof、& 一起使用时才表示整个数组,出现在表达式中就会被转换为指向数组第 0 个元素的指针。
4) *(*(p+1)+1)表示第 1 行第 1 个元素的值。
指针数组和二维数组指针的区别
int *(p1[5]); //指针数组,可以去掉括号直接写作 int *p1[5];
int (*p2)[5]; //二维数组指针,不能去掉括号
指针数组和二维数组指针有着本质上的区别:指针数组是一个数组,只是每个元素保存的都是指针,以上面的 p1 为例在,32位环境下它占用 4×5 = 20 个字节的内存。二维数组指针是一个指针,它指向一个二维数组,以上面的 p2 为例,它占用 4 个字节的内存。
13、
定义 含义
int *p; p可以指向 int 类型的数据,也可以指向类似 int arr[n] 的数组
int **p; p为二级指针,指向 int * 类型的数据
int *p[n]; p为指针数组。[ ] 的优先级高于 *,所以应该理解为 int *(p[n]);
int (*p)[n]; p是二维数组指针
int *p(); p是一个函数,他的返回值类型为 int *
int (*p)(); p是一个函数指针,指向原型为 int func()的函数
14、指针总结:
指针变量可以进行加减运算,例如p++、p+i、p-=i。指针变量的加减运算并不是简单的加上或减去一个整数,而是跟指针指向的数据类型有关。
两个指针变量可以相减。如果两个指针变量指向同一个数组中的某个元素,那么相减的结果就是两个指针之间的元素个数。
15、int *p; 4字节; char *p; 1字节; double *p; 8字节;
16、void *q 字节长度不确定,使用时要给出类型转换 a=(int) *q;
1、在C语言中,允许用一个变量来存放指针,这种变量称为指针变量。指针变量的值就是某份数据的地址,这样的一份数 据可以是数组、字符串、函数,也可以是另外的一个普通变量或指针变量。
2、定义指针变量与定义普通变量非常类似,不过要在变量名前面加星号*,格式为:
数据类型 * 变量名;
数据类型 * 变量名 = 值 ;
*表示这是一个指针变量,数据类型表示该指针变量所指向的数据的类型
3、定义指针变量时必须带*,给指针变量赋值时不能带*。
4、y=++*px; //px的内容加上1之后赋给y,++*px相当于++(*px)
y=*px++; //相当于y=*(px++)
5、假设有一个 int 类型的变量 a,pa 是指向它的指针,那么*&a和&*pa分别是什么意思呢?
*&a可以理解为*(&a),&a表示取变量 a 的地址(等价于 pa),*(&a)表示取这个地址上的数据(等价于 *pa),*&a仍然等价于 a。
&*pa可以理解为&(*pa),*pa表示取得 pa 指向的数据(等价于 a),&(*pa)表示数据的地址(等价于 &a),所以&*pa等价于 pa。
6、不能对指针变量进行乘法、除法、取余等其他运算,除了会发生语法错误,也没有实际的含义
7、数组中的所有元素在内存中是连续排列的,如果一个指针指向了数组中的某个元素,那么加 1 就表示指向下一个元素,减 1 就表示指向上一个元素。加减1都是跳的字节长度取决指针前面的定义类型;
8、数组指针:
int a[10];
int *p; p=a; a是a[0]的地址,是数组a[0]的首地址;
引入数组指针后,我们就有两种方案来访问数组元素了,一种是使用下标,另外一种是使用指针。
1) 使用下标也就是采用 a[i] 的形式访问数组元素。如果 p 是指向数组 a 的指针,那么也可以使用 p[i] 来访问数组元素,它等价于 a[i]。
2) 使用指针也就是使用 *(p+i) 的形式访问数组元素。另外数组名本身也是指针,也可以使用 *(a+i) 来访问数组元素,它等价于 *(p+i)。
数组名是常量,它的值不能改变,而数组指针是变量(除非特别指明它是常量),它的值可以任意改变。也就是说,数组名只能指向数组的开头,而数组指针可以先指向数组开头,再指向其他元素。
9、字符串指针:
C语言中没有特定的字符串类型,我们通常是将字符串放在一个字符数组中
C语言还支持另外一种表示字符串的方法,就是直接使用一个指针指向字符串,例如:
char *str = "hello";
这种方法不能修改字符串中的字符,只能将指针重新指向另一个字符串;
字符数组存储在全局数据区或栈区,第二种形式的字符串存储在常量区。全局数据区和栈区的字符串(也包括其他数据)有读取和写入的权限,而常量区的字符串(也包括其他数据)只有读取权限,没有写入权限。
10、二级指针:
一个指针指向的是另外一个指针,我们就称它为二级指针,或者指向指针的指针。
11、指针数组:
如果一个数组中的所有元素保存的都是指针,那么我们就称它为指针数组。
int *a[10];
指针数组还可以和字符串数组结合使用,例:#include <stdio.h>
int main()
{
char *str[3] = {
"helloworld!", str[0]指向"helloword"
"I love c", str[1]指向"I love c"
"C Language" str[2]指向"C Language"
};
printf("%s\n%s\n%s\n", str[0], str[1], str[2]);
return 0;
}
12、二维数组指针:
int (*p)[4] = a;
括号中的*表明 p 是一个指针,它指向一个数组,数组的类型为int [4],这正是 a 所包含的每个一维数组的类型。
对指针进行加法(减法)运算时,它前进(后退)的步长与它指向的数据类型有关,p 指向的数据类型是int [4],那么p+1就前进 4×4 = 16 个字节,p-1就后退 16 个字节,这正好是数组 a 所包含的每个一维数组的长度。也就是说,p+1会使得指针指 向二维数组的下一行,p-1会使得指针指向数组的上一行。
1) p指向数组 a 的开头,也即第 0 行;p+1前进一行,指向第 1 行。
2) *(p+1)表示取地址上的数据,也就是整个第 1 行数据
3) *(p+1)+1表示第 1 行第 1 个元素的地址。*(p+1)单独使用时表示的是第 1 行数据,放在表达式中会被转换为第 1 行数据的首地址,也就是第 1 行第 0 个元素的地址,因为使用整行数据没有实际的含义,编译器遇到这种情况都会转换为指向该行第 0 个元素的指针;就像一维数组的名字,在定义时或者和 sizeof、& 一起使用时才表示整个数组,出现在表达式中就会被转换为指向数组第 0 个元素的指针。
4) *(*(p+1)+1)表示第 1 行第 1 个元素的值。
指针数组和二维数组指针的区别
int *(p1[5]); //指针数组,可以去掉括号直接写作 int *p1[5];
int (*p2)[5]; //二维数组指针,不能去掉括号
指针数组和二维数组指针有着本质上的区别:指针数组是一个数组,只是每个元素保存的都是指针,以上面的 p1 为例在,32位环境下它占用 4×5 = 20 个字节的内存。二维数组指针是一个指针,它指向一个二维数组,以上面的 p2 为例,它占用 4 个字节的内存。
13、
定义 含义
int *p; p可以指向 int 类型的数据,也可以指向类似 int arr[n] 的数组
int **p; p为二级指针,指向 int * 类型的数据
int *p[n]; p为指针数组。[ ] 的优先级高于 *,所以应该理解为 int *(p[n]);
int (*p)[n]; p是二维数组指针
int *p(); p是一个函数,他的返回值类型为 int *
int (*p)(); p是一个函数指针,指向原型为 int func()的函数
14、指针总结:
指针变量可以进行加减运算,例如p++、p+i、p-=i。指针变量的加减运算并不是简单的加上或减去一个整数,而是跟指针指向的数据类型有关。
两个指针变量可以相减。如果两个指针变量指向同一个数组中的某个元素,那么相减的结果就是两个指针之间的元素个数。
15、int *p; 4字节; char *p; 1字节; double *p; 8字节;
16、void *q 字节长度不确定,使用时要给出类型转换 a=(int) *q;