函数,指针定义与使用

const修饰指针:
https://blog.csdn.net/weixin_46654029/article/details/108419164

一、函数的分类:
c程序是由函数组成的,我们写的代码都是由主函数main()开始执行的。函数是c程序的基本模块,是用于外层特定任务的程序代码单元。从定义角度上函数可分为系统函数和用户定义函数
1、系统函数,即库函数:这是由编译系统提供的,用户不必自己定义这些函数,可以直接使用他们,如打印函数printf()。
2、用户定义函数:以解决用户的专门需要。
函数的作用:可以省去重复代码的编写,降低代码的重复率。

步骤:导入头文件—使用函数—获取函数返回值

二、函数的调用:产生随机数

需要关心5个因素:
1、头文件:包含指定的头文件
2、函数名字,必须和头文件声明的名字一样
3、功能:需要知道函数能干什么才去调用
4、参数:参数类型要匹配
5、返回值:根据需要接收返回值

三、头文件

1、
#include<time.h>
time_t time(time_t*t);
功能:获取当前系统时间
参数:设置为NULL
返回值:当前系统时间time_t相当于long类型,单位为毫秒

2、
#include<stdlib.h>
void srand(unsigned int seed);
功能:来设置rand()产生随机数时的随机种子
参数:如果每次seed相等,rand()产生随机数相等
返回值:无

3、
#include<stdlib.h>
int rand(void);
功能:返回一个随机数值
参数:无
返回值:随机数

//打印随机数
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include<time.h>
#include<math.h>
#include<stdlib.h>
int main()
{
void srand(unsigned int seed);//获取随机数
//srand((size_t)time(NULL)); 同上
//srand((unsigned int)time(NULL)); 同上
for (int i = 0;i < 10;i++)
{
printf("%d\n", rand()%100); //0-99 %51+50表示50-100
}
return 0;
}

四、函数的定义

1、格式:
返回值类型 函数名(参数列表)
{
代码体
return 0;
}

//求两数的和 (不同函数中函数中的变量可以重名,应为作用域不同)(函数调用结束,函数会在内存中销毁【在栈区中自动销毁】)
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include<time.h>
#include<math.h>
#include<stdlib.h>
int add(int a, int b) //函数定义 中参数称为形参(形式参数:没有具体值)不能eg:int a=10
{
int sum = a + b; //代码体
return sum; //返回值
}
void print()
{
printf(“hello world\n”);
}
int main()
{
int a = 10;
int b = 20;
int c;
c = add(a, b); //函数调用 函数调用的过程中传递的参数为实参(实际参数:有具体的值)将实参传递给形参
printf("%d\n", c);
print();
// return EXIT_SUCCESS;
// return 0;
}

//在定义函数时指定的形参,可有可无,根据函数的需求来设计,如果没有形参,圆括号内容为空,或写一个void关键字
//没有形参,圆括号内容为空

void max()
{
}

//没形参,圆括号内容为void关键字

void max(void)
{
}

//如果函数的返回的类型和return语句中表达式的值不一致,则以函数返回值类型为准,即函数返回值类型决定返回值的类型。对数值型数据,可以自动进行类型转换

double max() //函数返回值为double类型
{
int a=10;
return a; //返回值a为int类型,它会转为double类型再返回
}

//如果函数返回值类型和return语句中表达式的值不一致,而它又不能自动进行类型转换,程序会报错
//只能由实参传给形参,不能由形参传给实参

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include<time.h>
#include<math.h>
#include<stdlib.h>
void swap(int a, int b)
{
int temp = a;
a = b;
b = temp;
printf(“交换前数据:\n”);
printf(“a=%d\n”, a);
printf(“b=%d\n”, b);
}
int main(void)
{
int a = 10;
int b = 20;
swap(a, b);
printf(“交换后数据:\n”);//函数调用
printf(“a=%d\n”, a);
printf(“b=%d\n”, b);
return 0;
}

