C语言入门

1、数据类型

1.1整型(int)

    int age = 10;//4 byte
    printf("%d\n", age);

1.2长整型(long)

    long b = 10;//4/8 byte
    printf("%d\n", b);

1.3单精度浮点型(float)

    float weight = 55.5;//4 byte
    printf("%f\n", weight);
    printf("%e\n", weight);//%e 以指数形式输出 float 类型,输出结果中的 e 小写

1.4双精度浮点型(double)

    double d_weight = 55.5;//8 byte
    printf("%lf\n", d_weight);
    printf("%le\n", d_weight);

1.5字符型(char)

    char ch1 = 'c';//1 byte
    printf("%c\n", ch1);

    char arr[] = "apple";//字符串
    printf("%s\n", arr);

2、操作符

2.1算数运算符

2.1.1除法

	float ans1 = 9 / 2;
	float ans2 = 9.0 / 2;

	printf("%f\n", ans1);//ans1=4.000000
	printf("%f\n", ans2);//ans2=4.500000

2.1.2取余

	//取余运算要求左右操作数必须为整数
	int ans1 = 9 % 2;
	float ans2 = 9 % 2;
	printf("%d\n", ans1);//ans1=1
	printf("%f\n", ans2);//ans2=1.000000

2.2关系运算符

2.2.1 大于/小于(>/<)

	//关系运算符的结果 1 和 0。(1代表true,0代表false)
	int ans1 = (10 > 0);
	int ans2 = (10 < 0);
	printf("%d\n", ans1);//ans1=1
	printf("%d\n", ans2);//ans2=0

2.2.2 不等于(!=) 

	int ans1 = (10 != 0);
	int ans2 = (10 != 10);
	printf("%d\n", ans1);//ans1=1
	printf("%d\n", ans2);//ans2=0

2.3逻辑运算符

2.3.1 逻辑与(&&)

	int ans1 = (10 != 0);
	int ans2 = (10 != 10);
	int ans3 = ans1 && ans2;
	int ans4 = ans1 && ans1;
	printf("%d\n", ans1);//ans1=1
	printf("%d\n", ans2);//ans2=0
	printf("%d\n", ans3);//ans3=0
	printf("%d\n", ans4);//ans4=1

2.3.2 逻辑或(||) 

	int ans1 = (10 != 0);
	int ans2 = (10 != 10);
	int ans3 = ans1 || ans2;
	int ans4 = ans1 || ans1;
	int ans5 = ans2 || ans2;

	printf("%d\n", ans1);//ans1=1
	printf("%d\n", ans2);//ans2=0
	printf("%d\n", ans3);//ans3=1
	printf("%d\n", ans4);//ans4=1
	printf("%d\n", ans5);//ans5=0

2.3.3 逻辑非(!) 

	int ans1 = (10 != 0);
	int ans2 = !ans1;

	printf("%d\n", ans1);//ans1=1
	printf("%d\n", ans2);//ans2=0

2.4位运算符

2.4.1 位与/或/反/异或(&、|、~、^)

	int ans1 = 0&3;//
	int ans2 =0|3;
	int ans3 = (~3);
	int ans4 = 3^5;//101^011=110

	printf("%d\n", ans1);//ans1=0
	printf("%d\n", ans2);//ans2=3
	printf("%d\n", ans3);//ans3=-4
	printf("%d\n", ans4);//ans3=6

2.4.2 位左移(<<)、位右移(>>)

	int ans1 = 4;
	int ans2 = 4;
	ans1 <<= 1;//ans1=ans1<<1;
	ans2 >>= 1;
	printf("%d\n", ans1);//ans1=8
	printf("%d\n", ans2);//ans2=2

2.4.3 前置/后置++

    int ans1 = 10;
	int ans2 = ++ans1;//先++,在使用

	printf("%d\n", ans1);//ans1=11
	printf("%d\n", ans2);//ans2=11
	int ans1 = 10;
	int ans2 = ans1++;//先使用,再++
	printf("%d\n", ans1);//ans1=11
	printf("%d\n", ans2);//asn2=10

