c语言_day6(完结)

目录

函数

格式:

函数的声明

函数的调用:函数名(实参)

形参和实参区别:

函数传参

值传递

地址传递

数组传递

开辟堆区空间

string函数族

strcpy

strncpy

strcat

strcmp

递归函数

结构体

格式:

结构体变量

赋值

访问

重定义typedef

结构体数组

初始化

结构体指针

赋值:

大小

结构体大小

结构体地址的连续性问题:

共用体

枚举

存储类型

extern外部引用


函数

函数三要素:功能、参数、返回值

格式:

[存储类型]   数据类型   函数名(形参列表)
{
		函数体;
		return  常量或变量或表达式;
}

常量或变量或表达式:数据类型要和定义函数的数据类型保持一致

当函数不需要返回值时,函数的数据类型是void,return语句可以没有

举例:

函数的声明

数据类型	函数名(形参列表)

函数的调用:函数名(实参)

1)不需要接收返回值和参数

2)不需要返回值,需要参数

3)需要返回值,不需要参数

4)需要参数,需要返回值

形参和实参区别:

形参是函数定义时,定义的形参变量。是形式上存在的参数,只有在电泳函数时才会开辟内存空间。
实参是调用函数时,实际传递的值。实际存在的值。

练习:

编写一个函数,函数的2个参数,第一个是一个字符,第二个是一个char *,返回字符串中该字符的个数。

参考:

返回字符串中某一字符在此字符串中首次出现的位置下标

函数传

值传递

单向传递,把实参传递给形参使用,改变形参,实参不受影响
(把值复制一份传递过去,对复制的内容进行了修改,原内容不变)

​​​​​​​

地址传递

双向传递,在函数中修改形参,实参会一起改变
(把变量的地址传递过去,通过地址对原内容修改)

​​​​​​​

数组传递

和地址传递一样,参数中如果存在数组的定义,也会认为是指针
(本质也会认为是地址传递,传递的是数组的首地址(一维数组)) 

sizeof==4

​​​​​​​

开辟堆区空间

​​​​​​​

malloc
#include <stdlib.h>
void *malloc(size_t size);
功能:在堆区开辟空间
参数:开辟的空间大小
返回值:成功:返回开辟的堆区空间首地址
		失败:NULL

void free(void *ptr);
功能:释放堆区空间
参数:堆区空间首地址
返回值:无

free(p);
p=NULL;

​​​​​​​

注意:
1.手动开辟堆区空间,要注意内存泄漏
2.使用完堆区空间后及时释放空间

思考:如下代码输出结果。
void fun(char *p)
	{
		p = (char *)malloc(32);
		strcpy(p, "hello");	
	}
	main()
	{
		char *m = NULL;
		fun(m);
		printf("%s\n", m);
	}
代码出现段错误,原因?

​​​​​​​思考下面代码能否正确运行,为什么?

1.

2

.

string函数族

​​​​​​​

strcpy

#include <string.h>
strlen
strcpy
#include <string.h>
char *strcpy(char *dest, const char *src);
功能:字符串的复制
参数:把src指向的字符串复制到dest;复制的同时会复制'\0'
	dest:目标字符串首地址
	src:原字符串首地址
返回值:目标字符串首地址

strncpy

       char *strncpy(char *dest, const char *src, size_t n);
功能:字符串的复制
参数:把src指向的字符串复制到dest;复制的同时会复制'\0'
	dest:目标字符串首地址
	src:原字符串首地址
	n:字符个数
返回值:目标字符串首地址

​​​​​​​

补充面试题:

strcat

#include <string.h>
char *strcat(char *dest, const char *src);
功能:字符串拼接	把dest后边的'\0'去掉后拼接src
参数:dest拼接的字符串存放位置
	src:要拼接的字符串
返回值:拼接后的字符串首地址

char *strncat(char *dest, const char *src, size_t n); //拼接src的前n个字符

strcmp

#include <string.h>
int strcmp(const char *s1, const char *s2);
功能:字符串的比较
参数:要比较的两个字符串的首地址
返回值:从字符串首个字符开始进行比较ASCII码值,如果相等会继续向下判断
	1	s1>s2
	-1	s1<s2
	0	s1=s2

递归函数

自己调用自己
1.执行过程分为两个阶段
1)递推阶段:从原问题出发,按递归公式从未知到已知,最终到达递归终止条件(只需了解)
2)回归阶段:按递归的终止条件求出结果,逆向逐步带入递归公式,回到原问题求解
3.递归的两个必要条件
(1)存在限制条件,当满足这个限制条件的时候,递归便不再继续.
(2)每次递归调用之后越来越接近这个限制条件

举个栗子:

结构体

用户自定义的数据类型,在结构体里可以包含若干个不同的数据类型的成员变量(也可以相同),

格式:

struct  结构体名
{
	数据类型	成员变量1;
	数据类型	成员变量2;
数据类型	成员变量3;
};
例:
struct star	//数据类型
{
    int id;
    char name[33];
    float height;
};
成员变量类型:基本数据类型(6个)、指针、数组、结构体等,但是不能是函数

