c语言学习-5

四、数组

看任何变量的内存,都是将该变量取地址,拖入内存窗口来看
C语言规定字符串的结束标志位'\0'
在这里插入图片描述

1.一维数组

#include<stdio.h>

/*
整型   int   4个字节
浮点型 float 4个字节
字符型 char  4个字节

看任何变量的内存,都是将该变量取地址,拖入内存窗口来看

C语言为了方便操作这些数据,提供了一种构造数据类型——数组。
所谓数组,是指一组具有相同数据类型的数据的有序集合。

声明数组时要遵循以下规则:
(1)数组名的命名规则和变量名的相同,即遵循标识符命名规则。
(2) 在定义数组时,需要指定数组中元素的个数,方括号中的常量表达式用来表示元素的个数,即数组长度。
(3)常量表达式中可以包含常量和符号常量,但不能包含变量。也就是说,C语言不允许对数组的大小做动态定义,
   即数组的大小不依赖于程序运行过程中变量的值。

*/
#define N 5
int main()
{
	//定义数组就是写一个变量名,后面加上方括号,方括号内写上整型常量
	//定义数组的一瞬间,数组占据的空间大小就确定下来了
	//数组初始化
	int c[N] = { 1,3,5,7,9 };
	int a[10] = { 1,3,5,7,9 };
	int b[10] = { 0 };
	int d[] = { 1,2,3,4 };

	return 0;
}

2.一维数组的存储及函数传递-访问越界

访问越界
Run-Time Check Failure #2 - Stack around the variable 'a' was corrupted.
在这里插入图片描述

#include<stdio.h>
#include<stdlib.h>

//数组越界
//一维数组的传递
#define N 5
int main()
{
	int j = 10;
	int a[5] = { 1,2,3,4,5 };//定义数组时,数组长度必须固定
	int i = 3;
	a[5] = 20;//越界访问,访问了不属于自己的空间
	a[6] = 21;
	a[7] = 22;//越界访问会造成数据异常
	printf("a[4] = %d\n", a[4]);//a[4]发生改变
	printf("j = %d\n", j);

	return 0;
}

在这里插入图片描述

3.一维数组的存储及函数传递

#include<stdio.h>
#include<stdlib.h>

//一维数组的传递,数组长度无法传递给子函数 
//c语言的函数调用方式是值传递
//打印数组里的每一个元素,数组在传递时,元素个数传递不过去
void print(int b[],int len)
{
	int i ;
	for (i = 0; i < len; i++)
	{
		//printf("b[%d] = %3d\n", i, b[i]);
		printf("%3d", b[i]);
	}

	b[4] = 20;//在子函数中修改数组元素
	printf("\n");

}

//数组越界
//一维数组的传递
//访问越界
//Run-Time Check Failure #2 - Stack around the variable 'a' was corrupted.
#define N 5
int main()
{
	int j = 10;
	int a[5] = { 1,2,3,4,5 };//定义数组时,数组长度必须固定
	int i = 3;
	//a[5] = 20;//越界访问,访问了不属于自己的空间
	//a[6] = 21;
	//a[7] = 22;//越界访问会造成数据异常
	print(a, 5);
	printf("a[4] = %d\n", a[4]);//a[4]发生改变
	//printf("j = %d\n", j);

	return 0;
}
  1  2  3  4  5
a[4] = 20

D:\cbook\第四章 数组\Debug\02.一维数组的存储及函数传递.exe (进程 19572)已退出,代码为 0。
要在调试停止时自动关闭控制台,请启用“工具”->“选项”->“调试”->“调试停止时自动关闭控制台”。
按任意键关闭此窗口. . .

4.字符数组

C语言规定字符串的结束标志位'\0'

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>

/*
字符数组
初始化字符数组时,一定要让字符数组的大小比看到的字符串的长度多1

C语言规定字符串的结束标志位'\0'
*/
int main()
{
	char a[6] = { 'h','e','l','l','o' };
	char c[5] = "how";
	printf("%s----%s\n", a, c);//printf的s%,对应后面要写的是字符数组名,字符串常量

	//读取字符串
	char e[20];
	scanf("%s", e);
	printf("e = %s\n", e);

	char d[20], f[20];
	scanf("%s%s", d, f);
	printf("%s----%s\n", d, f);

	return 0;
}
hello----how
h#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>