2.4.4 三目操作符

	//exp1?exp2:exp3
	int a = 10;
	int b = 20;
	int max = a > b ? a : b;
	printf("%d\n", max);//max=20
	int a = 1;
	int b = 1;
	int c = 1;
	int ans = (a = a + 1, b = b + a, c = a + b + c);
	printf("%d\n", ans);//ans=6

3、分支语句 

3.1选择语句

3.1.1 if...else

	int a = 30, b = 20, max = 0;
	if (a > b)
	{
		max = a;
	}
	else
	{
		max = b;
	}
	printf("%d\n", max);

3.1.2 switch

	int day = 0;
	scanf("%d", &day);
	switch (day)
	{
	case 1:
		printf("实验室搬砖\n");
		break;
	case 2:
		printf("划水摸鱼\n");
		break;
	default:
		printf("出去玩\n");
	}

 3.2循环语句

3.2.1 while

    //while循环中,break用于终止永久的循环
	//continue用于跳过本次循环continue后的代码
	int i = 0;
	while (i<10)
	{
		printf("%d\n", i);
		i++;
	}

3.2.2 for

    //100-1000的水仙花数
	for (int i = 100; i < 1000; i++)
	{
		int a = 0, b = 0, c = 0;
		a = i / 100;//百位
		b = i / 10 % 10;//十位
		c = i % 10;//个位
		int num = a * a * a + b * b * b + c * c * c;
		if (num == i)
		{
			printf("%d\n", i);
		}
	}
	//前n项的阶乘的和
	int i = 1, j = 1, num = 0, sum = 0;
	scanf("%d", &num);
	for (i=1;i<=num;i++)
	{
		j = j * i;
		sum += j;
	}
	printf("%d\n", sum);

3.2.3 do...while

	//n的阶乘
	int i = 1, j = 1, num = 0;
	scanf("%d", &num);
	do
	{
		j = j * i;
		i++;
	} while (i <= num);
	{
		printf("%d\n", j);
	}

4、函数

4.1函数的调用

4.1.1值传递

#define  _CRT_SECURE_NO_WARNINGS 
#include<stdio.h>
//在调用函数中将原函数的值拷贝一份过去被调用的函数,在被调用函数中对该值的修改不会影响原函数的值。
void swap(int a, int b)
{
	int tmp = a;
	a = b;
	b = tmp;
}
int main()
{
	int a = 10;
	int b = 20;
	printf("交换前 a = %d b = %d\n", a, b);
	swap(a, b);
	printf("交换后 a = %d b = %d\n", a, b);
	return 0;
	system("pause");
}

 4.1.2地址传递 

#define  _CRT_SECURE_NO_WARNINGS 
#include<stdio.h>
//交换函数,使用指针
//在调用函数的时将原函数的值所在的地址拷贝一份过去,被调用函数对这个地址所作的修改会影响原来值。
void swap(int* pa, int* pb)
{
	int tmp = *pa;
	*pa = *pb;
	*pb = tmp;
}
int main()
{
	int a = 10;
	int b = 20;
	printf("交换前 a = %d b = %d\n", a, b);
	swap(&a, &b);
	printf("交换后 a = %d b = %d\n", a, b);
	return 0;
	system("pause");
}

4.1.3嵌套调用

#define _CRT_SECURE_NO_WARNINGS 1//取消警告
#include<stdio.h>
int text1() {
	printf("text1调用");
	return 0;
}
int text2() {
	text1();
	return 0;
}
int main() {
    texr2();
	return 0;
}

4.1.4链式访问 

#define  _CRT_SECURE_NO_WARNINGS 
#include<stdio.h>
#include<string.h>
int main()
{	//将一个函数的返回值作为另一个函数的一个参数
	int len = strlen("abc");
	printf("%d\n", len);
	//也可以直接写成:
	printf("%d\n", strlen("abc"));//链式访问
	return 0;
	system("pause");
}

