IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> C语言--指针 -> 正文阅读

[C++知识库]C语言--指针

引言

C语言的一些基本例题
全部例题来自于C语言王道训练营 链接如下

B站链接.
书籍:《跟“龙哥”学C语言编程》

1.引用与解引用

下面展示一些 可运行的代码

#include<stdio.h>
#include<stdlib.h>
int main()
{
	int i = 10;
	int j = 5;
	int* p;//指针变量用来存储地址
	p = &i;
	printf("i=%d\n", i);//直接引用	
	printf("p=%d\n", *p);//间接引用
	printf("%p\n", &*p);//&* pointer_1与&a相同,都表示变量a的地址
	printf("%d\n", *&i);//*&a与a等价
	system("pause");
	return 0;
}

运行结果

i=10
p=10
0032F728
10
请按任意键继续. . .

2.指针的传递

下面展示一些 可运行的代码

#include<stdio.h>
#include<stdlib.h>
void change(int j)
{
	j = 5;
}
void zzchange(int* p)
{
	*p = 5;//间接访问得到变量i
}
int main()
{
	int i = 10;
	printf("before change i=%d\n", i);
	change(i);//当我们在change函数的函数栈空间内修改变量j的值后,change函数执行结束,其栈空间就会释放,j就不再存在,i的值不会改变。
	printf("after change i=%d\n", i);
	zzchange(&i);//传递i的地址
	printf("after zzchange i=%d\n", i);
	system("pause");
	return 0;
}

运行结果

before change i=10
after change i=10
after zzchange i=5
请按任意键继续. . .

3.指针的偏移

下面展示一些 可运行的代码

#include<stdio.h>
#include<stdlib.h>
#define N 5
int main()
{
	int a[N] = { 1,2,3,4,5 };
	int* p;
	int i;
	p = a;//保证符号两边的数值类型一致
	for (i = 0; i < N; i++)//正序输出
	{
		printf("%3d", *(p + i));
	}
	printf("\n----------------------------\n");
	p = &a[4];//p指向最后一个元素
	for (i = 0; i < N; i++)//逆序输出
	{
		printf("%-3d", *(p - i));
	}
	printf("\n");
	system("pause");
	return 0;
}

运行结果

  1  2  3  4  5
----------------------------
5  4  3  2  1
请按任意键继续. . .

4.指针与自增、自减

下面展示一些 可运行的代码

#include<stdio.h>
#include<stdlib.h>
//只有比后增优先级高的操作符,才会作为一个整体,如(),[]
int main()
{
	int a[3] = { 2,7,10 };
	int* p;
	int j;
	p = a;
	j = *p++;//j=*p,p++:p向后偏移
	printf("a[0]=%d,j=%d,*p=%d\n", a[0], j, *p);
	j = p[0]++;//j=p[0],p[0]++:p[0]的值+1
	printf("a[0]=%d,j=%d,*p=%d\n", a[0], j, *p);
	system("pause");
	return 0;
}

运行结果

a[0]=2,j=2,*p=7
a[0]=2,j=7,*p=8
请按任意键继续. . .

5.指针与一维数组

下面展示一些 可运行的代码

#include<stdio.h>
#include<stdlib.h>
void change(char *d)
{
	*d = 'H';
	d[1] = 'E';
	*(d + 2) = 'L';
}
int main()
{
	char c[10] = "hello";//等价于strcpy(c,"hello)
	char* p = "world";//把字符串常量'world'的首地址赋给p
	change(c);//c为实参
	printf("c=%s\n", c);
	printf("p=%s\n", p);
	//p[0]='H';//不可以对常量区数据进行修改
	p = "hello";//将字符串'hello'地址赋给p
	printf("p=%s\n", p);
	//c='world';//非法
	system("pause");
	return 0;
}

运行结果

c=HELlo
p=world
p=hello
请按任意键继续. . .

6.动态内存申请

下面展示一些 可运行的代码

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main()
{
	int i;
	char* p;
	scanf("%d", &i);//输入申请的空间大小
	p = (char *)malloc(i);//使用malloc动态申请空间,并返回空间的首地址
	strcpy(p, "malloc success");
	puts(p);
	free(p);//free时必须使用malloc申请时返回的指针值,不能进行任何偏移
	printf("free success\n");
	system("pause");
	return 0;
}