/*
字符数组
初始化字符数组时,一定要让字符数组的大小比看到的字符串的长度多1

C语言规定字符串的结束标志位'\0'
*/
int main()
{
	char a[6] = { 'h','e','l','l','o' };
	char c[5] = "how";
	printf("%s----%s\n", a, c);//printf的s%,对应后面要写的是字符数组名,字符串常量

	//读取字符串
	char e[20];
	scanf("%s", e);
	printf("e = %s\n", e);

	char d[20], f[20];
	scanf("%s%s", d, f);
	printf("%s----%s\n", d, f);

	return 0;
}ello
e = hello
hello world
hello----world

D:\cbook\第四章 数组\Debug\03.字符数组.exe (进程 19116)已退出,代码为 0。
要在调试停止时自动关闭控制台,请启用“工具”->“选项”->“调试”->“调试停止时自动关闭控制台”。
按任意键关闭此窗口. . .

5.字符数组的传递

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>

/*
* 我们把d称为形参
*/
void print(char d[])
{
	int i = 0;
	while (d[i]!='\0')//d[i]或者d[i]!=0
	{
		printf("%c", d[i]);//字符数组去输出某一个元素时,用%c
		i++;
	}
	printf("\n");
	//修改字符串数组中的内容,把首字母变大写
	d[0] -= 32;
}

int main()
{
	char c[10] = "hello";//c里边是10,或者20都可以,只要大于等于6即可
	print(c);//我们把c称为实参,调用print函数时,是d=c
	printf("%s", c);

	return 0;
}
hello
Hello
D:\cbook\第四章 数组\Debug\04.字符数组的传递.exe (进程 13904)已退出,代码为 0。
要在调试停止时自动关闭控制台,请启用“工具”->“选项”->“调试”->“调试停止时自动关闭控制台”。
按任意键关闭此窗口. . .

6.gets和puts

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>

/*
* 遇到一个问题, scanf通过%s读取字符串时,
* 当遇到空格以后,就会匹配结束,这样没办法把一行带有空格的字符串存入到一个字符数组中
*/
int main()
{
	char c[20];//字符数组的数组名里存放的就是字符数组的起始地址,类型是字符指针
	//c是一个字符数组,但是编译器给c内部存了一个值,c里边存储的值得类型是字符指针
	//fgets(c, sizeof(c), stdin);//gets(c)是一样的,等价
	gets(c);//当一次读取一行时,使用gets
	puts(c);//等价于printf("%s\n",c);

	return 0;
}
how are you
how are you

D:\cbook\第四章 数组\Debug\05.gets和puts.exe (进程 18868)已退出,代码为 0。
要在调试停止时自动关闭控制台,请启用“工具”->“选项”->“调试”->“调试停止时自动关闭控制台”。
按任意键关闭此窗口. . .

在这里插入图片描述

7.str函数使用

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>

/*
str 系列字符串操作函数主要包括strlen、strcpy、strcmp、strcat等
	strlen函数用于统计字符串长度
	strcpy函数用于将某个字符串复制到字符数组中
	strcmp函数用于比较两个字符串的大小
	strcat函数用于将两个字符串连接到一起
各个函数的具体格式如下所示:

#include <string.h>
	size_t strlen(char *str);
	char *strcpy(char *to,const char *from);//有const代表这个地方可以放一个字符串常量
	int strcmp(const char *str1,const char *str2);
	char *strcat(char *str1,const char *str2);

*/
int main()
{
	char c[20] = "hello world";
	printf("数组c内字符串的长度 = %d\n", strlen(c));
	char d[20];
	char e[20];
	strcpy(d, c);
	puts(d);
	strcpy(e, "study");
	puts(e);

	//下面是看strcmp,两个字符串比较,是比较对应字符位置的ASCII码值
	int ret = strcmp("hello", "hello");
	printf("两个字符串比较后的结果 = %d\n", ret);
	int ret1 = strcmp("how", "hello");
	printf("两个字符串比较后的结果 = %d\n", ret1);
	int ret2 = strcmp("hello", "how");
	printf("两个字符串比较后的结果 = %d\n", ret2);

	//下面看strcat,拼接两个字符串,目标数组要能够容纳拼接后的字符串
	strcat(c, e);
	puts(c);
	char f[20] = "你好 ";
	strcat(f, "世界");
	puts(f);


	return 0;
}
数组c内字符串的长度 = 11
hello world
study
两个字符串比较后的结果 = 0
两个字符串比较后的结果 = 1
两个字符串比较后的结果 = -1
hello worldstudy
你好 世界