4.2函数的参数

4.2.1实参

   //调用函数的时候,调用函数时写在函数名小括号后面的参数就叫实参
   //实参既可以放常量、变量、表达式
   swap(&a, &b);
   Max(a,b);

4.2.2形参 

    //定义函数的时候,写在函数名小括号后面的参数叫形参
    //看做是一个占位符,没有数据,只能等到函数被调用时接收传递进来的数据
    //交换函数,使用指针
    void swap(int* pa, int* pb)
    {
	   int tmp = *pa;
	   *pa = *pb;
	   *pb = tmp;
    }

4.3函数的递归

4.3.1按序输出

#define  _CRT_SECURE_NO_WARNINGS 
#include<stdio.h>
//函数递归
void print(unsigned int n)
{
	if (n > 9)
	{
		print(n / 10);
	}
	printf("%d ", n % 10);
}
int main()
{	
	unsigned int num = 1234;
	print(num);
	return 0;
	system("pause");
}

4.3.2求字符串长度

#define  _CRT_SECURE_NO_WARNINGS 
#include<stdio.h>
//函数递归
int my_strlen(char* str)
{
	if (*str != '\0')
		return 1 + my_strlen(str+1);
	else
		return 0;
}
int main()
{	
	char str[] = "hello";
	printf("%d\n", my_strlen(str));
	return 0;
	system("pause");
}

4.4.3阶乘

#define  _CRT_SECURE_NO_WARNINGS 
#include<stdio.h>
//函数递归
int main()
{	
	int num = 0, ret = 1;
	scanf("%d", &num);
	for (int i = 1; i <= num; i++)
	{
		ret = ret * i;
	}
	printf("%d", ret);
	return 0;
	system("pause");
}
#define  _CRT_SECURE_NO_WARNINGS 
#include<stdio.h>
//函数递归
int Fnc(int n)
{
	if (n > 1)
		return n * Fnc(n - 1);
	else
		return 1;
}
int main()
{	
	int n = 5;
	int ret = Fnc(n);
	
	printf("%d", ret);
	return 0;
	system("pause");
}

 4.4.4斐波那契数

#define  _CRT_SECURE_NO_WARNINGS 
#include<stdio.h>
//函数递归求斐波那契数
int Fib(int n)
{
	if (n <= 2)
		return 1;
	else
		return Fib(n - 1) + Fib(n - 2);
}
int main()
{	
	int n = 0;
	scanf("%d", &n);
	int ret = Fib(n);
	printf("%d", ret);
	return 0;
	system("pause");
}

5、数组

5.1定义

#define  _CRT_SECURE_NO_WARNINGS 
#include<stdio.h>
#include<string.h>
int main()
{
	//一维数组
	int arr1[5] = { 1,2,3,4,5 };
	int arr2[] = { 1,2,3 };
	char ch1[4] = { 'b','i','t' };//b i t \0
	char ch2[] = { 'b','i','t' };//b i t
	char ch3[5] = "bit";//b i t \0 0
	char ch4[] = "bit";//b i t \0

	//二维数组,行可省列不可省
	int arr[2][4] = {1,2,3,4,5,6,7,8};
	int arr1[2][2] = { {1,2},{1,2} };
	return 0;
}

6、指针

6.1指针类型

