课堂代码以及练习
值传递、地址传递、值返回、地址返回
#include<stdio.h>
void swap(int m,int n);
void fun(int *p,int *q);
void gun(int *p,int *q);
int hun();
int *iun();
int main(int argc, const char *argv[])
{
int num=520;
int key=1314;
swap(num,key);
printf("调用swap后主函数中num=%d,key=%d\n",num,key); //还是520,1314,因为是值传递,对主函数中变量的值没有影响
fun(&num,&key);
printf("调用fun后主函数中num=%d,key=%d\n",num,key); //还是520,1314,虽然传过去的是指针,但是因为函数中交换的是接受指针的指针变量的指向,本质还是值传递,对主函数中变量的值没有影响
gun(&num,&key);
printf("调用gun后主函数中num=%d,key=%d\n",num,key); //是1314,520,传过去指针,并且函数内将指针变量指向的内容交换了,也就是对主函数中变量值进行了交换
printf("调用hun后返回值为%d\n",hun()); //返回了一个int型的数值,需要接收,否则就会消失,并且函数的返回值是右值,无法通过hun()=456这样的语句反向赋值
int *ptr = iun(); //返回值是一个int*类型的变量,需要同样数据类型的ptr接收,并且由于函数中的变量使用了static修饰,并没有被回收,依然存在
printf("iun值为%d\n",*ptr);
*iun()=555; //并且返回值是左值,因此可以直接通过这样的语句,反过来给函数中的value赋值
printf("iun值%d\n",*iun());
return 0;
}
/*************************值传递************************/
void swap(int m,int n){
int temp = 0;
temp = m;
m = n;
n = temp;
printf("m=%d ,n=%d\n",m,n);
}
/************************值传递*****************************/
void fun(int *p,int *q){
int *temp=NULL;
temp = p;
p = q;
q = temp;
printf("*p=%d,*q=%d\n",*p,*q);
}
/*********************地址传递********************************/
void gun(int *p,int *q){
int temp=0;
temp = *p;
*p = *q;
*q = temp;
printf("*p=%d,*q=%d\n",*p,*q);
}
/***********************值返回********************************/
int hun(){
int value = 666;
return value;
}
/*************************地址返回*****************************/
int *iun(){
static int value = 999;
return &value;
}
内存分区
#include<stdio.h>
#include<stdlib.h>
int m; //全局区的.bss段
int n = 520; //全局区的.data段
static int k; //未初始化的静态变量,全局区 .bss段
static int l = 666; //已初始化的静态变了,全局区的.data段
char arr[32]="hello world"; //arr在.data段,hello world在ro段
char *p = "hello"; //指针在.data段,“hello”在.ro段
int main(int argc, const char *argv[])
{
double b = 999.9; //局部变量在栈区申请
int a;//局部变量,在栈区申请,初始值为随机值
printf("&a=%p,&b=%p\n",&a,&b);
static int c; //静态局部变量,在全局区的.bss段申请
static int d = 520; //静态局部变量初始化,在全局区的.data段
char *q = "nihao"; //q在栈区申请的8字节,但是“nihao”在全局区的.ro段
char r[32]="hello world"; //数组在栈区申请,“hello world”在全局区的.ro段
int *ptr = (int *)malloc(sizeof(int)); //ptr在栈区,申请的空间在堆区,初始值为随机值
return 0;
}
动态内存分配和回收(malloc、free)
#include<stdio.h>
#include<stdlib.h>
int main(int argc, const char *argv[])
{
//在堆区申请一个4字节的空间大小
int *p1 = (int *)malloc(4);
printf("*p1=%d\n",*p1);
//申请一个int类型的大小
int *p2 = (int *)malloc(sizeof(int));
*p2 = 520; //给堆区空间进行赋值
printf("*p2=%d\n",*p2);
//连续申请5个int类型大小
int *p3 = (int *)malloc(sizeof(int)*5);
//输出默认值
int i = 0;
for(i=0;i<5;i++){
printf("%d\t",p3[i]);
}
putchar(10);
//释放堆区空间
free(p1);
p1 = NULL;
free(p2);
p2 = NULL;
free(p3);
p3 = NULL;
return 0;
}
练习:要求在堆区申请6个int类型空间存放6名学生的成绩,分别使用函数实现申请空间、输入学生成绩、输出学生成绩、对学生进行升序排序、释放空间
#include<stdio.h>
#include<stdlib.h>
int *memory(int num);
void stuScoIn(int *p,int len);
void stuScoTurn(int *p,int len);
void stuScoOu(int *p,int len);
void myFree(int **p);
int main(int argc, const char *argv[])
{
int num = 6;
int *sco = memory(num); //调用申请空间函数,在堆区申请6个int大小的空间
stuScoIn(sco,num); //调用输入函数完成成绩的录入功能
stuScoTurn(sco,num); //调用排序函数
stuScoOu(sco,num); //调用输出函数
myFree(&sco); //调用内存释放函数
if(NULL == sco){
printf("空间释放成功\n");
}
return 0;
}
//定义从堆区申请空间的函数,num表示要申请空间的个数
int *memory(int num){
int *ptr = (int *)malloc(sizeof(int)*num); //从堆区申请num个int类型的大小空间
if(ptr == NULL){
printf("申请空间失败\n");
return NULL;
}else{
printf("申请空间成功\n");
return ptr;
}
}
//定义输入函数,ptr表示指向堆区空间的地址,num表示堆区空间元素个数
void stuScoIn(int *p,int len){
int i = 0;
if(NULL != p){
for(i=0; i<len; i++){
scanf("%d",p+i);
}
}
}
//定义冒泡排序函数
void stuScoTurn(int *p,int len){
int i = 0;
int j = 0;
int tmp = 0;
for(i=1; i<len; i++){ //排序趟数,从1开始
for(j=0; j<len-i; j++){ //控制元素以及每趟的比较次数
if(*(p+j)>*(p+j+1)){ //升序排列
tmp = *(p+j);
*(p+j) = *(p+j+1);
*(p+j+1) = tmp;
}
}
}
}
void stuScoOu(int *p,int len){
int i = 0;
for(i=0; i<len; i++){
printf("%d\t",*(p+i));
}
putchar(10);
}
//定义释放空间函数
void myFree(int **p){
if(NULL != p){
free(*p);
*p = NULL;
}
}
类型重定义
#include<stdio.h>
#include<string.h>
typedef unsigned short int uint16;//将无符号短整形重命名为uint16
typedef int *Ptr_i;//将int *类型重命名为Ptr_i
typedef char String[10];//将int[10]重命名为String
typedef int (*Ptr_NG)[4];
int main(int argc, const char *argv[])
{
uint16 num = 520; //等价于unsigned short int num = 520
printf("sizeof num = %ld\n",sizeof(num));
printf("num = %d\n",num);
Ptr_i p1=NULL;//此时p1是指针变量,int *p1
printf("sizeof p1 = %ld\n",sizeof(p1));
String s1 = {0}; //定义长度为10的字符数组
strcpy(s1,"hello");
puts(s1);
printf("sizeof s1 = %ld\n",sizeof(s1));
printf("strlen s1 = %ld\n",strlen(s1));
int numG[2][4] = {1,2,3,4,5,6,7,8};
Ptr_NG p2 = numG;
printf("*(*(p2+1))=%d\n",*(*(p2+1))); //观察解引用的逻辑判断是否符合数组指针的逻辑
printf("numG[1][0]=%d\n",numG[1][0]);
return 0;
}
给类型起多个名
#include<stdio.h>
typedef int *Ptr_i,int32;//int32是一个int类型的重命名
//Prt_i是int*类型的重命名
int main(int argc, const char *argv[])
{
int32 num; //nunm是一个int类型的变量
Ptr_i p; //p是一个int×类型的变量
printf("sizeof num = %ld\nsizeof p = %ld\n",sizeof(num),sizeof(p)); //4 8
return 0;
}
类型重定义与宏定义的区别
#include<stdio.h>
#define int32 int //会将int32替换成int
typedef unsigned int uint32;
#define ptr_i int*
typedef int *pptr_i;
int main(int argc, const char *argv[])
{
int32 num = 0;
uint32 key = 0;
ptr_i a,b;
pptr_i m,n;
printf("sizeof a = %ld\n",sizeof(a)); //8,a是int*型
printf("sizeof b = %ld\n",sizeof(b)); //4,b是int型
printf("sizeof m = %ld\n",sizeof(m)); //8,c是int*型
printf("sizeof n = %ld\n",sizeof(n)); //8,d是int*型
return 0;
}
结构体变量的初始化以及变量访问和结构体指针访问成员
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
//定义一个英雄结构体类型
struct Hero
{
char name[20];//姓名,构造数据类型
int Hp; //血量
double speed; //基础移速
int kill; //人头数
}h3 = {"盖伦",3500,500,5};
//练习:定义一个商品类型,成员属性:商品名称、产地、单价、重量
#if 1
struct Goods
{
char name[32];
char position[32];
float price;
float weight;
};
#endif
#if 1
struct //无名结构体
{
char name[32];
char position[32];
float price;
float weight;
}g1 = {"三鹿奶粉","China",350,1000};
#endif
int main(int argc, const char *argv[])
{
//使用英雄类型定义一个英雄变量
struct Hero h1 ={"亚索",596,340,0}; //此时定义了一个英雄变量h1
//定义英雄变量,指定某个成员进行赋值
struct Hero h2 = {.Hp=2000,.speed=1000};
//输出英雄变量h1中的所有内容
printf("h1.name = %s\n",h1.name);
printf("h1.Hp = %d\n",h1.Hp);
printf("h1.speed = %lf\n",h1.speed);
printf("h1.kill = %d\n",h1.kill);
struct Hero *ptr = (struct Hero*)malloc(sizeof(struct Hero));
strcpy(ptr->name,"亚瑟");//使用结构体指针进行赋值
ptr->Hp = 3000;
ptr->speed = 350;
ptr->kill = 3;
//输出英雄指针指向堆区空间中的内容
printf("英雄信息:%s\t%d\t%lf\t%d\n",ptr->name,ptr->Hp,ptr->speed,ptr->kill);
free(ptr);
ptr=NULL;
return 0;
}
练习:使用商品结构体定义一个商品变量,不用初始化,使用scanf将每个属性进行输入
#include<stdio.h>
struct Goods
{
char name[32];
char position[32];
float price;
float weight;
};
int main(int argc, const char *argv[])
{
struct Goods g1; //定义结构体变量
printf("请输入商品名称:");
scanf("%s",g1.name);//采用‘.’的方式,采用结构体变量的方式进行赋值
printf("请输入商品产地:");
scanf("%s",g1.position);
printf("请输入商品价格:");
scanf("%f",&g1.price);
printf("请输入商品重量:");
scanf("%f",&g1.weight);
putchar(10);
printf("商品名称:%s\n",g1.name);//采用‘.’的方式,采用结构体变量的方式进行输出
printf("商品产地:%s\n",g1.position);
printf("商品价格:%f\n",g1.price);
printf("商品重量:%f\n",g1.weight);
return 0;
}
思维导图