D:\cbook\第四章 数组\Debug\06.str函数使用.exe (进程 3252)已退出,代码为 0。
要在调试停止时自动关闭控制台,请启用“工具”->“选项”->“调试”->“调试停止时自动关闭控制台”。
按任意键关闭此窗口. . .

五、指针

1.指针的本质

取地址操作符为&,也称引用,通过该操作符我们可以获取一个变量的地址值;
取值操作符为*,也称解引用,通过该操作符我们可以得到一个地址对应的数据。

#include<stdio.h>

/*
&符号是取地址,指针变量的初始化一定是某个变量取地址
*/
int main()
{
	int i = 5;
	int* i_pointer = &i;//整型指针变量,指向整型
	printf("sizeof(i_pointer) = %d", sizeof(i_pointer));//4个字节


	return 0;
}
sizeof(i_pointer) = 4
D:\cbook\第五章 指针\Debug\01.指针的本质.exe (进程 9092)已退出,代码为 0。
要在调试停止时自动关闭控制台,请启用“工具”->“选项”->“调试”->“调试停止时自动关闭控制台”。
按任意键关闭此窗口. . .

在这里插入图片描述

2.引用与解引用

#include<stdio.h>

int main()
{
	int i = 10;
	int* p = &i;
	int* a, * b, * c;//声明三个指针变量
	printf("i = %d\n", i);//直接访问
	printf("*p = %d\n", *p);//间接访问


	return 0;
}
i = 10
*p = 10

D:\cbook\第五章 指针\Debug\02.引用与解引用.exe (进程 22164)已退出,代码为 0。
要在调试停止时自动关闭控制台,请启用“工具”->“选项”->“调试”->“调试停止时自动关闭控制台”。
按任意键关闭此窗口. . .

3.计算n的阶乘

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>

/*
Description
	利用while或者for循环计算n!的值。提示:n! = 1*2*3...*n
Input
	一个正整数n,1≤n≤10。
Output
	n!的值。
*/
int print(int m)
{
	int sum = 1;
	while (m)
	{
		sum *= m--;
	}
	return sum;
}
int main()
{
	int n;
	printf("计算n的阶乘\n");
	printf("请输入一个正整数:");
	scanf("%d", &n);
	int count = print(n);
	printf("\n");
	printf("n的阶乘为,即%d!=%d\n", n, count);

	return 0;
}
计算n的阶乘
请输入一个正整数:5

n的阶乘为,5!=120

D:\cbook\第五章 指针\Debug\03.计算n的阶乘.exe (进程 12764)已退出,代码为 0。
要在调试停止时自动关闭控制台,请启用“工具”->“选项”->“调试”->“调试停止时自动关闭控制台”。
按任意键关闭此窗口. . .