#define  _CRT_SECURE_NO_WARNINGS 
#include<stdio.h>
int main()
{
	//指针类型的意义
	//1、指针类型决定了指针在被解引用的时候访问几个字节
	//2、指针的类型决定了指针向前或者向后走一步有多大
    //int*指针,解引用访问4个字节;char*指针,解引用访问1个字节
	int arr[10] = { 0 };
	int *p = &arr;
	char *pc = &arr;
	printf("%p\n", p);//004FF720
	printf("%p\n", p + 1);//004FF724
	printf("%p\n", pc);//004FF720
	printf("%p\n", pc + 1);//004FF721
	return 0;
}
#define  _CRT_SECURE_NO_WARNINGS 
#include<stdio.h>
int main()
{
	char str1[] = "hello";
	char str2[] = "hello";
	char* str3 = "hello";
	char* str4 = "hello";
	printf("str1<==>%s\t*str1<==>%c\tstr1<==>%p\n", str1, *str1, str1);
	printf("str2<==>%s\t*str2<==>%c\tstr2<==>%p\n", str2, *str2, str2);
	printf("str3<==>%s\t*str3<==>%c\tstr3<==>%p\n", str3, *str3, str3);
	printf("str4<==>%s\t*str4<==>%c\tstr4<==>%p\n", str4, *str4, str4);
	return 0;
}

 习题一、

#define  _CRT_SECURE_NO_WARNINGS 
#include<stdio.h>
#include<string.h>
int main()
{
	//1、&a为数组地址
	//2、sizeof(a)取数组地址,其余为首元素地址
	int a[] = { 1,2,3,4,5 };
	int *p = (int*)(&a + 1);
	int *p1 = (int*)((int)a + 1);
	printf("%d %d\n", *(a + 1), *(p - 1));//2 5
	printf("%x %x\n", p[-1], *p1);//5 2000000
	return 0;
}

习题二、 

#define  _CRT_SECURE_NO_WARNINGS 
#include<stdio.h>
#include<string.h>
int main()
{
	//1、&a为数组地址
	//2、sizeof(a)取数组地址,其余为首元素地址
	int a[] = { 1,2,3,4,5 };
	int *p = (int*)(&a + 1);
	int *p1 = (int*)((int)a + 1);
	printf("%d %d\n", *(a + 1), *(p - 1));//2 5
	printf("%x %x\n", p[-1], *p1);//5 2000000
	return 0;
}
#define  _CRT_SECURE_NO_WARNINGS 
#include<stdio.h>
int main()
{
	//1、&a为数组地址
	//2、sizeof(a)取数组地址,其余为首元素地址
	int a[3][2] = { (0,1),(2,3),(4,5) };//逗号表达式,存放的1 3 5 0 0 0
	int*p;
	p = a[0];//首元素的地址
	printf("%d\n",p[0] );//1 p[0]==*(p+0)
	return 0;
}

6.2野指针 

6.2.1野指针成因

#define  _CRT_SECURE_NO_WARNINGS 
#include<stdio.h>
int main()
{
	//1. 指针未初始化
	int*pa;//局部变量指针未初始化,默认为随机值    
	*pa = 20;
	//2. 指针越界访问
	int arr[10] = { 0 };
	int*p = arr;
	int i = 0;
	for (i = 0; i <= 10; i++)
	{
		//当指针指向的范围超出数组arr的范围时,p就是野指针  
		*(p++) = i;
	}
	return 0;
}

6.2.2如何规避野指针

1. 指针初始化

2. 小心指针越界

3. 指针指向空间释放即使置NULL,0地址是无法访问的

4. 避免返回局部变量的地址

5. 指针使用之前检查有效性

6.3指针运算

6.3.1指针+、-整数

#define  _CRT_SECURE_NO_WARNINGS 
#include<stdio.h>
int main()
{
	int arr[] = { 0,1,2,3,4,5,6,7,8,9 };
	int*p = arr;
	int*pend = arr + 9;
	while (p<=pend) 
	{
		printf("%d\n", *p);
		p++;
	}
	return 0;
}

6.3.2指针-指针

#define  _CRT_SECURE_NO_WARNINGS 
#include<stdio.h>
int main()
{
	int arr[] = { 0,1,2,3,4,5,6,7,8,9 };
	int*p = arr;
	//相减前提指向同一空间
	printf("%d\n", arr[9]-arr[0]);//9
	printf("%d\n", sizeof(arr));//40
	printf("%d\n", sizeof(arr)/sizeof(arr[0]));	//10
	return 0;
}

6.3.3关系运算 

