#include <stdio.h>
//宏定义常量
#define ROWS 3
#define COLS 4
void swapValue(int x,int y);
void swapValue1(int *x ,int *y);
int main(int argc, const char * argv[]) {
/*
为什么需要指针?
1.使用指针处理数组中存储的数据,它的执行速度要比使用,下标快很多。因为下标需要进行位移量偏转,而指针是直接使用内存地址。
2.对于基本数据类型来书,我们在函数中无法更改函数调用处之前的局部变量,使用指针就可以做到。
...
指针:
一个变量的地址为该变量的"指针",它是个常量
指针变量:
指针变量是一个变量,用于存储地址的值
指针变量的声明:
数据类型 *指针变量名;
下面的声明中的 *号表示后面的变量名 p 为一个指针变量,前面的 int 类型表示该指针变量所存储的地址指向的存储单元上是存放一个整型的数据。
简要的说,就是上面的格式定义了一个指向 "数据类型" 的 "指针变量"
*/
int *p;
//指针的使用
//对指针赋值
int i = 10;
int *p1 ; //可以将int *看做是一个整体,然后p1中需要存储的是地址类型的数据
p1 = &i; //&是取值(地址)运算符
//等价于
// int *p1 = &i;
int *p2;
// *p2 = &i;
/*
错误原因:
*运算符优先级是大于 = ,首先 *p2进行运算,而*p2运算是求出p2所存储地址指向的内存的值,而此时p2内没有数据,所以*p2找不到相应的结果,所以这样是错误的。
注意: *号称为取值运算符
*/
/*
* 号的用法
1.表达式中,*两边都有表达式的话,*号是四则运算的乘法运算
2.在声明语句中,*表明后面的变量为一个指针形式的变量
3.*号如果不在声明语句中,而只是在右边的表达式的话,表明取*号右边变量中所存地址对应内存中的数据(取值)
*/
int *p3;
p3 = &i; //p3中就有了地址数据
// *p3 = &i;
//等价于 i = &i
//通过指针取值
int i1 = 100;
int *p4 ;
p4 = &i1;
printf("%d \n",*p4);
// printf("%d \n",p4); //打印结果是十进制的
//在C语言中提供了另一个控制字符串%p,专门用于打印指针的内存地址值,使得所打印的地址是十六进制的
printf("%p\n",p4);
//例子
int m = 10;
int n = 20;
//声明两个指针变量
int *p_i;
int *p_j;
p_i = &m;
p_j =&n;
printf("m = %d,n = %d\n",m,n);
//通过变量改变数据
m = 1000;
n = 2000;
printf("通过变量修改数据后的值:m = %d, n =%d\n",m,n);
//通过指针修改数据
*p_i = 100;
*p_j = 200;
printf("通过指针修改数据后的值:m = %d,n = %d\n",m,n);
printf("通过指针修改数据后的值:*p_i = %d,*p_j = %d\n",*p_i,*p_j);
//指针使用进阶
int i2 = 10;
int *p5;
int *p6;
p5 = &i2;
//
&*p5 ;
/*
表达式的含义?
&和*运算符的优先级相等,且是从右到左的顺序结合的
*p5 等于 i2
&*p5 等于 &i2
*/
printf("&i2 = %p\n",&i2);
printf("&*p5 = %p\n",&*p5);
//
// *&i2; //实际上就是i2的值
printf("*&i2 = %d\n",*&i2);
//
(*p5)++;
//先找出p5所存储地址指向的存储单元的值,把值进行自加,p5的地址不变
//
// *p5++;
//++ 与 * 同一优先级,结合方向是从右向左,所以先找出p5所存储地址的值,然后把该值加一,那么现在p5就不再指向变量i2了。
//值传递
int a1 = 10;
int b1 = 20;
printf("函数外,交换前:a1 = %d,b1 = %d\n",a1,b1);
swapValue(a1, b1);
printf("函数外,交换后:a1 = %d, b1 = %d\n",a1,b1);
/*
如果想像数组作为函数参数那样,在函数内改变传入局部变量的值后,在函数外部的局部变量的值对应改变,那么应该怎么做?
我们可以通过指针来做参数,因为指针中存放的同样是地址。在C语言中,地址传递也称为引用传递
*/
//指针作为函数参数
int a2 = 10;
int b2 = 20;
int *p_a2 = &a2;
int *p_b2 = &b2;
printf("函数外,交换前:*p_a2 = %d,*p_b2 = %d\n",*p_a2,*p_b2);
swapValue1(p_a2, p_b2);
printf("函数外,交换后:*p_a2 = %d,*p_b2 = %d\n",*p_a2,*p_b2);
//指向二维数组的指针
int array[3][4] = {
{1,2,3,4},
{11,12,13,14},
{111,112,113,114}
};
//array[0]、array[1]、array[2]分别代表了各自对应的一维数组的首元素地址,它是一个地址并不是一个数组元素
// array[0][0] //使用下标访问数组元素
//如何使用指针访问数组元素?
// *(array) 相当于 array[0]
//*(array+1) 相当于 array[1] ,array[1]是一个地址,对应着第二行的一个一维数组的首个元素地址
//*(array+1)+1 是第二行第二个元素的地址,然后继续使用*号,即可取出其对应的值了
printf("array[1][1] = %d\n",*(*(array+1)+1));
printf("array[2][3] = %d\n",*(*(array+2)+3));
//使用指针遍历二维数组
for (int i=0; i<3; i++)
{
for (int j=0; j<4; j++)
{
printf("*(*(array+%d)+%d)=%d\n",i,j,*(*(array+i)+j));
}
}
//声明一个指针变量让它指向二维数组
int *p9;
// p9 = array;
//这样是不可以的的,因为p9中的值指向的内存单元的值的数据类型是整型的。我们知道,array代表的是二维数组的第一行元素的地址,第一个元素又是一个一维数组。那么, p9 = array,就相当于让p指针存放了了一个地址,而这个地址所对应的存储单元中存储的又是一个地址。所以是不可以的。
p9 = array[0];
p9 = &array[0][0];
printf("*p9 = %d\n",*p9);
return 0;
}
void swapValue(int x,int y)
{
int tmp ;
printf("函数内,交换前:x = %d, y = %d\n",x,y);
tmp = x;
x = y;
y = tmp;
printf("函数内,交换后:x = %d, y = %d\n",x,y);
}
void swapValue1(int *x ,int *y)
{
int tmp;
printf("函数内,交换前: *x = %d ,*y = %d\n",*x,*y);
tmp = *x ;
*x = *y;
*y = tmp;
printf("函数内,交换后: *x = %d,*y = %d\n",*x,*y);
}