C语言 内存函数 自定义类型 结构体 枚举 联合

perror

在这里插入图片描述

#include <stdio.h>
#include <errno.h>
#include <string.h>

//strerror
//perror与上相关  更加方便直接打印错误信息   上边需要先将错误码转换为错误信息  再用printf打印
//
int main()
{
	//打开文件失败的时候,会返回NULL
	FILE* pf = fopen("test.txt", "r");
	//0   "no error"
	if (pf == NULL)
	{
		//printf("%s\n", strerror(errno));   strerror他会把错误码所对应的错误信息的首字符地址返回来。%s打印可以打印出一个字符串
		perror("fopen");//这个括号里是自定义信息  想加什么加什么  会在错误信息前显示
		return 1;
	}
	//读文件
	// 
	//关闭文件
	fclose(pf);
	pf = NULL;
	return 0;
}

字符分类函数

在这里插入图片描述

int main()
{
	char ch = 'a';
	//isdigit  如果是数字字符返回非0的值,如果不是数字字符,返回0

	if (ch >= 'A' && ch <= 'Z')
	{

	}

	//int ret = isdigit(ch);
	//int ret = islower(ch);
	//printf("%d\n", ret);

	return 0;
}

是想要的就返回非0 不是想要的就返回0

tolower转小写 toupper转大写

int main()
{
	char arr[20] = { 0 };
	scanf("%s", arr);
	int i = 0;
	while (arr[i] != '\0')
	{
		if (isupper(arr[i]))
		{
			arr[i] = tolower(arr[i]);//转化为小写在放到原位置
		}
		printf("%c ", arr[i]);
		i++;
	}

	return 0;
}

内存函数

*void memcpy( void dest, const void src, size_t count );
size表示要拷贝多大空间 单位是字节
** memcpy 内存块拷贝函数

int main()
{
	int arr1[10] = { 1,2,3,4,5,6,7,8,9,10 };
	//01 00 00 00 02 00 00 00 ...
	int arr2[20] = { 0 };
	//strcpy()
	//char* strcpy(char* dest, const char* src)
	return 0;
}

如上代码 我们之前所学的字符串拷贝函数肯定是不行的

int main()
{
	int arr1[10] = { 1,2,3,4,5,6,7,8,9,10 };
	int arr2[10] = { 0 };


	memcpy(arr2, arr1, 20); //把arr1前5个内容拷贝到arr1 因为拷贝单位是字节  一个整型4个字节
	return 0;
}

my_memcpy

#include <assert.h>

void* my_memcpy(void* dest, const void*src, size_t num)
{
	void* ret = dest;  //代码要求返回dest  但是下面dest已经往后走了 所以一开始要把存起来 以备后续返回
	assert(dest && src);

	
	
		while (num--)//总共要拷贝的字节数  循环四次  每次搞定四个字节
		{
			*(char*)dest = *(char*)src;//强制类型转换意思是void不能直接解引用
			dest = (char*)dest + 1;//拷贝完一次后往后走
			src = (char*)src + 1;
		}

	return ret;
}


int main()
{
	int arr1[10] = { 1,2,3,4,5,6,7,8,9,10 };
	int arr2[10] = { 0 };

	my_memcpy(arr2, arr1, 20);

	return 0;
}

int arr1[10] = { 1,2,3,4,5,6,7,8,9,10 }; 接下来想把12345 放到34567这块空间 源头从1 目的地3开始

int main()
{
	int arr1[10] = { 1,2,3,4,5,6,7,8,9,10 };
	//               1 2 1 2 3 4 5 8 9 10   应该出现的样子
	//my_memmove(arr1+2, arr1, 20);
	//memmove(arr1, arr1+2, 20);
	memmove(arr1+2, arr1, 20);   //加0指向1 加1指向2加2指向3

	//memcpy函数应该拷贝不重叠的内存
//memmove函数可以处理内存重叠的情况

	return 0;
}

模拟实现 my_memove

void* my_memmove(void* dest, const void*src, size_t num)
{
	void* ret = dest;
	assert(dest && src);

	if (dest < src)
	{
		//前->后
		while (num--)
		{
			*(char*)dest = *(char*)src;
			dest = (char*)dest + 1;
			src = (char*)src + 1;
		}
	}
	else 
	{
		//后->前
		while (num--)
		{
			//20先进来  减减效果产生来到这已经变成19
			*((char*)dest + num) = *((char*)src + num);//从后向前 必须要源头和目标的都是从后开始
		}
	}
	return ret;
}