#define  _CRT_SECURE_NO_WARNINGS 
#include<stdio.h>
int main()
{
	int arr[] = { 1,2,3,4,5 };
	int *p;
	for (p = &arr[0]; p < &arr[5]; p++)
	{
		*p = 0;
		printf("%d\n", *p);
	}
	return 0;
}

6.4指针与数组 

6.4.1数组名

#define  _CRT_SECURE_NO_WARNINGS 
#include<stdio.h>
int main()
{
	//数组名代表数组首元素的地址
	int arr[] = { 1,2,3,4,5 };
	int *p = arr;
	for (int i=0;i<5;i++)
	{
		printf("%p<==>%p\t", &arr[i], p + i);
        printf("%d<==>%d\n", arr[i], *(p + i));
	}
	return 0;
}

6.4.2指针数组

#define  _CRT_SECURE_NO_WARNINGS 
#include<stdio.h>
int main()
{
	//存放指针的数组
	int arr[5] = { 1,2,3,4,5 };
	int* parr[5] = { 0 };
	for (int i = 0; i < 5; i++)
	{
		parr[i] = &arr[i];
		printf("%d<==>%p\n", *parr[i],parr[i]);
	}
	return 0;
}
#define  _CRT_SECURE_NO_WARNINGS 
#include<stdio.h>
#include<string.h>

int main()
{
	int a[] = { 0,1,2,3,4 };
	int b[] = { 0,1,2,3,4 };
	int c[] = { 0,1,2,3,4 };
	int *arr[] = { a,b,c };
	for (int i = 0; i < 3; i++)
	{
		for (int j = 0; j < 5; j++)
		{
			printf("%d ", *(arr[i] + j));
		}
		printf("\n");
	}
	return 0;
}

6.4.3数组指针 

#define  _CRT_SECURE_NO_WARNINGS 
#include<stdio.h>
int main()
{
	int arr[5] = { 1,2,3,4,5 };
	int*p1 = arr;//值相同,类型不同
	int(*p2)[5] = &arr;
	for (int i = 0; i < 5; i++)
	{
		printf("%d ", *p1+i);
	}
	printf("\n");
	for (int i = 0; i < 5; i++)
	{
		printf("%d ", *((*p2) + i));
	}
	printf("\n");
	printf("p1<==>%p\t p1+1<==>%p\n", p1, p1 + 1);
	printf("p2<==>%p\t p2+1<==>%p\n", p2, p2 + 1);	
	return 0;
}
#define  _CRT_SECURE_NO_WARNINGS 
#include<stdio.h>
int main()
{
	int arr[3][5] = 
	{ {1,2,3,4,5},
	  {1,2,3,4,5},
	  {1,2,3,4,5} };
	int(*p)[5] = arr;//数组名代表首元素地址,首元素为第一行
	for (int i = 0; i < 3; i++)
	{
		for (int j = 0; j < 5; j++)
		{
			printf("%d", *(*(p + i) + j));//p+i为第i行arr[i][5];
		}
		printf("\n");
	}		
	return 0;
}

 6.5函数指针

6.5.1函数指针

#define  _CRT_SECURE_NO_WARNINGS 
#include<stdio.h>
int Add(int x, int y)
{
	return x + y;
}
int main()
{
	//函数名==&函数名
	//Add==&Add=*p==p
	int(*p)(int, int) = &Add;
	printf("%d %d", p(3,5),(*p)(3, 5));
	return 0;
}

 6.5.2函数指针数组

