C语言指针笔记总结1

一.基本类型指针

指针->地址->内存单元的编号。指针就是地址,就是一个内存单元的编号。
指针变量是存放地址的变量。
指针和指针变量不同,
指针就是一个值,但是通常会把指针变量叫做指针。
基本类型指针:int * , float *, double *, char *等;

代码1 基本介绍

第一个代码,通过代码简单介绍一下指针。

#include<stdio.h>
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的地址

代码2 更好地体会

#include<stdio.h>
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

代码3 通过指针互换两个数字

#include<stdio.h>

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

二.指针和数组的关系

一维数组名为数组的首地址,是一个指针常量;确定一个一维数组需要数组第一个元素地址以及数组长度;指针之间不能加、乘、除,可以减(结果就是它们之间的距离);两个指针变量指向的是同一块连续空间中的不同存储单元才可以相减;在数组中使用。

代码1 通过指针遍历输出数组元素。

#include<stdio.h>

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

代码2 通过指针修改数组元素的值。

#include<stdio.h>

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

代码3 指针变量之间的运算

#include<stdio.h>
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个单元

三.指针和函数的关系1

指针和函数和数组

数组长度为长整数且不能是变量。
传统数组内存程序员无法手动释放,在程序结束时由系统释放。
它只能在它所在函数运行结束时由系统释放。
数组的长度不能在函数运行过程中动态增缩。
A函数定义的数组在A函数运行期间可以被其他函数使用,
但A函数运行结束后其他函数将不能使用那个数组。

代码1

#include<stdio.h>

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)
以字节为单元编号。
一个变量的地址用这个变量第一个编号地址表示,
这个变量本身类型就可以指出这个变量占几个字节。

代码1

#include<stdio.h>
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

四.多级指针

代码1 介绍

#include<stdio.h>
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

代码2

#include<stdio.h>

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

五.指针和函数的关系2

内容

静态指针不能跨函数使用,动态指针可以跨函数使用,跨函数使用内存, 得使用多级指针。

代码1 静态指针不能跨函数使用

#include<stdio.h>

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

为什么有这个结果,不知道,学习中。

代码2 动态指针跨函数使用

#include<stdio.h>
#include<malloc.h>

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.

后记:正在学习中,如有讲错,请谅解。

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值