//实参单元与形参单元是不同单元。调用结束后,形参单元被释放,函数调用结束返回主函数后则不能再使用该形参变量。实参单元仍保留并维持原值。
//因此,在执行一个被调用函数时,并不会改变主函数中实参的值。

五、函数的样式

//无参函数调用,不能加上“实参”,但括号不能省略
//函数的定义

void test()
{
}
int main() //gerchar() Rand()里面没有参数
{
//函数的调用
test();//正确,圆括号不能省略
test(250);//错误,函数定义时没有参数
return 0;
}

//例题1 无参函数
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include<time.h>
#include<math.h>
#include<stdlib.h>
void fun01()
{
printf(“hello world”);
}
int main7()
{
fun01();
return EXIT_SUCCESS;
}

//例题2 无参函数
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include<time.h>
#include<math.h>
#include<stdlib.h>
void fun02()
{
return rand() % 10;
}
int main8()
{
srand((unsigned int)time(NULL));
fun02();
return EXIT_SUCCESS;
}

//例题3 冒泡排序函数版 有参函数
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include<time.h>
#include<math.h>
#include<stdlib.h>
void BubbleSort(int arr[], int len)
{
for (int i = 0;i < len-1;i++) //控制循环次数(外层执行次数=元素个数-1)
{
for (int j = 0;j < len-1 - i;j++) //内循环目的是比较相邻元素,将大的元素放后面
{
if (arr[j] > arr[j + 1]) //每次比较次数=元素个数-1-执行次数
{
int temp = arr[j]; //
arr[j] = arr[j + 1]; //数据逆置步骤
arr[j + 1] = temp; //
}
}
}
return;
}
int main9()
{
int arr[] = { 9,6,3,5,2,8,4,7,1,10 };
BubbleSort(arr,sizeof(arr)/sizeof(arr[0]));
for (int i = 0;i < 10;i++)
{
printf("%d\n", arr[i]);
}
return 0;
}

//实参与形参的个数应相等,类型应匹配(相同或赋值兼容)。实参与形参顺序对应,一对一传递数据。
//实参可以是常量,变量或表达式,无论实参是何种类型的量,在进行函数调用时,它们都必须具有确定的值,以便把这些值传递给形参。
//如果函数定义没有返回值,函数调用时不能写void关键字,调用函数时也不能接收函数的返回值。

//void表示空类型,不能直接定义数据
//可以作为函数的返回值类型,表示没有返回值。可以只写return;
//无参无返函数
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include<time.h>
#include<math.h>
#include<stdlib.h>
void main(void)
{
printf(“程序就这样”);
return;
}

六、函数的声明,main函数与exit函数

//函数声明

extren int add01(int a,int b);
//int add01(int ,int );

//例题(先声明)
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include<time.h>
#include<math.h>
#include<stdlib.h>
int main()
{
int a=add01(10, 20); //函数调用 可调用多次 定义变量a 也同时声明了
printf("%d\n", a );
return EXIT_SUCCESS;
}
int add01(int a, int b) //函数定义 只能定义一次,这视为声明
{
return a + b;
}

//exit()、return -1的使用
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include<time.h>
#include<math.h>
#include<stdlib.h>
void fun03()
{
printf(“hello world\n”);
printf(“hello world\n”);
printf(“hello world\n”);
exit(404); //终止程序执行,括号内为整型
return;
printf(“hello world\n”);
printf(“hello world\n”);
return;
}
int main()
{
fun03();
printf(“hello world\n”);
printf(“hello world\n”);
printf(“hello world\n”);
return -1; //exit(404);都表示终止程序执行
printf(“hello world\n”);
printf(“hello world\n”);
return EXIT_SUCCESS;
}

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include<time.h>
#include<math.h>
#include<stdlib.h>
void fun04()
{
printf(“hello world\n”);
printf(“hello world\n”);
printf(“hello world\n”);
exit(404); //终止程序执行,括号内为整型
return;
printf(“hello world\n”);
printf(“hello world\n”);
return;
}
int main()
{
fun04();
printf(“hello world\n”); //
printf(“hello world\n”); //表示只执行这3条
printf(“hello world\n”); //
return -1; //exit(404);都表示终止程序执行
printf(“hello world\n”);
printf(“hello world\n”);
return EXIT_SUCCESS;
}