#define  _CRT_SECURE_NO_WARNINGS 
#include<stdio.h>
int Add(int x, int y)
{
	return x + y;
}
int Sub(int x, int y)
{
	return x - y;
}
int Mul(int x, int y)
{
	return x * y;
}
int Div(int x, int y)
{
	return x / y;
}
void menu()
{
	printf("*************************\n");
	printf("******1.Add   2.Sub******\n");
	printf("******3.Mul   4.Div******\n");
	printf("*******  0.exit  ********\n");
	printf("*************************\n");
}
int main()
{
	int input = 0;
	do
	{
		menu();
		int(*Arr[5])(int, int) = { NULL,Add,Sub,Mul,Div };
		int x, y, ans = 0;
		printf("请选择:\n");
		scanf("%d", &input);
		if (input >= 1 && input <= 4)
		{
			printf("请输入两个数:\n");
			scanf("%d%d", &x, &y);
			ans = (Arr[input])(x, y);
			printf("ans=%d\n", ans);
		}
		else if(input==0)
		{
			printf("退出\n");
			break;
		}
		else
		{
			printf("请重新选择:\n");
		}
	} while (input);
	return 0;
}

6.5.3回调函数

#define  _CRT_SECURE_NO_WARNINGS 
#include<stdio.h>
int Add(int x, int y)
{
	return x + y;
}
int Sub(int x, int y)
{
	return x - y;
}
int Mul(int x, int y)
{
	return x * y;
}
int Div(int x, int y)
{
	return x / y;
}
void menu()
{
	printf("*************************\n");
	printf("******1.Add   2.Sub******\n");
	printf("******3.Mul   4.Div******\n");
	printf("*******  0.exit  ********\n");
	printf("*************************\n");
}

//回调函数
//int(*p)(int,int)=Add函数指针
int Calc(int(*p)(int, int))
{
	int x, y = 0;
	printf("请输入两个数:\n");
	scanf("%d%d", &x, &y);
	return p(x, y);
}
int main()
{
	int input = 0;
	do
	{
		menu();
		int ans = 0;
		printf("请选择:\n");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			ans = Calc(Add);
			printf("ans=%d\n", ans);
			break;
		case 2:
			ans = Calc(Sub);
			printf("ans=%d\n", ans);
			break;
		case 3:
			ans = Calc(Mul);
			printf("ans=%d\n", ans);
			break;
		case 4:
			ans = Calc(Div);
			printf("ans=%d\n", ans);
			break;
		case 0:
			printf("退出\n");
			break;
		default:
			printf("请重新选择:\n");
			break;		
		}
	} while (input);
	return 0;
}

6.5.4模拟qsort

#define  _CRT_SECURE_NO_WARNINGS 
#include<stdio.h>
void Swap(char*buf1, char*buf2, int width)
{
	for (int i = 0; i < width; i++)
	{
		char temp = *buf1;
		*buf1 = *buf2;
		*buf2 = temp;
		buf1++;
		buf2++;
	}
}

//模拟qsort
void bubble_sort(void* base, int len, int width, int(*cmp)(const void*e1, const void*e2))
{
	for(int i=0;i<len-1;i++)
	{
		for (int j = 0; j < len - 1 - i; j++)
		{
			if (cmp((char*)base + j * width, (char*)base + (j + 1)*width) > 0)
			{
				Swap((char*)base + j * width, (char*)base + (j + 1)*width, width);
			}
		}
	}
}

void print_arr(int arr[], int len)
{
	for (int i = 0; i < len; i++)
	{
		printf(" %d", arr[i]);
	}
	printf("\n");
}
int cmp_int(const void *e1, const void *e2)
{
	return *(int*)e1 - *(int*)e2;
}
int main()
{
	int arr[10] = { 9,8,7,6,5,4,3,2,1,0 };
	int len = sizeof(arr) / sizeof(arr[0]);
	int width = sizeof(arr[0]);
	print_arr(arr, len);
	bubble_sort(arr, len, width, cmp_int);
	print_arr(arr, len);	
	return 0;
}

 6.6二级指针

    int a = 10;
	int* pa = &a;//*pa==a
	int** ppa = &pa;//*ppa=pa,**ppa==*pa==a
	printf("%d %d %d\n", a, *pa,**ppa);//10 10 10	

7、自定义类型

7.1结构体

7.1.1结构体创建