//可以把元数据 从前向后拷贝 也可以从后向前拷贝
//从低地址往高地址拷贝时, 先拷贝高地址, 再拷贝低地址
//从高地址往低地址拷贝时, 先拷贝低地址, 再拷贝高地址
int main()
{
	int arr1[10] = { 1,2,3,4,5,6,7,8,9,10 };
	//               1 2 1 2 3 4 5 8 9 10   应该出现的样子
	//my_memmove(arr1+2, arr1, 20);
	//memmove(arr1, arr1+2, 20);
	my_memmove(arr1+2, arr1, 20);   //加0指向1 加1指向2加2指向3

	//memcpy函数应该拷贝不重叠的内存
//memmove函数可以处理内存重叠的情况

	return 0;
}

在这里插入图片描述

memcmp (内存比较)

int main()
{
	float arr1[] = { 1.0, 2.0,3.0,4.0 };
	float arr2[] = { 1.0, 3.0 };
	int ret = memcmp(arr1, arr2, 8);    //-1   相同返回值0  如果第一个字符串大于第二个返回1  如果第一个小于第二个返回(小于0的)-1
	//memcmp - strcmp
	printf("%d\n", ret);

	return 0;
}

在这里插入图片描述

memset

在这里插入图片描述
把ptr所指向的那块空间的前num个字节的内容设置成我指定的value值

int main()
{
	//40
	int arr[10] = { 0 };//20
	memset(arr, 1, 20);//以字节为单位设置内存的
	//01 00 00 00    这是1
	//01 01 01 01    这肯定不是
	return 0;
}

自定义类型

结构体声明(结构体是定义一个复杂对象)

struct Book  //关键字和标签名
{
	char name[20];   //描述所需要的属性
	int price;
	char id[12];
}b4,b5,b6;//b4,b5,b6是全局的    

上面类型如何使用   类型是用来创建变量


int main()
{
	//b1,b2,b3是局部变量
	struct Book b1;
	struct Book b2;
	struct Book b3;
    类似于  int  b1

	return 0;
}

在这里插入图片描述
圈起来的作用相同 但是作用域不同 局部和全局

特殊声明

匿名结构体类型    用这个类型创建了个变量叫s   这个类型创建好后只能用一次  后面就不能再创建
struct
{
	char c;
	int i;
	char ch;
	double d;
} s;
struct
{
	char c;
	int i;
	char ch;
	double d;
} s;

struct
{
	char c;
	int i;
	char ch;
	double d;
}* ps;

int main()
{
	ps = &s;
	
	return 0;
}

编译器认为这是错的

结构体自引用

结构体可以包含结构体

struct A
{
	int i;
	char c;
};

struct B
{
	char c;
	struct A sa;
	double d;
};

但是结构体里不能包含自己

//struct N
//{
//	int d;//4
//	struct N n;
//}
//int main()
//{
//	struct N sn;//
//
//	return 0;
//}

什么叫结构体自引用如下
在这里插入图片描述

struct Node  //我自己能找到跟自己同类型的下一个元素
{
	int data;
	struct Node* next;
};

结构体变量的定义和初始化

struct S
{
	char c;
	int i;
}s1, s2;

struct B
{
	double d;
	struct S s;
	char c;
};
int main()
{
	//struct S s3 = {'x', 20};
	struct B sb = { 3.14, {'w', 100},'q' };
	//.   变量
	//->  指针
	printf("%lf %c %d %c\n", sb.d, sb.s.c, sb.s.i, sb.c);

	return 0;
}

结构体内存对齐

结构体占多大内存空间

struct S
{
	int i;//4
	char c;//1
};

struct S2
{
	char c1;//1
	int i;//4
	char c2;//1
};

//结构体内存对齐

int main()
{
	struct S s = {0};
	printf("%d\n", sizeof(s));//8

	struct S2 s2 = { 0 };
	printf("%d\n", sizeof(s2));//12

	return 0;
}

下篇讲解

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值