运行结果

20
malloc success
free success
请按任意键继续. . .

7.野指针

下面展示一些 可运行的代码

#include<stdio.h>
#include<stdlib.h>
//在free(p)之后,需要把p置为NULL,也就是在free(p)之后加上p=NULL。如果不置为NULL,那么这时的p称为野指针。
//malloc函数内部的内存管理算法把free(p1)刚刚释放的空间分配给了p3,因此p1这时和p3指向同一块内存空间。
int main()
{
	int* p1, * p2, * p3;
	p1 = (int*)malloc(4);
	*p1 = 1;
	p2 = (int*)malloc(4);
	*p2 = 2;
	free(p1);//释放原为p1申请的空间,但未将p1赋值为NULL
	p3 = (int*)malloc(4);
	*p3 = 3;
	printf("*p3=%d\n", *p3);
	*p1 = 100;
	printf("*p1赋值100后,*p3=%d\n", *p3);
	system("pause");
	return 0;
}

运行结果

*p3=3
*p1赋值100后,*p3=100
请按任意键继续. . .

8.栈空间与堆空间的差异

下面展示一些 可运行的代码

#include<stdio.h>
#include<stdlib.h>
//函数栈空间释放后,函数内的所有局部变量消失
char* print_stack()
{
	char c[] = "I am print_stack";
	puts(c);
	return c;
}
//堆空间不会因为函数执行结束而释放
//堆空间只有在执行free操作后才会释放,否则在进程执行过程中会一直有效
char* print_malloc()
{
	char* p;
	p = (char*)malloc(20);
	strcpy(p, "I am print_malloc");
	puts(p);
	return p;
}
int main()
{
	char* p;
	p = print_stack(); //数据存放在栈空间
	puts(p);
	p = print_malloc();
	puts(p);
	system("pause");
	return 0;
}

运行结果