#define  _CRT_SECURE_NO_WARNINGS 
#include<stdio.h>
struct Stu
{
	char name[20];
	int id;
	int age;
	int scores;
};
void print1(struct Stu s)
{
	printf("%s %d %d %d\n", s.name, s.id, s.age, s.scores);
}
void print2(struct Stu *p)
{
	printf("%s %d %d %d\n", p->name, p->id, p->age, p->scores);
}
int main()
{
	Stu s = { "jack",2022204309,20,98 };
	Stu*p = &s;
	printf("%s %d %d %d\n", s.name, s.id, s.age, s.scores);
	printf("%s %d %d %d\n", p->name, p->id, p->age, p->scores);
	print1(s);//值传递
	print1(*p);//地址传递
	return 0;
}

7.1.2结构体内存对齐 

#define  _CRT_SECURE_NO_WARNINGS 
#include<stdio.h>
//结构体内存对齐
//让占用空间小的成员尽量集中在一起
struct S1
{
	char a;
	char b;
	int i;
};
struct S2
{
	char a;
	int i;
	char b;
};
int main()
{
	struct S1 s1 = { 0 };
	struct S2 s2 = { 0 };
	printf("%d\n", sizeof(s1));//8
	printf("%d\n", sizeof(s2));//12
	return 0;
}

7.1.3修改默认对齐数 

#define  _CRT_SECURE_NO_WARNINGS 
#include<stdio.h>
//结构体内存对齐
//默认对齐数为8
//把对齐数改为1
#pragma pack(1)
struct S1
{
	char a;
	char b;
	int i;
};
#pragma pack()//只有s1对齐数为1

struct S2
{
	char a;
	char b;
	int i;
};
int main()
{
	struct S1 s1 = { 0 };
	struct S2 s2 = { 0 };
	printf("%d\n", sizeof(s1));//6
	printf("%d\n", sizeof(s2));//8
	return 0;
}

7.2位段

#define  _CRT_SECURE_NO_WARNINGS 
#include<stdio.h>
//位段的声明与结构体类似
//1.位段成员必须是int/ unsigend int /signed int/char
//2.成员名后有冒号和数字
struct A
{
	//4个字节--32bit
	int _a : 2;//占2bit
	int _b : 5;//5bit
	int _c : 10;//10bit
	//4个字节--32bit
	int _d : 30;//30bit
};
int main()
{
	
	printf("%d\n", sizeof( struct A));//8
	return 0;
}

7.3枚举 

7.4联合体

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
//联合体成员共用一块内存空间
int check_sys1()
{
	int a = 1;
	if (*(char*)&a == 1)
	{
		return 1;
	}
	else
	{
		return 0;
	}
}
int check_sys2()
{
	union Un
	{
		char c;
		int i;
	}u;
	u.i = 1;
	return u.c;
}

int main()
{
	int ret1 = check_sys1();
	int ret2 = check_sys2();//利用联合体判断大小端
	if (ret1 == 1)
		printf("小端\n");
	else
		printf("大端\n");
	if (ret2 == 1)
		printf("小端\n");
	else
		printf("大端\n");

	
	return 0;
}

8、内存函数

8.1 memcpy

#include<stdio.h>
#include<assert.h>
void* my_memcpy(void* dest, const void* src, int num)
{
	void* ret = dest;
	assert(dest && src);
	while (num--)
	{
		*(char*)dest = *(char*)src;
		dest = (char*)dest + 1;
		src = (char*)src + 1;
	}
	return ret;
}
int main()
{
	char ch1[] = "abbbcdef";
	char ch2[] = "bbc";
	char* ret = my_memcpy(ch2, ch1,3);
	printf("%s\n", ret);	
	return 0;
}

8.2动态内存开辟