七、多文件编程
(调试前先设为启动项目)

头文件:

#pragma once //防止头文件重复包含
//全局变量的定义
//函数的声明
//extern int max(int a, int b);
int max(int a, int b);
//int max(int,int);

源文件:

#include<stdio.h>
#include"head.h"
int main30(void)
{
int a = 10;
int b = 20;
printf("%d\n", max(a, b));
return 0;
}

//函数定义
int max(int a,int b)
{
return a > b ? a : b;
}

八、指针的定义和使用

内存的含义:
存储器:计算机的组成中,用来存储程序和数据,辅助CPU进行运行处理的重要部分。
内存:内部存贮器,暂存程序/数据——掉电丢失SRAM、DRAM、DDR、DDR2、DDR3
外存:外部存储器,长时间保存程序/数据——掉电不丢ROM、ERRROM、FLASH、(NAND、NOR)、硬盘、光盘

内存地址:
将内存抽象为一个很大的一维数组。
编码就是对每一个字节分配一个32位或64位的编号(与32位或64位处理器相关)
这个内存编号我们称之为内存地址
内存中每一个数据都会分配相应的内存地址:
1.char占一个字节分配一个地址
2.int占四个字节分配四个地址
3.float struct 函数 数组等

一级指针存储变量地址
二级指针存储一级指针地址

获取内存地址
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include<time.h>
#include<math.h>
#include<stdlib.h>
int main()
{
int a = 0xaabbccdd;
//a=100;
printf("%p\n",&a);//获取内存地址
getchar();
return EXIT_SUCCESS;
}

利用指针打印输出整型变量
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include<time.h>
#include<math.h>
#include<stdlib.h>
int main()
{
//定义指针变量存储变量地址
int a = 10;//通过改变a值来改变地址
//指针类型–> 数据类型*(存什么类型变量就用什么类型的指针)
int* p;
p= &a;//表示a的地址赋值给p
*p = 100;//通过指针变量p间接修改变变量的值,表示a的地址值等于100;
printf("%p\n", &a);
printf("%p\n", p);//打印出相同地址
printf("%d\n", *p);//通过指针变量p间接修改变量的值
printf("%d\n", a);
return 0;
}

利用指针打印输出字符型变量
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include<time.h>
#include<math.h>
#include<stdlib.h>
int main()
{
char ch=‘a’;
charp=&ch;
//int a = 10;
//int
p= &a;//无符号整型数4个字节 p是变量
// 所有的指针类型存储的都是内存地址,内存地址都是无符号十六进制整形数
//printf("%d\n", sizeof(int* ));
printf("%d\n", sizeof(char*));
return 0;
}

在32位操作系统下所有指针类型是4个字节大小
在64位操作系统下所有指针类型是8个字节大小
&是取地址符号 是升维度的
是取值符号是降维度的

利用指针打印输出字符型变量地址
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include<time.h>
#include<math.h>
#include<stdlib.h>
int main()
{
char ch = ‘a’;
int* p = &ch;
printf("%p\n", p);
printf("%p\n", &ch);
return 0;
}

指针类型一定要和变量类型对应上

九、野指针和空指针和万能指针

指针变量也是变量,是变量就可以任意赋值,不要越界即可(32位为4个字节,64位为8个字节)
但是,任意数值赋值给指针变量是没有意义,因为这样的指针就成了野指针,此指针指向的区域是未知(操作系统不允许操作此类指针指向的内存区域)
所以,野指针不会直接引发错误,操作野指针指向的内存区域才会出问题。
野指针和有效指针保存的都是数值,为了标志此指针变量没有指向任何变量(空闲可用)
c语言中,可以把NULL赋值给此指针,这样标志此指针为空指针,没有任何指针