结构体变量

通过结构体数据类型定义的变量
struct	结构体名	变量名;
1.先定义结构体,再定义结构体变量
struct  结构体名
{
	数据类型	成员变量1;
	数据类型	成员变量2;
数据类型	成员变量3;
};
struct	结构体名	变量名;

举个栗子:

1.

2.定义结构体同时,定义结构体变量

3.缺省结构体名

赋值

1.定义的同时直接{}赋值

2.定义变量时未初始化,然后对变量单独赋值

3.点等法

访问

结构体变量名.成员变量名

重定义typedef

typedef  int  size_t;

int a; //size_t  a;

1)定义结构体的同时重定义

2)先定义结构体,再重定义

typedef struct star ST;//ST数据类型
    ST s;
    ST *p=&s;

​​​​​​​

练习:创建一个名为student的结构体,包含姓名,学号,班级,分数,(数据类型自己定义),从终端输入学生的信息并打印。

参考:

扩展:

结构体数组

结构体类型相同的变量组成的数组

格式:

1)定义结构体同时定义结构体数组

2)先定义结构体,再定义结构体数组

​​​​​​​

初始化

1)定义结构体数组同时直接赋值

2)先定义,再赋值

练习:

创建一个名为student的结构体数组,包含学号,姓名,分数,(数据类型自己定义),从终端输入学生的信息并打印分数及格的学生信息(输入3人即可)

结构体指针

​​​​​​​

指向结构体变量的指针
格式:
struct  结构体名   *结构体指针名;

举个栗子:

赋值:

格式:指针变量名->成员变量名
p->id=1;
p->height=184;
(*p).id=2;
strcpy(p->name,"kun");

大小

本质是指针,大小是4
总结:
1.不能把结构体类型变量作为整体引用,只能对结构体类型变量中的各个成员变量分别引用
2. 如果成员变量本身属于另一种结构体类型,用若干个成员运算符一级级找到最低级的成员

举个栗子:

 练习:

创建一个结构体数组,数组名为book

结构体成员包含编号,书名,售价(数据类型自己设定)。写一个函数,包含两个形参,分别接收结构体数组的首

​​​​​​​

结构体大小

字节对齐原则 ---- 对齐8字节 比8字节小按照8字节开辟空间

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct demo
{
short a;// 2 开辟8字节
int b; //4 
double c;//8 开辟8字节
};
int main()
{
printf("%d\n", sizeof(struct demo)); // 16
return 0;
}

补充:

结构体开辟空间示意图

1.在32位系统下,默认的value值为4字节,判断结构体中类型最大成员的字节大小,和默认的value值进行比较,按小的数进行对齐
2.结构体成员进行对齐时遵循地址偏移量是成员类型大小的整数倍,double类型数据存放在4字节的整数倍上
3.结构体成员按顺序进行存储

为什么要字节对齐?

1) 平台原因:不是所有的硬件平台都能访问任意地址上的任意数据的;某些硬件平台只能在某些地址处取某些特定类型的数据,否则抛出硬件异常。(提高程序的移植性)

2)性能原因:数据结构(尤其是栈)应该尽可能地在自然边界上对齐。原因在于,为了访问未对齐的内存,处理器需要作两次内存访问;而对齐的内存访问仅需要一次访问。

3)内存原因:在设计结构体时,通过对齐规则尽可能优化结构体的空间大小至最小空间\

结构体地址的连续性问题:

问题:为什么short的首地址不是0x7ffd30ea8c65?

​​​​​​​

结构体补充:

共用体

不同类型的成员变量共用同一块地址空间
格式:
union 共用体名
{
	成员列表;
};
定义共用体变量
union  共用体名 变量名;

1) 共用体成员共用同一块地址空间
2) 赋值顺序以最后一次赋值为准
3) 共用体的大小为成员中类型最大的数据的大小

用共用体测大小端:

#include<stdio.h>
union val
{
    int a;
    char b;
};
union val v;
int main(int argc, char const *argv[])
{
    v.a=0x12345678;
    if(v.b==0x78)
        printf("小端\n");
    else
        printf(" da端\n");
    return 0;
}

枚举

用户自定义的数据类型,可以用来声明一组常数
格式:
enum 枚举名
{
	value1,
	value2,
value3,
...
};

​​​​​​​

未赋值时,常数默认从0开始,依次加1;

练习:

存储类型

auto  static  extern  register
auto
修饰变量,一般省略

static修饰变量和函数
修饰变量
1.变量存放位置在静态区;未初始化,在.bss区;已初始化,在.data区
2.生命周期为整个程序
修饰局部变量,和普通局部变量的作用域没有区别,但是生命周期被延长至整个程序
修饰全局变量,限制在本文件中使用
	3.被static修饰的变量只会初始化依次,初值赋值为0

#include<stdio.h>
void fun()
{
    static int a=5;
    a++;
    printf("%d\n",a);
}
int main(int argc, char const *argv[])
{
    fun();		//6
    fun();		//7
    return 0;
}

extern外部引用

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值