8.2.1 malloc

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<malloc.h>
int main()
{
	//开辟10个整型空间,存放在栈区
	int arr[10] = { 0 };
	//动态内存开辟
	int* p = (int*)malloc(10 * sizeof(int));
	//如果分配成功则返回指向被分配内存的指针,否则返回空指针NULL
	if (p == NULL)
	{
		perror("main");
		return 0;
	}
	for (int i = 0; i < 10; i++)
	{
		*(p + i) = i;
		printf("%d ", p[i]);
	}
	//使用完成一定要释放空间,否则会造内存泄漏。
	free(p);//作用:释放给指针变量分配的内存空间。
	p = NULL;//使用后该指针变量一定要重新指向NULL,防止悬空指针(失效指针),规避错误操作。
	return 0;
}

 8.2.3 realloc

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<malloc.h>
int main()
{
	//开辟10个整型空间,存放在栈区
	int arr[10] = { 0 };
	//动态内存开辟
	int* p = (int*)malloc(10 * sizeof(int));
	if (p == NULL)
	{
		perror("main");
		return 0;
	}
	for (int i = 0; i < 10; i++)
	{
		*(p + i) = i;
		printf("%d ", p[i]);
	}

	//这里需要p指向更大的空间,20个int
	int *ptr=realloc(p, 20 * sizeof(int));

	//如果原空间之后有足够的空间就可以直接追加,然后返回调整之后的空间的起始位置地址
	//如果没有足够的空间,重新找一个新的内存区域,将原数据拷贝过去再追加,返回新空间的起始位置地址
	if (ptr != NULL)
	{
		p = ptr;
	}
	free(p);//释放内存空间。
	p = NULL;//防止悬空指针
	return 0;
}

9、文件

9.1读写文件

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
int main()
{
	FILE* pf = fopen("test_9.2.txt", "w");
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}
	//写文件
	fputc('t', pf);
	fputc('j', pf);
	fputc('u', pf);
	fputc('\n', pf);
	fputs("Tianjin University\n", pf);
	fputs("Peiyang University\n", pf);
	//关闭文件
	fclose(pf);
	pf = NULL;
	return 0;
}
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
struct S
{
	char arr[10];
	int num;
	float fn;
};
int main()
{
	struct S s1 = { "Tiangjin",125,9.2f };
	FILE* pf = fopen("test_9.2.txt", "w");
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}
	//对格式化数据进行写文件
	//fprintf(pf, "%s %d %f", s1.arr, s1.num, s1.fn);
	
	// 二进制写入
	fwrite(&s1, sizeof(struct S), 1, pf);
	//关闭文件
	fclose(pf);
	pf = NULL;
	return 0;
}
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
struct S
{
	char arr[10];
	int num;
	float fn;
};
int main()
{
	struct S s1 = { "Tiangjin",125,9.2f };
	struct S s2 = { 0 };
	char ch[100] = { 0 };
	//把格式化数据改成字符串
	sprintf(ch, "%s %d %f", s1.arr, s1.num, s1.fn);
	printf("%s\n", ch);
	//逆过程,还原
	sscanf(ch, "%s %d %f\n", s2.arr, &(s2.num), &(s2.fn));
	printf("%s %d %f\n", s2.arr,s2.num,s2.fn);
	
	return 0;
}

9.2随机读写 

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
int main()
{
	FILE* pf = fopen("test.txt", "r");
	if (pf == NULL)
	{
		perror("fopen");
		return 1;
	}
	//读取文件
	int ret = fgetc(pf);
	printf("%c ", ret);//a
	ret = fgetc(pf);
	printf("%c ", ret); //b
	//文件随机读写
	//调整文件指针
	fseek(pf, 2, SEEK_CUR);//当前位置后偏移2byte
	ret = fgetc(pf);
	printf("%c\n", ret);//e

	int ret1 = ftell(pf);//告知偏移量
	printf("%d\n", ret1);//5

	//文件指针回到起始位置
	rewind(pf);
    ret1 = ftell(pf);
	printf("%d\n", ret1);//0
	//关闭文件
	fclose(pf);
	pf = NULL;
	return 0;
}

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Jay-juice

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

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

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

打赏作者

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

抵扣说明:

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

余额充值