4.面值100元的人民币换成10元、5元、2元和1元面值的票子

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
/*
Description
	某人想将手中的一张面值100元的人民币换成10元、5元、2元和1元面值的票子。
	要求换正好40张,且每种票子至少一张。问:有几种换法?
Input
	无输入
Output
	一个数,表示共有多少种换法

*/
//穷举法,34种
int print()
{
	int count = 0;//count代表有多少种换法
	int a, b, c, d;//10元,5元,2元,1元分别有多少张
	for (a = 1; a <= 10; a++)
	{
		for (b = 1; b <= 20; b++) {
			for (c = 1; c <= 50; c++)
			{
				for (d = 1; d <= 100; d++) {
					if ((a * 10 + b * 5 + c * 2 + d * 1) == 100 && (a + b + c + d) ==40 )
					{
						count++;//count代表有多少种换法
						printf("%d * %d * %d * %d = 100\n", a, b, c, d);
					}
				}
			}
		}
	}
	return count;

}
//枚举法  穷举法
int main()
{
	int sum;
	printf("面值100元的人民币换成10元、5元、2元和1元面值的票子\n");
	sum = print();
	printf("面值100元的人民币换成10元、5元、2元和1元面值的票子为:%d个方法\n", sum);

	return 0;
}
面值100元的人民币换成10元、5元、2元和1元面值的票子
1 * 5 * 31 * 3 = 100
1 * 6 * 27 * 6 = 100
1 * 7 * 23 * 9 = 100
1 * 8 * 19 * 12 = 100
1 * 9 * 15 * 15 = 100
1 * 10 * 11 * 18 = 100
1 * 11 * 7 * 21 = 100
1 * 12 * 3 * 24 = 100
2 * 2 * 34 * 2 = 100
2 * 3 * 30 * 5 = 100
2 * 4 * 26 * 8 = 100
2 * 5 * 22 * 11 = 100
2 * 6 * 18 * 14 = 100
2 * 7 * 14 * 17 = 100
2 * 8 * 10 * 20 = 100
2 * 9 * 6 * 23 = 100
2 * 10 * 2 * 26 = 100
3 * 1 * 29 * 7 = 100
3 * 2 * 25 * 10 = 100
3 * 3 * 21 * 13 = 100
3 * 4 * 17 * 16 = 100
3 * 5 * 13 * 19 = 100
3 * 6 * 9 * 22 = 100
3 * 7 * 5 * 25 = 100
3 * 8 * 1 * 28 = 100
4 * 1 * 20 * 15 = 100
4 * 2 * 16 * 18 = 100
4 * 3 * 12 * 21 = 100
4 * 4 * 8 * 24 = 100
4 * 5 * 4 * 27 = 100
5 * 1 * 11 * 23 = 100
5 * 2 * 7 * 26 = 100
5 * 3 * 3 * 29 = 100
6 * 1 * 2 * 31 = 100
面值100元的人民币换成10元、5元、2元和1元面值的票子为:34个方法

D:\cbook\第五章 指针\Debug\04.兑换100元人民币.exe (进程 1760)已退出,代码为 0。
要在调试停止时自动关闭控制台,请启用“工具”->“选项”->“调试”->“调试停止时自动关闭控制台”。
按任意键关闭此窗口. . .

5.输入N个数(N小于等于100),输出数字2的出现次数

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
/*
Description
	输入N个数(N小于等于100),输出数字2的出现次数;
	解题提示:
	整型数组读取5个整型数的方法如下:
	int a[100];
	for(int i=O;i<5;i++){
		scanf("%d",&a[i]);
	}
Input
	输入的格式是两行
	第一行输入要输入的元素个数,比如5
	第二行输入12232,那么输出结果为3,因为2出现了3次
Output
	统计数字2出现的次数
*/
//增量编写法
int main()
{
	int n;
	int arr[100] = {0};
	//int brr[100];
	printf("要输入的元素个数:");
	scanf("%d", &n);//接下来要输入多少个元素
	printf("请输入%d个元素:",n);
	for (int i = 0; i < n; i++)
	{
		//scanf("%d", &brr[i]);//如何往数组里元素读入数据
		int m;
		scanf("%d", &m);
		arr[m-1]++;
	}
	printf("统计数字2出现的次数为:%d次", arr[2 - 1]);

	return 0;
}
要输入的元素个数:5
请输入5个元素:1 2 2 3 2
统计数字2出现的次数为:3次
D:\cbook\第五章 指针\Debug\05.某个数字出现的次数.exe (进程 5992)已退出,代码为 0。
要在调试停止时自动关闭控制台,请启用“工具”->“选项”->“调试”->“调试停止时自动关闭控制台”。
按任意键关闭此窗口. . .
要输入的元素个数:10
请输入10个元素:1 2 3 5 6 2 9 2 2 2
统计数字2出现的次数为:5次
D:\cbook\第五章 指针\Debug\05.某个数字出现的次数.exe (进程 21180)已退出,代码为 0。
要在调试停止时自动关闭控制台,请启用“工具”->“选项”->“调试”->“调试停止时自动关闭控制台”。
按任意键关闭此窗口. . .

6.增量编写法–统计2的次数

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>

//增量编写法
int main()
{
	int n;
	int arr[100];
	printf("要输入的元素个数:");
	scanf("%d", &n);//接下来要输入多少个元素
	printf("请输入%d个元素:", n);
	int i;
	for (i = 0; i < n; i++)
	{
		scanf("%d", &arr[i]);//如何往数组里元素读入数据
	}

	int count = 0;
	for (i = 0; i < n; i++)//统计2出现的次数
	{
		if (arr[i] == 2)
		{
			count++;
		}
	}

	printf("统计数字2出现的次数为:%d次", count);

	return 0;
}
要输入的元素个数:5
请输入5个元素:1 2 2 3 2
统计数字2出现的次数为:3次
D:\cbook\第五章 指针\Debug\06.增量编写法.exe (进程 3388)已退出,代码为 0。
要在调试停止时自动关闭控制台,请启用“工具”->“选项”->“调试”->“调试停止时自动关闭控制台”。
按任意键关闭此窗口. . .

