指针->地址->内存单元的编号。指针就是地址,就是一个内存单元的编号。
指针变量是存放地址的变量。
指针和指针变量不同,
指针就是一个值,但是通常会把指针变量叫做指针。
基本类型指针:int * , float *, double *, char *等;
第一个代码,通过代码简单介绍一下指针。
#include
int main(void)
{
int * p;
/*
创建一个指针型变量p;
int * 是一起的;p是变量的名字;
int * 表示p变量只能存放的是int类型变量的地址。
p的数据类型是int * 。
*/
int i = 3;
int j;
p = &i;//&是取地址符号,就是获取i的地址,把i的地址给p。
/*
1.把i的地址给p;于是p保存了i的地址,于是p指向i;
2.修改p的值或i的值互不影响;修改i的值,p的值并不会变,因为它存放的是i的地址,但*p会变;修改p的值,i的值不会变,i不会受到影响,*p会变,因为它已经不指向i了。
3.值针变量本质还是变量。
4.如果一个指针变量指向了一个普通变量,则
指针变量 就等同于 普通变量
就是 *p 等于 i。
它们出现的地方可以相互替换。
5.所以:如int * p, p存放的是int型变量的地址,它不能存放如double型变量的地址;那么double * p这个p只能存放double型变量的地址, 以此类推都是。
*/
j = *p;//*p 等于 i, 就是一个整型的值。
printf("i = %d, j = %d, *p = %d, p = %d\n", i, j, *p, p);
//也就是i == j == *p != p
return 0;
}
结果:
i = 3, j = 3, *p = 3, p = 1703720
p的值就是i的地址
#include
int main(void)
{
int i = 5;
int *p;
int *q;
p = &i;
q = p;//p的值是i的地址,把p的值赋值给q, 就是q也指向i。
printf("q = %d\n", *q);
return 0;
}
结果:
q = 5
#include
void swap(int *, int *);//声明。
int main(void)
{
int a = 3;
int b = 5;
swap(&a, &b);//传递实参
printf("a = %d, b = %d\n", a, b);//a, b的值已经互换,打印。
return 0;
}
void swap(int *p, int *q)//a, b 取地址p, q。 *p, *q,就是a, b。*p和*q互换了,那么a,b 值就互换了。
{
int t;
t = *p;//*p是int 型; p是 int * 型;
*p = *q;
*q = t;
}
/*
*的含义:
含义1.乘法,2*3 == 6
含义2.定义指针:int * p;
如:i = * p;
间接运算符或指针运算符:
该运算符放在已经定义好的指针变量前面,
表示 :以p的内容为地址的变量
*/
结果:
a = 5, b = 3
一维数组名为数组的首地址,是一个指针常量;确定一个一维数组需要数组第一个元素地址以及数组长度;指针之间不能加、乘、除,可以减(结果就是它们之间的距离);两个指针变量指向的是同一块连续空间中的不同存储单元才可以相减;在数组中使用。
#include
void function(char *p, int len)
{
int i;
for (i = 0; i < len; ++i)
{
printf("%c ", *(p + i));
}
printf("\n");
}
int main(void)
{
char a[5] = {'s', 'q', 'e', 'u', 'h'};
printf("a = %#X , a = %#X\n", a, &a[0]);
//%X就是以十六进制输出,中间加#就是结果前面会加0X。
function(a, 5);
return 0;
}
结果:
a = 0X19FF28 , a = 0X19FF28
s q e u h
#include
void function(int *p, int len)
{
p[3] = 88;//p[3]等价于*(p + 3)等价于a[3]等价于*(a + 3)
}
int main(void)
{
int a[5] = {1, 2, 3, 4, 5};
printf("%d\n", a[3]);
function(a, 5);
//a是数组名,就表示数组的首地址,传递首地址和数组长度就够了。
printf("%d\n", a[3]);
return 0;
}
结果:
4
88
#include
void function(int *p, int len)
{
int num;
num = 2 * (*(p + (len-1)) - *p);//取内容
//*(p + (len-1)等于8,*p等于1,8减1为7再乘2等于14
printf("num = %d\n", num);
}
int main()
{
int a[6] = {1,2,3,4,5,8};
function(a, 6);
int *p;
int *q;
p = &a[5];//取a[5]地址
q = &a[0];//取a[0]地址, 这里写成q = a也行。
printf("p和q所指向的单元相隔%d个单元\n", p - q);
return 0;
}
结果:
num = 14
p和q所指向的单元相隔5个单元
数组长度为长整数且不能是变量。
传统数组内存程序员无法手动释放,在程序结束时由系统释放。
它只能在它所在函数运行结束时由系统释放。
数组的长度不能在函数运行过程中动态增缩。
A函数定义的数组在A函数运行期间可以被其他函数使用,
但A函数运行结束后其他函数将不能使用那个数组。
#include
void f2(int * p, int len)
{
p[2] = 10;
}
void f1(void)
{
int a[5] = {1,2,3,4,5};
f2(a, 5);
printf("a[2] = %d\n", a[2]);
}
int main(void)
{
f1();
return 0;
}
结果:
a[2] = 10
一个指针变量占4个字节,和电脑位数有关。
预备知识:
sizeof(数据类型)
功能:返回值就是该数据类型所占的字节数。
例子:sizeof(char) = 1, sizeof(int) = 4, sizeof(double) = 8
sizeof(变量名)
功能:返回值就是该变量所占的字节数。
·假设p指向char类型变量(char本身占1)
·假设q指向int类型变量(int本身占4)
·假设r指向double类型变量(double本身占8)
以字节为单元编号。
一个变量的地址用这个变量第一个编号地址表示,
这个变量本身类型就可以指出这个变量占几个字节。
#include
int main(void)
{
char ch = 'a';
int s = 66;
double x = 56.7;
char * p = &ch;
int * q = &s;
double * r = &x;
printf("%d %d %d\n", sizeof(p), sizeof(q),sizeof(r));
printf("%d %d %d\n", sizeof(ch), sizeof(s),sizeof(x));
return 0;
}
结果:
4 4 4
1 4 8
#include
int main(void)
{
int i = 10;
int *p = &i;//p只能存放int型的地址,i型为int型
int **q = &p;//q只能存放p型的地址,p型为int *型
int ***r = &q;//r为int ***型,r只能存放q型的地址,q型为int **型
// 说以***r == i;
printf("i = %d\n", ***r);
return 0;
}
结果:
i = 10
#include
void f(int ** q)//就是q是int ** 类型,它存放int * 型,就是p
{
printf("i = %d\n", **q);
}
void g()
{
int i = 8;
int * p = &i;
f(&p);
//p是int *类型,p只能存放int型的地址,&p是 int ** 类型。
}
int main(void)
{
g();
return 0;
}
结果:
i = 8
静态指针不能跨函数使用,动态指针可以跨函数使用,跨函数使用内存, 得使用多级指针。
#include
void f(int **q)//q存放指针型变量p的地址
{
int i = 5;
*q = &i;//*q等价于p,而p只能存放int 型的地址,所以要取地址
}
int main(void)
{
int * p;
f(&p);
printf("%d\n", *p);//*p就是p里面的内容,已改变//本语句语法没有问题,但逻辑上有问题,因为i已经释放了
//*p里的i已经释放了,*p指向i也没有用
//上面的是静态指针,于是就不能跨函数使用,动态指针才行
return 0;
}
结果:
5
为什么有这个结果,不知道,学习中。
#include
#include
void f(int **q)
{
*q = (int *)malloc(sizeof(int));
//sizeof(int)表示当前机器整型占几个字节,不同机器整型不一定占4个字节
//等价于p = (int *)malloc(sizeof(int))
// int i = 5;
// *q = &i;
// q = 5;//不行
// *q = 5;//不行
**q = 5;
// free(q);在这里不能fee(q);
}
int main(void)
{
int * p;
f(&p);
printf("%d\n", *p);
return 0;
}
结果:
5
malloc的使用:https://blog.csdn.net/m0_46490164/article/details/113860102.
后记:正在学习中,如有讲错,请谅解。