//空指针:int*p=NULL;

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include<time.h>
#include<math.h>
#include<stdlib.h>
int main()
{
//野指针–>指针变量指向一个未知的空间(内存、并非地址位置)
int* p=100;//内存地址编号100
//操作野指针对应的内存空间可能报错
//操作系统将0-255作为系统占用不允许访问操作
//程序中允许存在野指针
//不建议将一个变量的值直接赋值给指针
printf("%d\n", *p);
return EXIT_SUCCESS;
}

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include<time.h>
#include<math.h>
#include<stdlib.h>
int main()
{
//空指针是指内存地址编号为0的空间
int* p = NULL;//操作空指针对应的空间一定会报错
//int* p = 100;//操作系统将0-255作为系统占用不允许访问操作
//空指针可以用作条件判断
if (p == NULL)
{
}
printf("%d\n", *p);
return 0;
}

//万能指针void指针可以指向任意变量的内存空间
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include<time.h>
#include<math.h>
#include<stdlib.h>
int main()
{
int a = 10;
// int
p = &a;
// 万能指针可以接收任意类型变量的内存地址
void* p = &a; // 定义指针类型一定要和变量的类型对应上
// *p = 100;–>
(int)p=100;//没有这一项时打印出来a=10;
printf("%d\n", a);
// printf("%d\n", p);-- >
printf("%d\n", (int)p);//在通过万能指针修改变量时,需要找到变量对应的指针类型
// printf("%p\n", p); 报错
printf(“万能指针在内存中占字节大小:%d\n”, sizeof(void
));
// printf(“void在内存中占字节大小:%d\n”, sizeof(void)); 报错
return EXIT_SUCCESS;
}

十、const修饰的指针

//const 修饰指针类型 const int* p = &a;

//修饰指针变量 int* const p;

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include<time.h>
#include<math.h>
#include<stdlib.h>
int main25()
{
//常量
const int a = 10;
//指针间接修改常量的值
int* p = &a;//获取a的地址
*p= 100;
printf("%d\n", a);
return EXIT_SUCCESS;
}

//const 修饰指针类型 const int* p = &a;
//可以修改指针变量的值p
///不可以修改指针指向内存空间的值
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include<time.h>
#include<math.h>
#include<stdlib.h>
int main26()
{
int a = 10;
int b = 20;
const int* p = &a;//const修饰指针类型
p = &b;//正确
//*p = 100; 错误
printf("%d\n", *p);
return 0;
}

//修饰指针变量 int* const p;
//可以修改指针指向内存空间的值p
//不可以修改指针变量的值
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include<time.h>
#include<math.h>
#include<stdlib.h>
int main27()
{
int a = 10;
int b = 20;
int
const p = &a; //const修饰指针变量
//p = &b; 错误,不能改变p的值,可以改变*p的值
*p = 200;//正确
printf("%d\n", a);
return 0;
}

//&是取地址符号 是升维度的
//是取值符号是降维度的
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include<time.h>
#include<math.h>
#include<stdlib.h>
int main28()
{
int a = 10;
int b = 20;
const int
const p = &a;//const修饰指针类型和指针变量 只读指针
//p=&b; 报错
//p=100;报错
printf("%d\n", p);//对比证明下面的步骤改变p的值
int
pp = &p;//指针+*表示往前走一步 pp可以为p1、p2(获取p的地址)
*pp = &b;//*pp是一级指针的值–> 结果为20
//**pp = 100;//**pp是二级变量的值 结果为100
printf("%d\n", *p);
return 0;
}

修改一级指针对应空间的值就往p前面+ *

原文链接:http://blog.qmgua.com/?id=51

=========================================

http://blog.qmgua.com/ 为 “布尔博客” 唯一官方服务平台,请勿相信其他任何渠道。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

幸运的涛

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

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

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

打赏作者

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

抵扣说明:

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

余额充值