7.字符串逆转比较

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>

/*
Description
	读取一个字符串,字符串可能含有空格,将字符串逆转,
	原来的字符串与逆转后字符串相同,输出0,
	原字符串小于逆转后字符串输出-1,
	大于逆转后字符串输出1。
	例如输入hello,逆转后的字符串为olleh,因为hello小于olleh,所以输出-1
lnput
	输入一个字符串,例如hello,当如输入的字符串也可能是how are you,含有空格的字符串
Output
	输出是一个整型数,如果输入的字符串是hello,那么输出的整型数为-1

*/
int main()
{
	char c[100];
	printf("请输入一个字符串:\n");
	gets(c);//当一次读取一行时,使用gets
	printf("数组c内字符串的长度 = %d\n", strlen(c));
	printf("反转之前C:");
	puts(c);
	printf("\n");

	int m = strlen(c)-1;
	char d[100];
	strcpy(d, c);
	for (int i = 0; i < m; i++, m--)
	{
		char tmp = c[i];
		c[i] = c[m];
		c[m] = tmp;
	}
	printf("反转之后C:");
	puts(c);
	printf("\n");
	
	int count = strcmp(d, c);
	if (count == -1)
	{
		printf("输入%s,逆转后的字符串为%s,因为原字符串%s小于逆转后的字符串%s,所以输出%d", d, c, d, c, count);
	}
	else if (count == 1)
	{
		printf("输入%s,逆转后的字符串为%s,因为原字符串%s大于逆转后的字符串%s,所以输出%d", d, c, d, c, count);
	}
	else {
		printf("输入%s,逆转后的字符串为%s,因为原字符串%s等于于逆转后的字符串%s,所以输出%d", d, c, d, c, count);
	}
	

	return 0;
}
请输入一个字符串:
hello
数组c内字符串的长度 = 5
反转之前C:hello

反转之后C:olleh

输入hello,逆转后的字符串为olleh,因为原字符串hello小于逆转后的字符串olleh,所以输出-1
D:\cbook\第五章 指针\Debug\07.字符串逆转比较.exe (进程 15164)已退出,代码为 0。
要在调试停止时自动关闭控制台,请启用“工具”->“选项”->“调试”->“调试停止时自动关闭控制台”。
按任意键关闭此窗口. . .
请输入一个字符串:
hello world
数组c内字符串的长度 = 11
反转之前C:hello world

反转之后C:dlrow olleh

输入hello world,逆转后的字符串为dlrow olleh,因为原字符串hello world大于逆转后的字符串dlrow olleh,所以输出1
D:\cbook\第五章 指针\Debug\07.字符串逆转比较.exe (进程 11260)已退出,代码为 0。
要在调试停止时自动关闭控制台,请启用“工具”->“选项”->“调试”->“调试停止时自动关闭控制台”。
按任意键关闭此窗口. . .
请输入一个字符串:
hahaahah
数组c内字符串的长度 = 8
反转之前C:hahaahah

反转之后C:hahaahah

输入hahaahah,逆转后的字符串为hahaahah,因为原字符串hahaahah等于于逆转后的字符串hahaahah,所以输出0
D:\cbook\第五章 指针\Debug\07.字符串逆转比较.exe (进程 10716)已退出,代码为 0。
要在调试停止时自动关闭控制台,请启用“工具”->“选项”->“调试”->“调试停止时自动关闭控制台”。
按任意键关闭此窗口. . .

8.fgets和gets

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>