I am print_stack
H`?
I am print_malloc
I am print_malloc
请按任意键继续. . .

9.深入理解const

下面展示一些 可运行的代码

#include<stdio.h>
#include<stdlib.h>
int main()
{
	char str[] = "hello world";
	char str1[] = "how do you do";
	//ptr是一个指向char*类型的常量,不能用ptr来修改所指向的内容
	const char* ptr = str;
	//const指针,不能修改ptr1指针,但可以修改该指针指向的内容。
	char* const ptr1 = str1;
	str[0] = 'H';//操作合法
	printf("++++str的内容++++\n");
	puts(str);
	printf("++++str1的内容++++\n");
	puts(str1);
	printf("++++ptr1指向str1++++\n");
	puts(ptr1);
	ptr1[0] = 'n';//合法
	printf("++++ptr1修改后++++\n");
	puts(ptr1);
	//不能通过ptr指针来修改
	//ptr[0] = 'n';//操作非法,编译错误,错误E0137:表达式必须是可修改的左值
	printf("++++ptr指向str++++\n");
	puts(ptr);
	ptr = str1;
	printf("++++ptr更改指向str1++++\n");
	puts(ptr);
	//ptr1 = str;//非法,编译错误,左值指定const对象
	system("pause");
}

运行结果

++++str的内容++++
Hello world
++++str1的内容++++
how do you do
++++ptr1指向str1++++
how do you do
++++ptr1修改后++++
now do you do
++++ptr指向str++++
Hello world
++++ptr更改指向str1++++
now do you do
请按任意键继续. . .

10.memmove的实现

下面展示一些 可运行的代码

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define N 5
int main()
{
	int a[N] = { 1,2,3,4,5 };
	int b[N] = { 1,2,3,4,5 };
	int i;
	memmove(b + 2, b + 1, 8);//将3 4 用2 3代替
	for (i = 0; i < N; i++)
	{
		printf("%3d", b[i]);
	}
	printf("\n");
	system("pause");
	return 0;
}

运行结果

  1  2  2  3  5
请按任意键继续. . .

11.数组指针与二维数组

下面展示一些 可运行的代码

#include<stdio.h>
#include<stdlib.h>
void print(int (*p)[4], int row)
{
	//int p[][4]改为int (*p)[4],二者是等价的
	//对于打印位置的p[i][j],可以写成*(*(p+i)+j),一般来说,我们更多地使用形式p[i][j]
	int i, j;
	for (i = 0; i < row; i++)
	{
		for (j = 0; j < sizeof(p[0]) / sizeof(int); j++)
		{
			printf("%-3d",*(*(p+i)+j));
		}
		printf("\n");
	}
}
//数组指针用于二维数组的传递和偏移
int main()
{
	int a[3][4] = { 1,3,5,7,9,11,13,15,17,19,21,23 };
	int b[4] = { 1,2,3,4 };
	int i = 10;
	int(*p)[4];//定义一个数组指针
	p = a;
	print(a, 3);
	system("pause");
	return 0;
}

运行结果

1  3  5  7
9  11 13 15
17 19 21 23
请按任意键继续. . .

12.二级指针的传递

下面展示一些 可运行的代码

#include<stdio.h>
#include<stdlib.h>
//二级指针也是一种指针,其作用也是传递和偏移
//二级指针只服务于一级指针的传递与偏移
void change(int** p, int* pj)
{
	*pj= 15;
	*p = pj;
}
//要想在子函数中改变一个变量的值,必须把该变量的地址传进去
//要想在子函数中改变一个指针变量的值,必须把该指针变量的地址传进去
int main()
{
	int i = 10;
	int j = 5;
	int* pi, * pj;
	pi = &i;
	pj = &j;
	printf("i=%d,*pi=%d,*pj=%d\n", i, *pi, *pj);
	change(&pi, pj);
	printf("after change i=%d,*pi=%d,*pj=%d\n", i, *pi, *pj);
	system("pause");
	return 0;
}

运行结果

i=10,*pi=10,*pj=5
after change i=10,*pi=15,*pj=15
请按任意键继续. . .

13.二级指针的偏移

下面展示一些 可运行的代码

#include<stdio.h>
#include<stdlib.h>
void print(char* p[])//这里可以写成char **p
{
	int i;
	for (i = 0; i < 5; i++)
	{
		puts(p[i]);
	}
}
//二级指针的偏移,服务的时指针数组
int main()
{
	char* p[5];//定义一个指针数组
	char b[5][10] = { "lele","lili","lilei","hanmeimei","zhousi" };
	int i, j, tmp;
	char* t;
	char** p2;
	int a[5] = { 3,7,9,2,4 };
	for (i = 0; i < 5; i++)
	{
		p[i] = b[i];//让指针数组中的每个指针都指向一个字符串
	}
	p2 = p;
	for (i = 4; i > 0; i--)
	{
		for (j = 0; j < i; j++)
		{
			if (strcmp(p2[j], p2[j + 1]) == 1) //判断p2[j]是否大于p2[j+1]
			{
				t = p2[j];
				p2[j] = p2[j + 1];
				p2[j + 1] = t;
			}
		}
	}
	print(p2);
	puts("----------------");
	for (i = 0; i < 5; i++)
	{
		puts(b[i]);
	}
	system("pause");
	return 0;
}

运行结果

hanmeimei
lele
lilei
lili
zhousi
----------------
lele
lili
lilei
hanmeimei
zhousi
请按任意键继续. . .

14.函数指针

下面展示一些 可运行的代码

#include<stdio.h>
#include<stdlib.h>
void b()
{
	printf("I am func b\n");
}
void a(void (*p)()) 
{
	p();
}
//定义函数指针,初始化只能赋函数名
int main()
{
	void (*p)();//定义一个函数指针变量
	p = b;
	a(p);
	system("pause");
	return 0;
}

运行结果

I am func b
请按任意键继续. . .

总结

第一次发表一篇完整的博客,对于一些遗漏,读者不要太过深究~
比较适合新手打基础大佬请绕路~
希望这些可以帮助你更好的理解C语言
马上就考研了 我居然还在纠结一些基础 真是闲的闲的闲的闲*10000!
过几天在更新后几章的内容
欢迎大家评论收藏点赞 !!!

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2021-08-10 13:14:33  更:2021-08-10 13:14:58 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/9 16:17:24-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码