//fgets相对于gets去读取标准输入时,会把\n放到字符数组中
int main()
{
	char c[100], d[100];
	printf("请输入一个字符串:\n");
	//gets(c);//当一次读取一行时,使用gets
	fgets(c, sizeof(c), stdin);//stdin标准输入
	int len = strlen(c);
	c[len - 1] = '\0';
	//puts(c);//用来调试的
	int i, j;
	for (i = strlen(c) - 1, j = 0; i >= 0; i--, j++)//字符串翻转
	{
		d[j] = c[i];
	}
	d[j] = '\0';
	puts(d);//得到的d对不对
	int result = strcmp(c, d);
	if (result < 0) {
		printf("%d\n", -1);
	}
	else if (result > 0) {
		printf("%d\n", 1);
	}
	else {
		printf("%d\n", 0);
	}
	

	return 0;
}
请输入一个字符串:
hello
olleh
-1

D:\cbook\第五章 指针\Debug\08.fgets和gets.exe (进程 19660)已退出,代码为 0。
要在调试停止时自动关闭控制台,请启用“工具”->“选项”->“调试”->“调试停止时自动关闭控制台”。
按任意键关闭此窗口. . .
请输入一个字符串:
cba
abc
1

D:\cbook\第五章 指针\Debug\08.fgets和gets.exe (进程 6276)已退出,代码为 0。
要在调试停止时自动关闭控制台,请启用“工具”->“选项”->“调试”->“调试停止时自动关闭控制台”。
按任意键关闭此窗口. . .
请输入一个字符串:
aba
aba
0

D:\cbook\第五章 指针\Debug\08.fgets和gets.exe (进程 5980)已退出,代码为 0。
要在调试停止时自动关闭控制台,请启用“工具”->“选项”->“调试”->“调试停止时自动关闭控制台”。
按任意键关闭此窗口. . .

9.指针的传递

#include<stdio.h>
#include<stdlib.h>

void change(int j)
{
	j = 5;
}
int main()
{
	int i = 10;
	printf("before change i = %d\n", i);
	change(i);
	printf("after change i = %d\n", i);
	
	return 0;
}
before change i = 10
after change i = 10

D:\cbook\第五章 指针\Debug\09.指针的传递.exe (进程 20128)已退出,代码为 0。
要在调试停止时自动关闭控制台,请启用“工具”->“选项”->“调试”->“调试停止时自动关闭控制台”。
按任意键关闭此窗口. . .

10.指针的传递–值传递–地址传递

#include<stdio.h>
#include<stdlib.h>

/*
值传递
*/
void change(int j)//j称为形参
{
	printf("值传递\n");
	j = 5;
}
/*
地址传递
*/
void rechange(int *m)//j称为形参,m=&i
{
	printf("地址传递\n");
	*m = 5;//指针的间接访问
}
int main()
{
	int i = 10;//i是局部变量
	printf("before change i = %d\n", i);
	change(i);//函数调用是,把i称为实参;值传递
	printf("after change i = %d\n", i);
	rechange(&i);
	printf("after rechange i = %d\n", i);

	return 0;
}
before change i = 10
值传递
after change i = 10
地址传递
after rechange i = 5

D:\cbook\第五章 指针\Debug\09.指针的传递.exe (进程 14144)已退出,代码为 0。
要在调试停止时自动关闭控制台,请启用“工具”->“选项”->“调试”->“调试停止时自动关闭控制台”。
按任意键关闭此窗口. . .

11.指针的偏移

#include<stdio.h>
#include<stdlib.h>

/*
* 指针的偏移
* 
* 数组是特殊的,不能和整型变量,浮点型,字符型变量类比
*
* 数组名  a  类型是数组,a里边存了一个值,是地址值,是数组的起始地址,记住
* 
* 引发了异常:读取访问权限冲突。
* P是OxCCCCCCCC。
*
* 内存分为3种权限,掌握两种,可读,可写
* 出现上述异常是因为对应内存位置不可读
* 
*/
int main()
{
	int a[5] = { 1,2,3,4,5 };

	//int* p=0xcccccccc;//对一个指针变量进行取值,得到的类型是其基类型
	int* p;//对一个指针变量进行取值,得到的类型是其基类型
	p = a;
	printf("*p = %d\n", *p);
	for (int i = 0; i < sizeof(a)/sizeof(a[0]); i++)
	{
		printf("a[%d]=%d\n", i, *(p + i));
	}

}
*p = 1
a[0]=1
a[1]=2
a[2]=3
a[3]=4
a[4]=5

D:\cbook\第五章 指针\Debug\10.指针的偏移.exe (进程 22380)已退出,代码为 0。
要在调试停止时自动关闭控制台,请启用“工具”->“选项”->“调试”->“调试停止时自动关闭控制台”。
按任意键关闭此窗口. . .

在这里插入图片描述

12.指针与自增、自减

#include<stdio.h>
#include<stdlib.h>

//只有比后增优先级高的操作符,才会作为一个整体,如()、[]
int main()
{
	int a[3] = { 2,7,8 };
	int *p;//对一个指针变量进行取值,得到的类型是其基类型
	int j;
	p = a;//让指针变量p,指向数组的开头

	//j = (*p)++;//j=*p;(*p)++
	j = *p++;//j=*p;p++,任何时候都是把后加加去掉,第二步另外一个运算符看优先级是否高于++;
	//先把*p的值赋给j,然后对p加1
	printf("a[0]=%d,a[1]=%d,a[2]=%d,j=%d,*p=%d\n", a[0], a[1], a[2], j, *p);//{2,7,8},2,7

	j = p[0]++;//先把p[0]赋给j,然后对p[0]加1
	printf("a[0]=%d,a[1]=%d,a[2]=%d,j=%d,*p=%d\n", a[0], a[1], a[2], j, *p);//{2,8,8},7,8

	j = (*p)++;
	printf("a[0]=%d,a[1]=%d,a[2]=%d,j=%d,*p=%d\n", a[0], a[1], a[2], j, *p);//{2,9,8},8,9

	return 0;
}
a[0]=2,a[1]=7,a[2]=8,j=2,*p=7
a[0]=2,a[1]=8,a[2]=8,j=7,*p=8
a[0]=2,a[1]=9,a[2]=8,j=8,*p=9

D:\cbook\第五章 指针\Debug\11.指针与自增、自减.exe (进程 18756)已退出,代码为 0。
要在调试停止时自动关闭控制台,请启用“工具”->“选项”->“调试”->“调试停止时自动关闭控制台”。
按任意键关闭此窗口. . .

13.指针与一维数组

#include<stdio.h>
#include<stdlib.h>

//指针的偏移
//数组名作为实参传递给子函数时,是弱化为指针的
void change(char *d)//d为形参
{
	*d = 'H';
	d[1] = 'E';//*(d + 1) = 'E';
	*(d + 2) = 'L';
}
//指针与一维数组
//函数调用的本质是值传递(实参赋值给形参)
//数组传递是弱化为指针

int main()
{
	char c[10] = "hello";
	change(c);//c为实参
	printf("c = %s\n", c);
	puts(c);

	return 0;
}
c = HELlo
HELlo

D:\cbook\第五章 指针\Debug\12.指针与一维数组.exe (进程 5612)已退出,代码为 0。
要在调试停止时自动关闭控制台,请启用“工具”->“选项”->“调试”->“调试停止时自动关闭控制台”。
按任意键关闭此窗口. . .

14.malloc动态内存申请

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<string.h>

/*
* C语言的数组长度固定是因为其定义的整型、浮点型、字符型变量、数组变量都在栈空间中,而栈空间的大小在编译时是确定的。
* 如果使用的空间大小不确定,那么就要使用堆空间。
* 
* 申请5*sizeof(int)=20字节
* 
* 数组一开始定义好就确定下来了,数组是放在栈空间
* 
* 程序是放在磁盘上的有序的指令集合
* 
* 程序启动起来时才叫进程
* 
* malloc可以帮我们实现动态数组
*/
int main()
{
	int i;//申请多大的空间
	char *p;
	scanf("%d", &i);//输入需要申请的空间大小
	p = (char *)malloc(i);//malloc申请空间的单位是字节
	strcpy(p, "malloc success");
	puts(p);

	//释放空间,p的值必须和最初malloc返回的值一致
	free(p);//free时必须使用malloc申请时返回的指针值,不能进行任何偏移
	p = NULL;//如果不把p值为NULL,把p称为野指针

	return 0;
}
20
malloc success

D:\cbook\第五章 指针\Debug\13.malloc动态内存申请.exe (进程 4388)已退出,代码为 0。
要在调试停止时自动关闭控制台,请启用“工具”->“选项”->“调试”->“调试停止时自动关闭控制台”。
按任意键关闭此窗口. . .

在这里插入图片描述

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

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<string.h>

//栈空间
char* print_stack()
{
	printf("-----栈空间-----\n");
	char c[] = "I am print_stack";
	puts(c);//能正常打印
	return c;
}
//堆空间
char* print_malloc()
{
	printf("-----堆空间-----\n");
	char* 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();//堆空间不会随着子函数的结束而释放,必须自己free
	puts(p);

	return 0;
}
-----栈空间-----
I am print_stack
-----堆空间-----
I am print_malloc
I am print_malloc

D:\cbook\第五章 指针\Debug\14.栈空间与堆空间的差异.exe (进程 11788)已退出,代码为 0。
要在调试停止时自动关闭控制台,请启用“工具”->“选项”->“调试”->“调试停止时自动关闭控制台”。
按任意键关闭此窗口. . .

在这里插入图片描述

16.malloc实现动态数组

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>

/*
Description
	输入一个整型数,然后申请对应大小空间内存,然后读取一个字符串,
	字符串的输入长度小于最初输入的整型数大小,最后输出输入的字符串即可
	(无需考虑输入的字符串过长,超过了内存大小);
	注意下面问题:
		char *p;
		scanf("%d",&n);
		p=malloc(n);
		scanf("%c",&c);/注意在scanf和gets中间使用scanf("%c",&c),去除换行gets(p);
Input
	一个整型数和一个字符串,例如和
	10
	hello
Output
	输出输入的字符串,上面输入的是hello,那么输出hello

*/
//malloc可以帮我们实现动态数组
int main()
{
	int i;//申请多大空间
	scanf("%d", &i);//读取一个整型数
	char* p;
	p = (char*)malloc(i);//malloc申请空间的单位是字节,不进行强制类型转换会有警告
	char c;
	scanf("%c", &c);//为了去除缓冲区里的\n,VS可以用rewind,oj不行,不能用rewind
	gets(p);
	puts(p);

	return 0;
}
10
hello
hello

D:\cbook\第五章 指针\Debug\15.malloc实现动态数组.exe (进程 8012)已退出,代码为 0。
要在调试停止时自动关闭控制台,请启用“工具”->“选项”->“调试”->“调试停止时自动关闭控制台”。
按任意键关闭此窗口. . .

17.字符指针与字符数组的初始化

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<string.h>

int main()
{
	char *p = "hello";//把字符串型常量"hello"的首地址赋给p
	char c[10] = "hello";//等价于strcpy(c,"hello");
	printf("c[0]=%c\n", c[0]);
	printf("p[0]=%c\n", p[0]);
	c[0] = 'H';
	printf("c[0]=%c\n", c[0]);
	printf("p[0]=%c\n", p[0]);
	//p[0] = 'H';//不可以对常量区数据进行修改
	p = "world";//将字符串world的地址赋给p
	//c = "world";//非法
	printf("p[0]=%c\n", p[0]);

	return 0;

}
c[0]=h
p[0]=h
c[0]=H
p[0]=h
p[0]=w

D:\cbook\第五章 指针\Debug\16.字符指针与字符数组的初始化.exe (进程 14444)已退出,代码为 0。
要在调试停止时自动关闭控制台,请启用“工具”->“选项”->“调试”->“调试停止时自动关闭控制台”。
按任意键关闭此窗口. . .

18.二级指针的传递-了解

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>

//了解
//二级指针的初始化一定是某一个一级指针取地址
void change(int **p, int *pj)
{
	int i = 5;
	*p = pj;
}
//要想在子函数中改变一个变量的值,必须把该变量的地址传进去
//要想在子函数中改变一个指针变量的值,必须把该指针变量的地址传进去
int main()
{
	int i = 10, j = 5;
	int *pi, *pj;
	pi = &i;
	pj = &j;
	printf("i=%d,*pi=%d,*pj=%d\n", i, *pi, *pj);//等于i=10,*pi=10,*pj=5
	change(&pi, pj);
	printf("after change i=%d,*pi=%d,*pj=%d\n", i, *pi, *pj);//after change i=10,*pi=5,*pj=5

	return 0;
}
i=10,*pi=10,*pj=5
after change i=10,*pi=5,*pj=5

D:\cbook\第五章 指针\Debug\17.二级指针的传递.exe (进程 11068)已退出,代码为 0。
要在调试停止时自动关闭控制台,请启用“工具”->“选项”->“调试”->“调试停止时自动关闭控制台”。
按任意键关闭此窗口. . .

在这里插入图片描述
在这里插入图片描述

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

良辰美景好时光

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值