C语言学习笔记

1. 指针

  • 如果数组作为函数参数,数组形参会退化为指针
void printf_arry(int a[1])
// 相当于
void printf_arry(int a[100])
//相当于
void printf_arry(int *a)
{	// a,当作指针用,指针类型在32位系统下,长度为4个字节
    n=sizeof(a)/sizeof(a[0]);//sizeof(a) 指针4字节 sizeof(a[0])整形4字节
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-r0B5o82T-1625986523467)(assets/1588255342250.png)]

1.1 指针易错点

  • 写内存是一定要确保内存可写
#include <stdio.h>

int main() 
{
	// 写内存是一定要确保内存可写
	char *buf2 = "abdfhgkj";// 文字常量区,内存不可改
	//buf2[1] = "1";  //error
	char bu3[] = "abdfhgkj";
	buf31] = "1";    //ok
}
  • 不允许向NULL和未知非法地址拷贝内存
#include <stdio.h>

int main() 
{
	
	char *p3= 0X111;
    //给p3指向的内存区域拷贝内存
	strcpy(p3, "1111")  //error
}

1.2 二级指针作为输入

int main(void)
{ 
    char *p0 = "aaaaaa";
    char *p1 = "ccccc";
    char *p2 = "bbbbbb";
    char *p3 = "111111";
    
    //指针数组,指针的数组,它是一个数组,只是每一个元素都是指针
	char * p[] = { "aaaaaa", "ccccc", "bbbbbb", "111111" };
    int n =sizeof(p)/sizeof(p[0]);
    printf("sizeof(p)= %d sizeof(p[0])=%d \n", sizeof(p), sizeof(p[0]));
    
	int i=0;
    for(i=0;i<4;i++)
    {
        printf("%s\n",p[i]);
    }
	char * q[10] = { "aaaaaa", "ccccc", "bbbbbb", "111111" };
	 printf("sizeof(q)= %d sizeof(q[0])=%d \n", sizeof(q), sizeof(q[0]));
	return 0;
}

//输出结果
/*
	16 4
	aaaaaa
	ccccc
	bbbbbb
	111111
	40 4
*/

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-eE3ky4gV-1625986523469)(assets/1588498140051.png)]

排序demo
int main(void)
{
	char *p0 = "aaaaaa";
	char *p1 = "ccccc";
	char *p2 = "bbbbbb";
	char *p3 = "111111";

	//指针数组,指针的数组,它是一个数组,只是每一个元素都是指针
	char * p[] = { "aaaaaa", "ccccc", "bbbbbb", "111111" };
    char **p = { "aaaaaa", "ccccc", "bbbbbb", "111111" };//error
	int n = sizeof(p) / sizeof(p[0]);
	printf("sizeof(p)= %d sizeof(p[0])=%d \n", sizeof(p), sizeof(p[0]));

	int i = 0;
	for (i = 0; i<n; i++)
	{
		printf(" %s", p[i]);
	}
	printf("\n");

	int j = 0;
	char *tmp = NULL;

	//选择法排序
	for (i = 0; i < n-1; i++)
	{
		for (j = i + 1; j < n; j++) 
		{
			if (strcmp(p[i], p[j]) > 0)
			{
				tmp = p[i];
				p[i] = p[j];
				p[j] = tmp;
			}
		}
	}
	for (i = 0; i<n; i++)
	{
		printf(" %s", p[i]);
	}
	printf("\n");

	return 0;
}


[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dDDw9B4V-1625986523470)(assets/1588500932861.png)]

函数分装
void print_array(char *p[], int n) // 等价于void print_array(char **p, int n)
{
	int i = 0;
	for (i = 0; i < n; i++)
	{
		printf("%s,", p[i]);

	}
}

int sort_array(char *array[], int len)
{
	int i = 0;
	int j = 0;
	char *temp = NULL;

	for (i = 0; i < len; i++) {
		for (j = i; j < len; j++) {
			if (strcmp(array[i], array[j])  > 0) {
				temp = array[i];
				array[i] = array[j];
				array[j] = temp;
			}
		}
	}

	return 0;
}
int main(void)
{
	char *p0 = "aaaaaa";
	char *p1 = "ccccc";
	char *p2 = "bbbbbb";
	char *p3 = "111111";
	int error_type;

	//指针数组,指针的数组,它是一个数组,只是每一个元素都是指针
	char * p[] = { "aaaaaa", "ccccc", "bbbbbb", "111111" };
	int n = sizeof(p) / sizeof(p[0]);
	
	printf("排序前\n");
	print_array(p, 4);

	error_type = sort_array(p, 4);
	printf("排序后\n");
	print_array(p, 4);

	
	return 0;
}

1.3 二维数组

//a代表首行的地址,首行地址和首行首元素是有区别的(步长不一样),但是他们得值是一样的 
char a[4][30] = { "aaaaaa", "ccccc", "bbbbbb", "111111" }
//第一个维度可以不写,但由前提条件,必须要初始化
//char a[][30] ;//error
char a[][30] = { "aaaaaa", "ccccc", "bbbbbb", "111111" };
printf("a:%d a+1:%d",a, a+1);//输出结果a+1 和 a的值差30

for(i = 0; i<4; i++)
{
    printf("%s\n", a[i]);// a[i]相当于*(a+1),也可以为a+1因为首行地址和首行首元素地址的值相同
}
二维数组排序
#define  _CRT_SECURE_NO_WARNINGS 
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

/*
int print_array(char **array, int num)//error步长不一样
{
	printf("a:%d, a+1::%d", a, a+1);// 输出结果:相差4字节(指针类型的步长4),外面相差6
    
}*/
//int print_array(char array[5][6],  int num)//ok
//int print_array(char[6]* array, int num)
int print_array(char array[][6], int num)      //int print_array(char (*array)[6], int num)
{
	int i = 0;

	for (i = 0; i < num; i++) {
	
		printf("%s\n", *(array + i)); 
	}

	return 0;
}


int sort_array(char array[][6], int num)
{
	char buf[6]  = { 0 };
	int i = 0;
	int j = 0;

	for (i = 0; i < num; i++) {
		for (j = i; j< num; j++) {
			if (strcmp(array[i], array[j]) > 0) {
				strcpy(buf, array[i]);
				strcpy(array[i], array[j]);
				strcpy(array[j], buf);
			}
		}
	}

	return 0;
}

int main(void)
{
	char my_array[5][6] = { "aaa", "ccc", "bbb", "111" };
	int num = 0;
	int i = 0;


	for (i = 0; i < 5; i++) {
		if (strlen(my_array[i]) != 0) {
			num++;
		}
	}
	printf("num : %d\n", num);

	printf("排序前\n");
	print_array(my_array, num);

	sort_array(my_array, num);


	printf("排序后\n");
	print_array(my_array, num);




	return 0;
}
#define  _CRT_SECURE_NO_WARNINGS 
#include <stdio.h>
#include <string.h>
#include <stdlib.h>


char ** get_mem(int num)
{
	char **array = NULL;
	int i = 0;

	array = (char**)malloc(sizeof(char*)* num);
	if (array == NULL) {
		fprintf(stderr, "malloc char **array error\n");
		return NULL;
	}
	memset(array, 0, sizeof(char*)*num);

	for (i = 0; i < num; i++) {
		array[i] = (char*)malloc(64);
		if (array[i] == NULL) {
			fprintf(stderr, "maloc array[%d] error\n", i);
			return NULL;
		}

		sprintf(array[i], "%d%d%d%d", 9-i, 9-i, 9-i, 9-i);
	}

	return array;
} //main::my_array = array;


void free_mem(char **array, int num)
{
	char **temp_array = array;
	int i = 0;

	if (array == NULL) {
		return;
	}

	for (i = 0; i < num; i++) {
		if (temp_array[i] != NULL) {
			free(temp_array[i]);
			temp_array[i] = NULL;
		}
	}

	free(temp_array);
}

int print_array(char **array, int num)
{
	int i = 0; 

	for (i = 0; i < num; i++) {
		printf("%s\n", *(array + i));
		//printf("%s\n", array[i]);
	}

	return 0;
}

int sort_array(char **array, int num)
{
	int i = 0;
	int j = 0;
	char* temp = NULL;

	for (i = 0; i < num; i++) {
		for (j = i; j < num; j++) {
			temp = array[i];
			array[i] = array[j];
			array[j] = temp;
		}
	}

	return 0;
}

int main(void)
{
	char **my_array = NULL;

	
	int num = 4;

	my_array = get_mem(num);
	if (my_array == NULL) {
		fprintf(stderr, "get_mem err\n");
		return -1;
	}
	print_array(my_array, num);

	printf("------\n");
	sort_array(my_array, num);

	print_array(my_array, num);

	free_mem(my_array, num);
	my_array = NULL;


	return 0;
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AFJfc6ox-1625986523472)(assets/1588506633171.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9dTNoYvU-1625986523473)(assets/1588506666133.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JL7OzQhu-1625986523474)(assets/1588506772631.png)]

2 void

  • 函数参数为空,定义函数时,可以用void修饰:int fun(void)
  • 不能定义void类型的普通变量 void a;//err 无法确定类型,不同类型分配的空间不一样
  • 可以定义void *变量 void *p //ok 32位系统永远4字节 64系统 8字节
  • 数据类型本质 固定内存块大小别名
  • void *p 万能指针 ,函数返回值,函数参数

3 内存四区模型介绍

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mwDfBuxT-1625986523475)(assets/1588255838730.png)]

3.1 全局区

全局变量和静态变量,里面又分为初始化区、未初始化区、文字常量区、字符常量。整个程序运行完毕,系统自动回收。

#include<stdio.h>
#include<string.h>
char *get_str1()
{
	char *p = "abcdef";// 文字常量区

	return p;
}

char *get_str2()
{
	char *q = "abcdef";// 文字常量区

	return q;
}

int main(void) 
{
	char *p = NULL;
	char *q = NULL;

	p = get_str1();
	// %s 指针指向内存区域的内容
	// %d 打印p本身的值
	printf("p = %s p = %d\n",p, p);

	q = get_str2();
	printf("q = %s q = %d", q, q);

	printf("\n");
	return 0;

}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GO4q417g-1625986523476)(assets/1588302908167.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Wpd7AgQ9-1625986523476)(assets/1588256763467.png)]

p=get_str1()执行后

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BJYUvVtL-1625986523477)(assets/1588256772796.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6sCjwABA-1625986523478)(assets/1588257392123.png)]

3.2 栈区

系统分配空间,系统自动回收,函数内部定义的变量,函数参数,函数结束,其内部变量生命周期结束。

栈区地址生长方向:地址由上往下递减

//栈区
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
char *get_str()
{
char str[] = "abcdef";// 文字常量区

return str;

}

int main(void)
{
	char buf[128] = {0};
	char *q = NULL;
	strcpy(buf, get_str());// 输出可能会乱码,下面没有出现乱码的原因是,因为先发生拷贝了,然后栈区在消失
	printf("buf = %s\n", buf);
	
	return 0;
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vLNT09EC-1625986523478)(assets/1588303249572.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9ZY1zezC-1625986523479)(assets/1588258247592.png)]

//栈区
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
char *get_str()
{
char str[] = "abcdef";// 文字常量区

return str;

}

int main(void)
{

	char *p = NULL;
	p = get_str();
	printf("buf = %s\n", p);

	return 0;

}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LCBMLRox-1625986523480)(assets/1588303437739.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Yb7OkMJi-1625986523481)(assets/1588258458097.png)]

3.3 堆区

程序员动态分配空间,由程序员手动释放,没有手动释放,分配空间一直可用。

堆区地址生长方向:地址由上往下递增

//堆区
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
char *get_str()
{
	char str[] = "abcdef";// 文字常量区
	char *tmp = (char*)malloc(100);
	if (tmp == NULL) {
		return NULL;
	}
	strcpy(tmp, "ABCDEFGHIJK");

	return tmp;

}

int main(void)
{
    char buf[128] = {0};
    char *p = NULL;
    
    p = get_str();
    if (p != NULL)
    {
        printf("p = %s\n", p);
        free(p);
        p = NULL;

    }

    return 0;

}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Pq9HK0Dm-1625986523481)(assets/1588303834914.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LYMuWfN3-1625986523482)(assets/1588258937239.png)]

4 字符串

  • c语言没有字符串类型,通过字符数据模拟
  • 以 ‘\0’ 结束,即0
//不指定长度,没有0结束符,有多少个元素就有多长
char buf[] = {'a', 'b', 'c'};

//指定长度,后面没有赋值的元素,自动补0
char buf[100] = {'a', 'b', 'c'};

//所有元素赋值0
char buf[100] = {0};

char buf[] = "abc";
//strlen 测字符串长度,不包含数字0, '\0'
//sizeof 测量数组长度,包含数字0, '\0'
printf("strlen = %d, sizeof = %d\n",strlen(buf), sizeof(buf) ); // 3 4

char buf[100] = "abc";
printf("strlen = %d, sizeof = %d\n",strlen(buf), sizeof(buf) ); // 3 100

5 const

  • const 修饰一个变量为只读
//const 修饰一个变量为只读
const int a =100;
a = 1000; //error 不能直接修改

int *p=&a;
*a = 1000;//ok c语言中const其实是假的,可以通过指针间接修改

//指针变量,指针指向的内存是两个概念
char buf[] = "agsg";

//从左往右看,跳过类型,看修饰哪个字符
//如果是*,说明指针指向的内存不能改变
//如果是指针变量,说明指针的指向不能改变,指针的值不能改变 
const char *p = buf;//不能通过p buf中的内容,但是可以改变p,可以指向别的
char const *p1 = buf;//等价于上面
p[1]='s';//error
p = "agsag";//ok

char * const p2 =buf;
p2[1]='s';//ok
p2 = "agsag";// error

const char * const p3 = buf;//指向不能变,指向的内存也不能变
p3[1]='s';//ok
p3 = "agsag";//ok

typedef mystruct
{
    int a;
    int b;
}mystruct;

void fun(mystruct *p)
{
    //指针能变
    p = NULL;//OK
    //指针指向的内存也可以变
    p->a = 10;//ok
    
    
}
void fun1(mystruct const *p)
{
 
    p = NULL;//OK
    p->a = 10;//ERROR
    
}
void fun2(mystruct * const p)
{
    p = NULL;//ERROR
    p->a = 10;//OK
    
}
void fun3(mystruct const * const p)
{
    p = NULL;//ERROR
    p->a = 10;//ERROR
    
}

6 多维数组

int b[5]={0};
//b 表示首行首元素地址, +1,跳4个字节
//&b 表示首行地址,+1,跳4*5=20个字节

6.1 指针数组

  • 指针数组,它是数组,每个元素都是指针
  • [] 比*优先级高
  • char *a[]={“aaaaaaa”, “bbbbb”,“cccc”};

6.2 数组指针

typedef int A[10];//A 数组类型
A b;//相当于int b[10]; 数组类型变量,普通变量
A *p;//数组指针变量

typedef int (*P)[10];//数组指针类型
P p;//数组指针变量

int (*q)[10];//数组指针变量
 
// 数组指针,他是指针,指向一个数组的指针
// 定义数组指针变量
int a[10]={0}; 
inti
//1.先定义数组类型,根据类型定义指针变量
typedef int A[10];//A数组类型
A *P=NULL;//P数组指针类型的变量
//p=al//a代表首元素地址,a和&a一样,最终也是当作&a,但是编译器会有警告
p=&a;//&a代表整个数组首地址

printf("p:%d p+1:%d",p,p+1);//相差40

for(i=0;i<10;i++)
{
    //a[]
    //p=&a
    //*a=*&a->a
    (*p)[i]=i+1;
}
for(i=0;i<10;i++)
{
    printf("%d",(*p)[i]=);
}
//2.数组指针的第二种定义方法
//先定义数组指针类型,根据类型定义变量
//和指针数组写法很类似,多了()
//()和[]的优先级一样,从左往右 
//指向数组的指针,他有typedef,所以它是一个数组指针类型
typedef  int(*p)[10];
P q;//数组指针变量
q = &a;


//3.数组指针的第三种定义方法
//直接定义数组指针变量,没有typedef就是变量,有为类型
int(*q)[10];
q = &a; 

6.3 二维数组

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aT9XJlzY-1625986523483)(assets/1588570756173.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-25DRbZFW-1625986523483)(assets/1588571136488-1589204006538.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TMrMwrpJ-1625986523484)(assets/1588516591444.png)]

int a[][4] = {1,2,3,4,5,6,7,8,9101112};
//a 代表第0行首地址
// a+i -> &a[i]代表第i行首地址
// *(a+i) -> a[i] 代表第i行地址首元素地址
// *(a+i)+j ->  &a[i][j] 代表第i行第j列元素地址
// *(*(a+i)+j) -> a[i][j] 代表第i行第j列元素的值


int main()
{
	int a[][4] = {1,2,3,4,5,6,7,8,9101112};
    //3个a[4]的一维数组
    
    //定义数组指针
   //指向一维数组的整个数组首地址 
    int (*p)[4];
    p=&a;//有警告  &a表示二维数组的首地址,虽然和a的值相同,但是步长不一样 
    p = a;
    
    int t[1];
    //测一维数组的长度,sizeof()首行首元素的地址
    printf("sizeof(t) = %d sizeof(&t) = %d", sizeof(t),sizeof(&t));//输出结果 40 4
    // *(a+0)和a[0]表示首行首元素地址 &a[0]和a+0表示首行地址
    printf("sizeof(a[0]) = %d sizeof(&a[0]) = %d", sizeof(a[0]),sizeof(&a[0]));//输出结果 16 4
    printf("sizeof(*(a+0)) = %d sizeof(a+0) = %d", sizeof(*(a+0)),sizeof(a+0));//输出结果 16 4
}
二维数组做函数参数
//定义数组指针类型,在定义变量
typedef int (*P)[10];//数组指针类型
P p;//数组指针变量
p = a;

#define  _CRT_SECURE_NO_WARNINGS 
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

//数组做形参都会退化成指针,指针步长不一定一样
void make_array(int (*a)[5], int row, int col)
//void make_array(int a[3][5])//ok
//void make_array(int **a)//error 指针步长不一样
{
	int i = 0;
	int j = 0;

	for (i = 0; i < row; i++) {
		for (j = 0; j < col; j++) {
			a[i][j] = i + j;
		}
	}
}

void print_array(int (*a)[5], int row, int col)
//void print_array(int a[3][5]) // print_array:a[3][5]  = main:a[3][5]
{
	int i = 0;
	int j = 0;

	for (i = 0; i < row; i++) {
		for (j = 0; j < col; j++) {
			printf("a[%d][%d]: %d  ", i, j, a[i][j]);

		}
		printf("\n");
	}
	printf("\n");
}

typedef int(ARRAY_5_6)[5][6];

void make_array2(ARRAY_5_6 *b, int row, int col, int height)
//void make_array2(int b[3][5][6], int row, int col, int height)
//void make_array2(int(*b)[5][6], int row, int col, int height)
{
	int i = 0, j = 0, k = 0;

	for (i = 0; i < row; i++) {
		for (j = 0; j < col; j++) {
			for (k = 0; k < height; k++) {
				//b[i][j][k] = i + j + k;
				*(*(*(b + i) + j) + k) = i + j + k;
			}
		}
	}
}

void print_array2(ARRAY_5_6 *b, int row, int col, int height)
{
	int i = 0, j = 0, k = 0;

	for (i = 0; i < row; i++) {
		for (j = 0; j < col; j++) {
			for (k = 0; k < height; k++) {
				printf("b[%d][%d][%d]:%d  ", i, j, k, b[i][j][k]); 
			}
			printf("\n");
		}
		printf("\n");
	}
	printf("\n");
}

void print_array3(int *p, int num)
{
	int i = 0;
	for (i = 0; i < num; i++) {
		printf("%d ", p[i]);
	}
	printf("\n");
}

int main(void)
{
	int a[3][5]; //Êý×éÎÞÂÛÊǼ¸Î¬Êý×飬 ¶¼ÊÇÒ»¿éÁ¬ÐøµÄÄÚ´æ¿Õ¼ä

	int b[3][5][6];


	make_array(a, 3 ,5);
	print_array(a, 3, 5);

	printf("------\n");

	make_array2(b, 3, 5, 6);
	print_array2(b, 3, 5, 6);
	printf("------\n");


	print_array3((int *)a, 15);

	return 0;
}

7 结构体

7.1 结构体变量的定义

7.2浅拷贝 和深拷贝

  • 浅拷贝
  • 结构体中嵌套指针,而且动态分配空间
  • 同类型结构体变量赋值
  • 不同结构体成员指针变量指向同一块内存

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ejqRNnMW-1625986523484)(assets/1588584499552.png)]

  • 深拷贝(不会造成通一个地址指向同一个内存空间)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nJph4cm3-1625986523485)(assets/1588584762509.png)]

7.3 字节对齐

  • 字节对齐按最长字节
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main()
{
	struct MyStruct
	{
		int a; //int类型4字节
		short b;//short类型2字节
		double c;//double类型8字节

	}A;
	/*
		a:4*0
		b:2*2=4
		c:8*1=8
		a a a a b b * *
		c c c c c c c c
	*/
	printf("%d\n",sizeof(A));//16字节 
	printf("\n");


	struct MyStructb
	{
		int a; //int类型4字节
		double c;//double类型8字节
		short b;//short类型2字节
		

	}B;
	/*
	a a a a * * * *
	c c c c c c c c
	b b * * * * * *
	*/
	printf("%d\n", sizeof(B));//24字节 
	printf("\n");

}

8 链表

数组:一次性分配一块连续的存储区域

优点:

​ 随机访问元素效率高

缺点:

​ 需要分配一块连续的存储区域(很大区域,有可能分配失败)

​ 删除和插入某个元素效率低

链表:现实生活中的灯笼

优点:

​ 不需要一块连续的存储区域

​ 删除和插入某个元素效率高

缺点:

​ 随机访问元素效率低

数据类型的本质是内存大小的别名

1.代码区、常量区、静态区(全局区)、堆区、栈区

这里写图片描述

代码区:存放程序的代码,即CPU执行的机器指令,并且是只读的。
常量区:存放常量(程序在运行的期间不能够被改变的量,例如: 10,字符串常量”abcde”, 数组的名字等)
静态区(全局区):静态变量和全局变量的存储区域是一起的,一旦静态区的内存被分配, 静态区的内存直到程序全部结束之后才会被释放
堆区:由程序员调用malloc()函数来主动申请的,需使用free()函数来释放内存,若申请了堆区内存,之后忘记释放内存,很容易造成内存泄漏
栈区:存放函数内的局部变量,形参和函数返回值。栈区之中的数据的作用范围过了之后,系统就会回收自动管理栈区的内存(分配内存 , 回收内存),不需要开发人员来手动管理。栈区就像是一家客栈,里面有很多房间,客人来了之后自动分配房间,房间里的客人可以变动,是一种动态的数据变动。

int a = 0; 全局初始化区  
char *p1; 全局未初始化区  
main()  
{  
    int b;char s[] = "abc";char *p2;char *p3 = "123456"; 123456\0在常量区,p3在栈上。  
    static int c =0; 全局(静态)初始化区  
    p1 = (char *)malloc(10);  
    p2 = (char *)malloc(20);  
    分配得来得1020字节的区域就在堆区。  
    strcpy(p1, "123456"); 123456\0放在常量区,编译器可能会将它与p3所指向的"123456"
    优化成一个地方。  
}  
1.1 stm32内存配置

这里写图片描述

默认分配的ROM区域是0x8000000开始,大小是0x20000的一片区域,那么这篇区域是只读区域,不可修改,也就是存放的代码区和常量区。
默认分配的RAM区域是0x20000000开始,大小是0x4000的一片区域,这篇区域是可读写区域,存放的是静态区、栈区和堆区。该芯片的内部分区如下图所示:

这里写图片描述

1.2 stm32代码区
  • 代码区的内存是由系统控制的
  • 代码区的存放 :程序中的函数编译后cpu指令
  • 代码区的地址:函数的地址,程序的入口地址,程序的名字
    函数的名称也是一个指针,可以通过查询函数名称所处的内存地址,查询函数存放的区域。
void test(void)
{
    printf("main:0x%p\n",main);//打印main函数的存放地址
}

这里写图片描述

到main函数确实存放在0x08002e81这片地址区域,在代码区中。

1.3 常量区

下面来分析一句代码:
char *p = “abcdef”; 这句代码和char *p; p= “abcdef”;是等价的。
上面的两种定义方式的具体意思是:定义一个char * 型的指针p,p存放的是字符串常量”abcdef”的首地址,字符串常量”abcdef”是存放在常量区的,也就是p是指向常量区的。那么p指向的区域里面的内容是不可以得修改,只可以 *p来读取p指向的内容,当然也可以把指针p移走,指向其他区域。
测试如下:

void test(void)
{   
    char *p="abcdef";
    printf("0x%p: %s\n", p , p);//打印指针p的地址和p指向的字符串内容
    p="qwedma";
    printf("0x%p: %s\n", p , p);//打印指针p的地址和p指向的字符串内容
    p[0]='1';                     //尝试把p指向的第一个字符q修改为1
    printf("0x%p: %s\n", p , p);//打印指针p的地址和p指向的字符串内容
}

这里写图片描述

看到,abcdef字符串常量存放在0x08002ecc区域,p指针指向该区域,并把p指针移走指向qwedma字符串常量的首地址0x08002ee0。当尝试修改p指向的第一个字符,即把qwedma修改为1wedma,发现打印出来的内容并未改变,常量区的内容不可以改变。

继续看这句 char str[] = “abcd”;这句话是定义了一个字符数组,但是这个str数组是存放在栈区的,然后再把字符串常量”abcd”拷贝到栈区的str数组内,那么此时的str是可以修改的。

void test(void)
{
    char str[] = "abcd";
    printf("0x%p: %s\n", str , str);
    str[0]='e';
    printf("0x%p: %s\n", str , str);
}

这里写图片描述

看到str是指向栈区的地址:0x200007c0,且指向的内容可以被修改,第一个字符a被修改为e。

1.4 静态区
static int a;
int c;
void test(void)
{
    static int b=1;
    b++;
    printf("b:0x%p: %d\n", &b , b);
}
int main()
{
    printf("a: 0x%p: %d\n", &a , a);
    printf("c: 0x%p: %d\n", &c , c);
    for(uint8_t i=0;i<5;i++)
    {
        test();
    }
    return 0;
}

这里写图片描述

静态全局变量,b静态局部变量,c是全局变量,它们都存放在静态区;a和c并未初始化,打印出来都是0,说明编译器自动把他们初始化为0;b在for循环中初始化5次,但实际效果是b仅初始化一次,后面每次调用b都是上次的值,且b的地址一直是不变的,编译器只会为第一次初始化的b分配内存,后面4次初始化是无效的。

1.5 堆区

堆区是调用malloc函数来申请内存空间,这部分空间使用完后需要调用free()函数来释放。
void * mallc(size_t);函数的输入是分配的字节大小,返回是一个void*型的指针,该指针指向分配空间的首地址,void *型指针可以任意转换为其他类型的指针。

void test(void)
{   
    int *p1=malloc(4);//申请4字节的空间
    *p1=123;// 该空间赋值123
    printf("0x%p:%d\n",p1,*p1);
    printf("0x%p\n",&p1);
    free(p1);
    printf("0x%p:%d\n",p1,*p1);
    p1 = NULL;
    printf("0x%p\n",p1);
}

这里写图片描述

nt *p1=malloc(4);语句是申请了4个字节的空间,空间的首地址赋给指针p1,可以看到这个首地址是0x200003e8,存在是堆区;
printf(“0x%p\n”,&p1);指针p1本身也是需要存放的,p1本身是存放在栈区的0x200009d0;
free(p1);内存释放函数 free(开辟的内存的首地址) ,将内存标记为可用且将里面的内容清空为0,但指针p1还是指向这片空间。比较安全的做法是p1 = NULL;把p1指针释放,避免造成野指针。

void test(void)
{   
    int *p1=malloc(4);
    int *p2=malloc(4);
    printf("p1:0x%p\n",p1);
    printf("p2:0x%p\n",p2);
}

这里写图片描述

地址是大于p1的地址,验证堆区是向上生长的,后申请的空间地址会依次增加。

1.6 栈区

栈区由编译器自动分配释放,存放函数的参数值、返回值和局部变量,在程序运行过程中实时分配和释放,栈区由操作系统自动管理,无须手动管理。栈区是先进后出原则,即先进去的被堵在屋里的最里面,后进去的在门口,释放的时候门口的先出去。

void test(void)
{   
    int a;
    int b=0;    
    printf("a:0x%p:%d\n",&a,a);
    printf("b:0x%p:%d\n",&b,b);c
}

这里写图片描述

可以看到后定义的局部变量b地址是比a小的,即栈区是向下生长的;
a变量没有进行初始化,打印出的a是垃圾值,编译器不会把局部变量初始化为0。但是,需要注意:如果你运行于debug调试模式,运行时机制会把你的栈空间全部初始化为0,这就是解释了为什么平时在debug时看到的未初始化的局部变量初始值是0.
使用局部变量时,尽量要先进行初始化,避免垃圾值造成错乱。

1.7 大小端测试

数据在内存中存放,有大段模式和小端模式。
小端模式(little-endian):低位字节存在低地址上,高位字节存在高地址上;
大端模式( big-endian):低位字节存在高地址上,高位字节存在低地址上,刚好与小端模式相反。
另:网络字节序:TCP/IP各层协议将字节序定义为Big-Endian,因此TCP/IP协议中使用的字节序通常称之为网络字节序

static uint32_t m=0x87654321;
char *p=(char*)&m;
void test(void)
{   
    printf("P  :0x%p: %x\n",p,*p);
    printf("P+1:0x%p: %x\n",p+1,*(p+1));
    printf("P+2:0x%p: %x\n",p+2,*(p+2));
    printf("P+3:0x%p: %x\n",p+3,*(p+3));
}

这里写图片描述

字节21放在低地址,高字节87放在高地址,与小端模式相符。

1.8 keil中代码和数据量所占字节的查询

keil软件勾选上生成批处理文件,在keil编译完成后,可以查看到代码和定义的数据所占的字节大小。

这里写图片描述

这里写图片描述

如上图,Code是程序代码所占的字节,即代码区;
RO-data 代表只读数据,程序中所定义的常量数据和字符串等都位于此处,即常量区;
RW-data 代表已初始化的读写数据,程序中定义并且初始化的全局变量和静态变量位于此处,一部分静态区(全局区);
ZI-data 代表未初始化的读写数据,程序中定义了但没有初始化的全局变量和静态变量位于此处,另一部分的静态区(全局区)。ZI英语是zero initial,就是程序中用到的变量并且被系统初始化为0的变量的字节数,keil编译器默认是把你没有初始化的变量都赋值一个0,这些变量在程序运行时是保存在RAM中的。
Total ROM Size (Code + RO Data + RW Data)这样所写的程序占用的ROM的字节总数,也就是说程序所下载到ROM flash 中的大小。

为什么Rom中还要存RW,因为掉电后RAM中所有数据都丢失了,每次上电RAM中的数据是被重新赋值的,每次这些固定的值就是存储在Rom中的,为什么不包含ZI段呢,是因为ZI数据都是0,没必要包含,只要程序运行之前将ZI数据所在的区域一律清零即可,包含进去反而浪费存储空间。

实际上,ROM中的指令至少应该有这样的功能:
\1. 将RW从ROM中搬到RAM中,因为RW是变量,变量不能存在ROM中。
\2. 将ZI所在的RAM区域全部清零,因为ZI区域并不在Image中,所以需要程序根据编译器给出的ZI地址及大小来将相应得RAM区域清零。ZI中也是变量,同理:变量不能存在ROM中。
在程序运行的最初阶段,RO中的指令完成了这两项工作后C程序才能正常访问变量。否则只能运行不含变量的代码。

2 大小端判断

2.1 利用指针
static uint32_t m=0x87654321;
char *p=(char*)&m;
void test(void)
{   
    printf("P  :0x%p: %x\n",p,*p);
    printf("P+1:0x%p: %x\n",p+1,*(p+1));
    printf("P+2:0x%p: %x\n",p+2,*(p+2));
    printf("P+3:0x%p: %x\n",p+3,*(p+3));
}

这里写图片描述

字节21放在低地址,高字节87放在高地址,与小端模式相符。

2.2 强制类型转换
#include<stdio.h>

static int m = 0x654321;
char p = (char)m;
int main()
{
	printf("P:%x\n", p);
	return 0;
}
2.3 使用联合体进行判断

第一,联合体的各个成员都是公用内存的;

第二,联合体的成员不管是在哪个架构上默认都是从低地址开始存储的,这点非常重要

#include <stdio.h>
#include <stdlib.h>

union endian{
    char a;
    int b;
}test;

int main()
{
    test.b = 0x12345678;
    printf("0x%x\n", test.a);

}
0x78

所以可以判断我所用的架构是小端的。下面稍微解释一下,test.a是联合体在内存中的第一个字节(也是在内存地址中最低的地址),打印出来了0x78说明数据的逻辑低位存储在了内存地址的低位,这就是小端了。

3 基本问题

3.1 用预处理指令#define声明一个常数,用以表明1年中有多少秒(忽略闰年问题)

#defineSECONDS_PER_YEAR (60 * 60 * 24 * 365)UL(无符号长整型)

3.2 写一个“标准”宏MIN,这个宏输入两个参数并返回较小的一个。

#defineMIN(A,B) ((A) <= (B) (A) : (B))

3.3 static的作用

static关键字指明变量的“静态属性”

static关键字同时具有“作用域限定符”的意义

  • static修饰的静态变量存储在静态存储区
  • static修饰的全局变量的作用域只是声明的文件中
  • static修饰的函数作用域只是声明的文件中
  1. 修饰局部变量:(编译器一般不对局部变量进行初始化,除非显示的赋值),静态局部变量使用static修饰符定义,即使在声明时未赋初值,编译器也会把它初始化为0。且静态局部变量存储于进程的全局数据区,即使函数返回,它的值也会保持不变。该变量的内存只被分配一次,因此其值在下次调用时仍维持上次的值

  2. 修饰全局变量:

    全局变量定义在函数体外部,在全局数据区分配存储空间,且编译器会自动对其初始化。

    普通全局变量对整个工程可见,其他文件可以使用extern外部声明后直接使用。也就是说其他文件不能再定义一个与其相同名字的变量了(否则编译器会认为它们是同一个变量)。

    静态全局变量仅对当前文件可见,其他文件不可访问,其他文件可以定义与其同名的变量,两者互不影响。

  3. 函数

    函数的使用方式与全局变量类似,在函数的返回类型前加上static,就是静态函数。其特性如下:

    • 静态函数只能在声明它的文件中可见,其他文件不能引用该函数

    • 不同的文件可以使用相同名字的静态函数,互不影响。

  4. 在类中的static成员变量属于整个类所拥有,对类的所有对象只有一份拷贝

  5. 在类中的static成员函数属于整个类所拥有,这个函数不接收this指针,因而只能访问类的static成员变量

3.4const作用

在c语言中const修饰的变量是只读的(不可以作为左值),其本质还是变量

const修饰的变量会在内存中占用空间

本质上const只对编译器有用,在运行时无用(运行时,还是可以用指针改变常量的值)

// 标准c编译器
#include<stdio.h>
int main() {

	const int cc = 1;
	int* p = (int*)&cc;
	printf("%d\n", cc);
    cc=3; //报错,左值不能被修改
	*p = 3;
	printf("%d\n", cc);
	return 0;
}

现代c编译器对const对应优化,通过符号表

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5nwtXW0U-1626016175234)(C:\Users\zxm\Desktop\笔记\c.assets\image-20200926205055241.png)]

当作为左值时直接报错,作为右边有两种情况,1 直接读取,编译器只从从符号表中取1,进行替换。2 当出现一次,以上以指针来间接取值时,编译器将从内存中取值

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rtp52OwL-1626016175236)(C:\Users\zxm\Desktop\笔记\c.assets\image-20200926205906041.png)]

  • 欲阻止一个变量被改变,可以使用const关键字。在定义该const变量时,通常需要对它进行初始化,因为以后就没有机会再去改变它了
  • 指针来说,可以指定指针本身为const,也可以指定指针所指的数据为const,或二者同时指定为const
  • 在一个函数声明中,const可以修饰形参,表明它是一个输入参数,在函数内部不能改变其值。
  • const修饰函数返回值表示返回值不可改变,多用于返回指针的情况
  • 对于类的成员函数,若指定其为const类型,则表明其是一个常函数,不能修改类的 成员变量
  • 对于类的成员函数,有时候必须指定其返回值为const类型,以使得其返回值不为“左值”
  • const修饰的数组空间是不可以被改变的
3.5 指针常量与常量指针
3.5.1 指针常量——指针类型的常量(int *const p)

本质上一个常量,指针用来说明常量的类型,表示该常量是一个指针类型的常量。**在指针常量中,指针自身的值是一个常量,不可改变,始终指向同一个地址。在定义的同时必须初始化。**用法如下:

int a = 10, b = 20;
int * const p = &a;
*p = 30; // p指向的地址是一定的,但其内容可以修改
3.5.2 常量指针——指向“常量”的指针(const int *p, int const *p)

常量指针本质上是一个指针,常量表示指针指向的内容,说明该指针指向一个“常量”。**在常量指针中,指针指向的内容是不可改变的,指针看起来好像指向了一个常量。**用法如下:

int a = 10, b = 20;
const int *p = &a;
p = &b; // 指针可以指向其他地址,但是内容不可以改变
3.5.3 例子
int main() {
    int m = 10;
    const int n = 20; // 必须在定义的同时初始化
 
    const int *ptr1 = &m; // 指针指向的内容不可改变
    int * const ptr2 = &m; // 指针不可以指向其他的地方
 
    ptr1 = &n; // 正确
    ptr2 = &n; // 错误,ptr2不能指向其他地方
 
    *ptr1 = 3; // 错误,ptr1不能改变指针内容
    *ptr2 = 4; // 正确
 
    int *ptr3 = &n; // 错误,常量地址不能初始化普通指针吗,常量地址只能赋值给常量指针
    const int * ptr4 = &n; // 正确,常量地址初始化常量指针
 
    int * const ptr5; // 错误,指针常量定义时必须初始化
    ptr5 = &m; // 错误,指针常量不能在定义后赋值
 
    const int * const ptr6 = &m; // 指向“常量”的指针常量,具有常量指针和指针常量的特点,指针内容不能改变,也不能指向其他地方,定义同时要进行初始化
    *ptr6 = 5; // 错误,不能改变指针内容
    ptr6 = &n; // 错误,不能指向其他地方
 
    const int * ptr7; // 正确
    ptr7 = &m; // 正确
 
    int * const ptr8 = &n;
    *ptr8 = 8;
 
    return 0;
}
3.6 volatile关键字
  1. 可以理解为“编译器警告指示字”
  2. 用于告诉编译器必须每次去内存中取变量值
  3. 主要修饰可能被多个线程访问的变量
  4. 也可以修饰可能被未知因素修改的变量

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-65G1smPx-1626016175238)(C:\Users\zxm\Desktop\笔记\c.assets\image-20200926210651975.png)]

当obj在整段程序中都没有被当做成左值,编译器会进行优化,默认其值不会被改变,即直接将obj替换成10.而把 a b 赋值为10.

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9RHu26mt-1626016175241)(C:\Users\zxm\Desktop\笔记\c.assets\image-20200926211051578.png)]

const colatile是否可以同时修饰一个变量值

const colatile int i =0;这个时候i具有什么属性?编译器如何处理这个变量。

3.7 struct 和 union

struct中的每个域在内存中都独立分配空间

union只分配最大域的空间,所有域共享这个空间

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZW4pJjf0-1626016175242)(C:\Users\zxm\Desktop\笔记\c.assets\image-20200926212552084.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gWqpGGN5-1626016175243)(C:\Users\zxm\Desktop\笔记\c.assets\image-20200926212704575.png)]

3.8 auto

auto即局部变量的默认属性

编译器默认所有的局部变量都是auto

3.9 register

register关键字指明将变量存储于寄存器中

register只是请求寄存器变量,但不一定请求成功

  • register变量的必须是CPU寄存器可以接受的值
  • 不能用&运算符获取register变量的地址
3.10 void指针

c语言规定只有相同类型的指针才可以相赋值

void* 指针作为左值用于接收任意类型的指针

void* 指针作为右值赋值给其他指针时需要强制类型转换

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ur73rXKT-1626016175243)(C:\Users\zxm\Desktop\笔记\c.assets\image-20200926214823161.png)]

3.11 extern

extern用于声明外部定义的变量和函数

external用于告诉编译器用c方式编译

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TU4BhbLZ-1626016175244)(C:\Users\zxm\Desktop\笔记\c.assets\image-20200926215120427.png)]

3.12 sizeof

sizeof 是编译器的内置指示符,不是函数

sizeof用于计算相应实体所占的内存大小

3.13 enum

enum为常量

enum是一种自定义类型

enum默认常量在前一个值得基础上依次加1

enum类型的变量只能取定义时的类散值

枚举类型和#define的区别?

  1. #define宏常量只是简单的进行值替换,枚举常量是真正意义上的常量
  2. #define无法被调试,nume可以
  3. #define宏常量无类型信息,枚举常量是一种特定类型的常量
3.14 typedef

typedef用于给一个已经存在的数据类型重命名

typedef并没有产生新的类型

typedef重定义的类型不能进行unsigned和signed扩展

typedef和#define的区别?

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mUTxEtAd-1626016175245)(C:\Users\zxm\Desktop\笔记\c.assets\image-20200926220421523.png)]

p1, p2 为指针 P3为指针 P4是char类型

3.15 逻辑运算符

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fmQMADp7-1626016175246)(C:\Users\zxm\Desktop\笔记\c.assets\image-20200926221109217.png)]

3.16 ++,–
int i =3;
(++i)+(++i)+(++i); //

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XGeziBs3-1626016175246)(C:\Users\zxm\Desktop\笔记\c.assets\image-20200926222331367.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zpMBBjSt-1626016175247)(C:\Users\zxm\Desktop\笔记\c.assets\image-20200926222528568.png)]

3.17 优先级

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XLDAWkAO-1626016175248)(C:\Users\zxm\Desktop\笔记\c.assets\image-20200926223135504.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-z1d5ft8T-1626016175249)(C:\Users\zxm\Desktop\笔记\c.assets\image-20200926223529425.png)]

3.18 编译过程

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IZmBMpTA-1626016175249)(C:\Users\zxm\Desktop\笔记\c.assets\image-20200926223811385.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-t1RsRfdS-1626016175250)(C:\Users\zxm\Desktop\笔记\c.assets\image-20200926224249933.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BnJZHBVi-1626016175251)(C:\Users\zxm\Desktop\笔记\c.assets\image-20210330125838042.png)]

预编译

  • 处理所有注释,以空格替换
  • 将所有#define删除,并且扩展所有宏定义
  • 处理条件编译指令#if #ifdef #elif #else #endif
  • 处理#include 展开被包含的文件
  • 保留编译器需要使用的#pragma指令
  • 预处理指令:gcc -E file.c -o hello.i (-E 只做预编译操作)

编译

  • 对预处理文件进行一系列词法分析,语法分析和语义分析

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KvusDrCU-1626016175251)(C:\Users\zxm\Desktop\笔记\c.assets\image-20200926224620546.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-S1Si8Vba-1626016175252)(C:\Users\zxm\Desktop\笔记\c.assets\image-20200926224656662.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JKAbDlek-1626016175252)(C:\Users\zxm\Desktop\笔记\c.assets\image-20200926224910084.png)]

3.19 #define 和 const

区别:

(1)就起作用的阶段而言: #define是在编译的预处理阶段起作用,而const是在 编译、运行的时候起作用

(2)就起作用的方式而言: #define只是简单的字符替换,没有类型检查,存在边界的错误;const对应数据类型,进行类型检查; (3)就存储方式而言:#define只是进行展开,有多少地方使用,就替换多少次,它定义的宏常量在内存中有若干个备份,占用代码段空间;const定义的只读变量在程序运行过程中只有一份备份,占用数据段空间。

(4)从代码调试的方便程度而言: const常量可以进行调试的,define是不能进行调试的,因为在预编译阶段就已经替换掉了。 (5)从是否可以再定义的角度而言: const不足的地方,是与生俱来的,const不能重定义,而#define可以通过#undef取消某个符号的定义,再重新定义。

(6)从某些特殊功能而言: define可以用来防止头文件重复引用,而const不能;

(7)从用于类中来看:const用于类成员变量的定义,只要一定义,不可修改。define 不可用于类成员变量的定义,但是可以用于全局变量。

(8)const采用一个普通的常量名称,define可以采用表达式作为名称;

#include<stdio.h>
#include<stdlib.h>
#include<malloc.h>

/*
int main()
{
  int array[100];
  int i=0;
  int sum=0;
  char y;
   char c;
  printf("input num\n");
  /*
   do
   {
    scanf("%d",&array[i]);
    i++;
   }while(y=getchar()!='\n');         //用于判断是否按了回车

   */
/*
  while(c !='\n'){
        scanf("%d",&array[i]);
        c=getchar();
        i++;

   }

  for(int j=0;j<i;j++)
  {
       sum =sum+array[j];
  }
  printf("sum = %d \n", sum); 
   return 0;
}*/


typedef struct DOUBLE_LIST
{
    int data;
    struct DOUBLE_LIST *prev;
    struct DOUBLE_LIST *next;
}double_list;
double_list *createlist()       //创建有n个元素的双向链表 并输入元素
{
    double_list *head, *p, *q;
    int n,x;\
	char c;
    head = (double_list *)malloc(sizeof(double_list));
    head->prev = head;
    head->next = head;
    p = head;
    printf("input nums:\n");
    //scanf("%d",&n);
	while(c !='\n'){
		
		scanf("%d",&x);
		c=getchar();
		q = (double_list *)malloc(sizeof(double_list));
        q->data = x;
        p->next = q;
        head->prev = q;
        q->prev = p;
        q->next = head;
        p = q;

   }
	/*
    for(int i=0;i<n;i++)
    {
        scanf("%d", &x);
        q = (double_list *)malloc(sizeof(double_list));
        q->data = x;
        p->next = q;
        head->prev = q;
        q->prev = p;
        q->next = head;
        p = q;
    }*/
    return head;
}
//遍历并且输出这些元素
void printlist(double_list *head)
{
    double_list *p;
    p = head;
    p = p->next;
    while(p!=head)
    {
        printf("%d  ", p->data);
        p = p->next;
    }
    printf("\n");
}
//得到现在双向链表中的元素的个数
int lengthlist(double_list *head)
{
    double_list *p;
    p = head;
    p = p->next;
    int coun = 0;
    while(p!=head)
    {
        coun++;
        p = p->next;
    }
    return coun;
}
//在第i个元素之前插入数据data
void insertlist_f(double_list *head, int i, int data)
{
    double_list *p = head, *q;
    p = p->next;
    i--;
    while(i--)
        p = p->next;
    q = (double_list *)malloc(sizeof(double_list));
    q->data = data;
    (p->prev)->next = q;
    q->prev = p->prev;
    q->next = p;
    p->prev = q;
}
//删除第i个位置的元素
void deletelist_i(double_list *head, int i)
{
    double_list *p = head;
    p = p->next;
    i--;
    while(i--)
        p = p->next;
    (p->prev)->next = p->next;
    (p->next)->prev = p->prev;
    free(p);
}
//删除值为x的元素
void deletelist_x(double_list *head, int x)
{
    double_list *p = head, *q;
    p = p->next;
    while(p!=head)
        if(p->data == x)
        {
            q = p->next;
            (p->prev)->next = p->next;
            (p->next)->prev = p->prev;
            free(p);
            p = q;
        }
        else
            p = p->next;
}
//对双向链表进行排序
void sortlist(double_list *head)  //升序
{
    double_list *p = head, *q, *t;
    p = p->next;
    for(;p!=head;p=p->next)
        for(t = p->next;t!=head;t=t->next)
        {
            if(p->data > t->data)
            {
                int a = p->data;
                p->data = t->data;
                t->data = a;
            }
        }
}
int main()
{
    double_list *head;
    head = createlist();
    //deletelist_x(head, 2);
    sortlist(head);
    printlist(head);
    insertlist_f(head, 2, 2);
    printlist(head);
 
    return 0;
}


#include<stdio.h>
#include<stdlib.h>
#include<malloc.h>

/*
int main()
{
  int array[100];
  int i=0;
  int sum=0;
  char y;
   char c;
  printf("input num\n");
  /*
   do
   {
    scanf("%d",&array[i]);
    i++;
   }while(y=getchar()!='\n');         //用于判断是否按了回车

   */
/*
  while(c !='\n'){
        scanf("%d",&array[i]);
        c=getchar();
        i++;

   }

  for(int j=0;j<i;j++)
  {
       sum =sum+array[j];
  }
  printf("sum = %d \n", sum); 
   return 0;
}*/


typedef struct LIST
{
    int num;
    struct LIST *prev;
    struct LIST *next;
}list_obj;
list_obj *createlist(void)       //创建有n个元素的双向链表 并输入元素
{
    list_obj *head, *pPrev, *pNext;
    int n,x,Tmp;
	char c;
	
    head = (list_obj *)malloc(sizeof(list_obj));
    head->prev = NULL;
    head->next = NULL;
    pPrev = head;
    printf("input nums:\n");
	while(c !='\n'){
		
		scanf("%d",&Tmp);
		c=getchar();
		pNext = (list_obj *)malloc(sizeof(list_obj));
        pNext->num = Tmp;
        pPrev->next = pNext;
        pNext->prev = pPrev;
        pPrev = pNext;

   }
	pNext->next =NULL;
    return head;
}

list_obj *createlistV2(void)       //创建有n个元素的双向链表 并输入元素
{
    list_obj *head, *pPrev, *pNext, *ptr;
    int n,x,Tmp;
	char c;
	
    head = (list_obj *)malloc(sizeof(list_obj));
    head->prev = NULL;
    head->next = NULL;
    ptr = head;
    printf("input nums:\n");
	while(c !='\n'){
		
		scanf("%d",&Tmp);
		c=getchar();
		if (ptr == head)
		{
			pNext = (list_obj *)malloc(sizeof(list_obj));
			pNext->num = Tmp;
			pNext->prev = ptr;
			ptr->next = pNext;
			pNext->next = NULL;
			ptr = pNext;
			continue;
		}

		ptr = head->next;
		if(Tmp <= ptr->num)/*前插*/
		{
			pPrev = (list_obj *)malloc(sizeof(list_obj));
			pPrev->num = Tmp;			
			ptr->prev->next = pPrev;
			pPrev->prev = ptr->prev;
			pPrev->next = ptr;
			ptr->prev = pPrev;
		}
		else
		{
			while(1)
			{
				if(ptr->next ==NULL)
				{
					if(Tmp <= ptr->num)/*前插*/
					{
						pPrev = (list_obj *)malloc(sizeof(list_obj));
						pPrev->num = Tmp;
						ptr->prev->next = pPrev;
						pPrev->prev = ptr->prev;
						pPrev->next = ptr;
						ptr->prev = pPrev;

					}
					else
					{
						pNext = (list_obj *)malloc(sizeof(list_obj));
						pNext->num = Tmp;
						pNext->prev = ptr;
						pNext->next = NULL;
						ptr->next = pNext;
						ptr = pNext;
						break;
					}
				}
				if(Tmp <= ptr->num)/*前插*/
				{
					pPrev = (list_obj *)malloc(sizeof(list_obj));
					pPrev->num = Tmp;
					ptr->prev->next = pPrev;
					pPrev->prev = ptr->prev;
					pPrev->next = ptr;
					ptr->prev = pPrev;

					break;
				}
				ptr = ptr->next;
				
			}
		}

   }

    return head;
}


//遍历并且输出这些元素
void printlist(list_obj *head)
{
    list_obj *ptr;
    ptr = head;
    ptr = ptr->next;
    while(ptr!=NULL)
    {
        printf("%d ", ptr->num);
        ptr= ptr->next;
    }
    printf("\n");
}

//对双向链表进行排序
void sortlist(list_obj *head)  //升序
{
    list_obj *p = head, *q, *t;
    p = p->next;
    for(;p!=NULL;p=p->next)
        for(t = p->next;t!=NULL;t=t->next)
        {
            if(p->num > t->num)
            {
                int a = p->num;
                p->num = t->num;
                t->num = a;
            }
        }
}

int main()
{
    list_obj *head;
	/*
    head = createlistV2();
	printlist(head);
	*/
    //deletelist_x(head, 2);
   
    head = createlist();
	
    sortlist(head);
    printlist(head);


    return 0;
}


/*1*/
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <string.h>
#define Uint8   unsigned char
#define Uint16  unsigned short
#define Uint32  unsigned int
//Uint32 yuv420p_I420_YU12(Uint8 *I420,  Uint16 width, Uint16 height);
void VOS_FREE(void *pData);

typedef enum 
{
      Mirror_image=1,
	  Inverted_image ,
	  Rotate_to_the_left,
	  Rotate_to_the_right,
	  Up_and_down_together,
	  left_and_right_together,
	
}function;
const char * const funcChars[] = {
  "Mirror_image",
  "Inverted_image",
  "Rotate_to_the_left",
  "Rotate_to_the_right",
  "Up_and_down_together",
  "left_and_right_together",
};
typedef enum 
{
      YUV_420P_I420=1,
	  YUV_420P_YV12,
	  YUV_420SP_NV12,
	  YUV_420SP_NV21,
	  YUV_422P_I422,
	  YUV_422P_YV16,
	  YUV_422SP_NV16,
	  YUV_422SP_NV61
}format;
const char * const formatChars[] = {
  "YUV_420P_I420",
  "YUV_420P_YV12",
  "YUV_420SP_NV12",
  "YUV_420SP_NV21",
  "YUV_422P_I422",
  "YUV_422P_YV16",
  "YUV_422SP_NV16",
  "YUV_422SP_NV61"
};
typedef struct
{
	Uint32 width;
	Uint32 height;
	Uint32  size;
	format inType;
	format outType;
}intputParm;



Uint32 func_switch(Uint8 *I420, intputParm *obj, function type)
{
	
	Uint32 i, j;
	Uint8 *input = I420;
	Uint8 *outPtr = NULL;

	Uint8 *tmpPtr1 = NULL;
	Uint8 *tmpPtr2 = NULL;
	Uint8 *tmpPtr3 = NULL;
    Uint8 *yBuf = I420;
    Uint8 *uBuf = I420 + obj->size;
    Uint8 *vBuf = I420 + (obj->size)*5/4;
	Uint8 *yPtr = NULL;
    Uint8 *uPtr = NULL;
    Uint8 *vPtr = NULL;
	Uint8 *uvPtr = NULL;
	Uint8 *vuPtr = NULL;

	char outName[30];
    Uint32  size = obj->size;

	FILE* outputFile = NULL;
	char *outputName = NULL;
	
	switch (type)
	{
		case Mirror_image:
			outPtr = (Uint8*)malloc(obj->width * obj->height * 1.5 *sizeof(Uint8));

			if (NULL == outPtr)
			{
				printf("wrong malloc\n");
				return -1;
			}
			sprintf(outName, "%s_%d_%d.yuv", funcChars[type - 1], obj->width, obj->height);
			printf("%s\n",outName);
			outputFile = fopen(outName, "wb");
			tmpPtr1 = outPtr;
			tmpPtr2 = I420;
			/* Y */
			for(i = 0; i < (obj->height)*1.5 ; i++)
			{
				tmpPtr2 = I420 + (i+1)*(obj->width);
				for(j = 0; j < obj->width; j++)
				{
					*tmpPtr1 = *tmpPtr2;
					tmpPtr1++;
					tmpPtr2--;
				}

			}

			fwrite(outPtr, 1, size*3/2, outputFile);

			free(outPtr);
			fclose(outputFile);
			break;
		case Inverted_image:
			outPtr = (Uint8*)malloc(obj->width * obj->height * 3 *sizeof(Uint8));
			if (NULL == outPtr)
			{
				printf("wrong malloc\n");
				return -1;
			}

			sprintf(outName, "%s_%d_%d.yuv", funcChars[type - 1], obj->width, obj->height*2);
			printf("%s\n",outName);
			outputFile = fopen(outName, "wb");
			tmpPtr1 = outPtr;

			/* Y */
			memcpy(tmpPtr1, yBuf, (obj->size));
			tmpPtr1 = tmpPtr1 + obj->size;
			
			for(i = 0; i < obj->height; i++)
			{
				tmpPtr2 = I420 + (obj->height-1)*obj->width - i*(obj->width);
				for(j = 0; j < obj->width; j++)
				{
					*tmpPtr1 = *tmpPtr2;
					tmpPtr1++;
					tmpPtr2++;
				}

			}

			/* U */
			memcpy(tmpPtr1, uBuf, (obj->size)/4);
			tmpPtr1 = tmpPtr1 + (obj->size)/4;
			for(i = 0; i < (obj->height)/4; i++)
			{
				tmpPtr2 = I420 + (obj->height*5/4-1)*obj->width - i*(obj->width);
				for(j = 0; j < obj->width; j++)
				{
					*tmpPtr1 = *tmpPtr2;
					tmpPtr1++;
					tmpPtr2++;
				}

			}
			
			/* V */
			memcpy(tmpPtr1, vBuf, (obj->size)/4);
			tmpPtr1 = tmpPtr1 + (obj->size)/4;
			for(i = 0; i < (obj->height)/4; i++)
			{
				tmpPtr2 = I420 + (obj->height*3/2-1)*obj->width - i*(obj->width);
				for(j = 0; j < obj->width; j++)
				{
					*tmpPtr1 = *tmpPtr2;
					tmpPtr1++;
					tmpPtr2++;
				}

			}

			fwrite(outPtr, 1, size*3, outputFile);

			free(outPtr);
			fclose(outputFile);
			break;
		case Rotate_to_the_left:
			outPtr = (Uint8*)malloc(obj->width * obj->height * 1.5 *sizeof(Uint8));

			if (NULL == outPtr)
			{
				printf("wrong malloc\n");
				return -1;
			}
			sprintf(outName, "%s_%d_%d.yuv", funcChars[type - 1], obj->height, obj->width);
			printf("%s\n",outName);
			outputFile = fopen(outName, "wb");
			tmpPtr1 = outPtr;
			tmpPtr2 = I420;
			/* Y */
			for(i = 0; i < (obj->width); i++)
			{
				tmpPtr2 = I420 + obj->width -i;
				for(j = 0; j < obj->height ; j++)
				{
					*tmpPtr1 = *tmpPtr2;
					tmpPtr1++;
					tmpPtr2 = (I420 + obj->width -i) + (j+1)*obj->width;
				}

			}
			
			tmpPtr1 = outPtr +size;
			for(i = 0; i < (obj->width); i++)
			{
				tmpPtr2 = I420 + size +obj->width -i;
				for(j = 0; j < ((obj->height) / 4) ;j++)
				{
					*tmpPtr1 = *tmpPtr2;
					tmpPtr1++;
					tmpPtr2 = (I420 + size +obj->width -i) + (j+1)*obj->width;
				}

			}
			tmpPtr1 = outPtr +size*5/4;
			for(i = 0; i < (obj->width); i++)
			{
				tmpPtr2 = I420 + size*5/4 +obj->width -i;
				for(j = 0; j < ((obj->height) / 4 ); j++)
				{
					*tmpPtr1 = *tmpPtr2;
					tmpPtr1++;
					tmpPtr2 = (I420 + size*5/4 +obj->width -i) + (j+1)*obj->width;
				}

			}
			fwrite(outPtr, 1, size*3/2, outputFile);

			free(outPtr);
			fclose(outputFile);
			break;

		case Rotate_to_the_right:
			/* code */
			break;
		case Up_and_down_together:
			outPtr = (Uint8*)malloc(obj->width * obj->height * 3 *sizeof(Uint8));
			if (NULL == outPtr)
			{
				printf("wrong malloc\n");
				return -1;
			}

			sprintf(outName, "%s_%d_%d.yuv", funcChars[type - 1], obj->width, obj->height*2);
			printf("%s\n",outName);
			outputFile = fopen(outName, "wb");
			tmpPtr1 = outPtr;

			/* Y */
			memcpy(tmpPtr1, yBuf, (obj->size));
			tmpPtr1 = tmpPtr1 + obj->size;
			memcpy(tmpPtr1, yBuf, (obj->size));
			/* U */
			tmpPtr1 = tmpPtr1 + obj->size;
			memcpy(tmpPtr1, uBuf, (obj->size)/4);
			tmpPtr1 = tmpPtr1 + (obj->size)/4;
			memcpy(tmpPtr1, uBuf, (obj->size)/4);
			/* V */
			tmpPtr1 = tmpPtr1 + (obj->size)/4;
			memcpy(tmpPtr1, vBuf, (obj->size)/4);
			tmpPtr1 = tmpPtr1 + (obj->size)/4;
			memcpy(tmpPtr1, vBuf, (obj->size)/4);

			fwrite(outPtr, 1, size*3, outputFile);

			free(outPtr);
			fclose(outputFile);
			break;
		case left_and_right_together:
			outPtr = (Uint8*)malloc(obj->width * obj->height * 3 *sizeof(Uint8));
			if (NULL == outPtr)
			{
				printf("wrong malloc\n");
				return -1;
			}

			sprintf(outName, "%s_%d_%d.yuv", funcChars[type - 1], obj->width*2, obj->height);
			printf("%s\n",outName);
			outputFile = fopen(outName, "wb");
			tmpPtr1 = outPtr;
			tmpPtr2 = I420;
			tmpPtr3 = outPtr + obj->width;
			
			/* Y */
			for(i=0; i < (obj->height)*1.5; i++)
			{	
				tmpPtr1 = outPtr + i*(obj->width)*2;
				tmpPtr3 = outPtr + obj->width + i*(obj->width)*2;
				
				for(j = 0; j < (obj->width); j++){
					*tmpPtr1 = *tmpPtr2;
					//*(tmpPtr1+obj->width) = *tmpPtr2;
					*tmpPtr3 = *tmpPtr2;
					tmpPtr2++;
					tmpPtr1++;
					tmpPtr3++;
					
				}
			}
			
			fwrite(outPtr, 1, size*3, outputFile);

			free(outPtr);
			fclose(outputFile);
			break;	      


		default:
			break;
	}
	return 0;
}

int main(int argc, char** argv)
{
	char inName[30];
	FILE* rgbFile = NULL;
	Uint8* inBuf = NULL;
	intputParm parm;
	function type;
	printf("Mirror_image 			=1\n");
	printf("Inverted_image			=2\n");
	printf("Rotate_to_the_left		=3\n");
	printf("Rotate_to_the_right		=4\n");
	printf("Up_and_down_together	=5\n");
	printf("left_and_right_together	=6\n");

	printf("\n");
	printf("input function:");
	scanf("%u",&type);
	printf("type = %d\n", type);
	parm.inType		= 1;
	parm.outType	= 1;
	parm.width		= 500;
	parm.height		= 350;
	parm.size = parm.width * parm.height;
	sprintf(inName, "%s_%d_%d.yuv", formatChars[parm.inType - 1], parm.width, parm.height);
	rgbFile=fopen(inName,"rb");//打开down.rgb
	if (rgbFile == NULL)
	{
		printf("cannot find rgb file\n");
		exit(1);
	}

	inBuf = (Uint8 *)malloc(parm.width * parm.height * 3 * sizeof(Uint8));
	fread(inBuf, 1, parm.width * parm.height * 3, rgbFile);//读取down.rgb数据
	if (inBuf == NULL)
	{
		printf("wrong fread\n");
		exit(1);
	}
	
	
	func_switch(inBuf, &parm, type);

	return(0);
}

void VOS_FREE(void *pData)
{
    if (NULL != pData)
    {
        free(pData);
        pData = NULL;
    }
    return;
}


/*
			yBuf = (Uint8*)malloc(obj->width * obj->height * sizeof(Uint8));
			uBuf = (Uint8*)malloc(sizeof(Uint8) * (obj->width * obj->height) / 4);
			vBuf = (Uint8*)malloc(sizeof(Uint8) * (obj->width * obj->height) / 4);
			if (NULL == yBuf || NULL == uBuf || NULL == vBuf)
			{
				printf("wrong malloc\n");
				exit(1);
			}
			sprintf(outName, "%s_%d_%d.yuv", formatChars[obj->outType - 1], obj->width, obj->height);
			outputFile = fopen(outName, "wb");
			memcpy(yBuf, input, size);
			memcpy(uBuf, input + size, size/4);
			memcpy(vBuf, input + size*5/4, size/4);
			fwrite(yBuf, 1, size, outputFile);
			fwrite(vBuf, 1, size/4, outputFile);
			fwrite(uBuf, 1, size/4, outputFile);
			*/
/*1*/



/*2*/
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <string.h>
#define Uint8   unsigned char
#define Uint16  unsigned short
#define Uint32  unsigned int
//Uint32 yuv420p_I420_YU12(Uint8 *I420,  Uint16 width, Uint16 height);
void VOS_FREE(void *pData);

typedef enum 
{
      YUV_420P_I420=1,
	  YUV_420P_YV12,
	  YUV_420SP_NV12,
	  YUV_420SP_NV21,
	  YUV_422P_I422,
	  YUV_422P_YV16,
	  YUV_422SP_NV16,
	  YUV_422SP_NV61
}format;
const char * const formatChars[] = {
  "YUV_420P_I420",
  "YUV_420P_YV12",
  "YUV_420SP_NV12",
  "YUV_420SP_NV21",
  "YUV_422P_I422",
  "YUV_422P_YV16",
  "YUV_422SP_NV16",
  "YUV_422SP_NV61"
};
typedef struct
{
	Uint32 width;
	Uint32 height;
	Uint32  size;
	format inType;
	format outType;
}intputParm;

Uint32 yuv420p_I420(Uint8 *I420, intputParm *obj)
{
	format type;
	Uint32 i, j;
	Uint8 *input = I420;
	Uint8 *outPtr = NULL;
    Uint8 *yBuf = I420;
    Uint8 *uBuf = I420 + obj->size;
    Uint8 *vBuf = I420 + (obj->size)*5/4;
	Uint8 *yPtr = NULL;
    Uint8 *uPtr = NULL;
    Uint8 *vPtr = NULL;
	Uint8 *uvPtr = NULL;
	Uint8 *vuPtr = NULL;

	char outName[30];
    Uint32  size = obj->size;

	FILE* outputFile = NULL;
	char *outputName = NULL;
	
	switch (obj->outType)
	{
		case YUV_420P_YV12:
			outPtr = (Uint8*)malloc(obj->width * obj->height * 1.5 *sizeof(Uint8));
			if (NULL == outPtr)
			{
				printf("wrong malloc\n");
				return -1;
			}

			yPtr = outPtr;
    		uPtr = outPtr + obj->size;
    		vPtr = outPtr + (obj->size)*5/4;

			sprintf(outName, "%s_%d_%d.yuv", formatChars[obj->outType - 1], obj->width, obj->height);
			outputFile = fopen(outName, "wb");

			memcpy(yPtr, yBuf, obj->size);
			memcpy(uPtr, vBuf, (obj->size)/4);
			memcpy(vPtr, uBuf, (obj->size)/4);

			fwrite(outPtr, 1, size*3/2, outputFile);

			free(outPtr);
			fclose(outputFile);
			break;
		case YUV_420SP_NV12:
			outPtr = (Uint8*)malloc(obj->width * obj->height * 1.5 *sizeof(Uint8));
			if (NULL == outPtr)
			{
				printf("wrong malloc\n");
				return -1;
			}

			yPtr = outPtr;
    		uvPtr = outPtr + obj->size;
    		
			sprintf(outName, "%s_%d_%d.yuv", formatChars[obj->outType - 1], obj->width, obj->height);
			outputFile = fopen(outName, "wb");

			memcpy(yPtr, yBuf, obj->size);
			for (i = 0, j = 0; i < (obj->size)/2 ; i += 2, j++)
			{
				uvPtr[i]	= uBuf[j];
				uvPtr[i+1]	= vBuf[j];
			}

			fwrite(outPtr, 1, size*3/2, outputFile);

			free(outPtr);
			fclose(outputFile);
			break;
		case YUV_420SP_NV21:
			outPtr = (Uint8*)malloc(obj->width * obj->height * 1.5 *sizeof(Uint8));
			if (NULL == outPtr)
			{
				printf("wrong malloc\n");
				return -1;
			}

			yPtr = outPtr;
    		uvPtr = outPtr + obj->size;
    		
			sprintf(outName, "%s_%d_%d.yuv", formatChars[obj->outType - 1], obj->width, obj->height);
			outputFile = fopen(outName, "wb");

			memcpy(yPtr, yBuf, obj->size);
			for (i = 0, j = 0; i < (obj->size)/2 ; i += 2, j++)
			{
				uvPtr[i]	= vBuf[j];
				uvPtr[i+1]	= uBuf[j];
			}

			fwrite(outPtr, 1, size*3/2, outputFile);

			free(outPtr);
			fclose(outputFile);
			break;
		case YUV_422P_I422:
			outPtr = (Uint8*)malloc(obj->width * obj->height * 2 *sizeof(Uint8));
			if (NULL == outPtr)
			{
				printf("wrong malloc\n");
				return -1;
			}

			yPtr = outPtr;
			uPtr = outPtr + obj->size;
    		vPtr = outPtr + (obj->size)*3/2;
    		
			sprintf(outName, "%s_%d_%d.yuv", formatChars[obj->outType - 1], obj->width, obj->height);
			outputFile = fopen(outName, "wb");

			memcpy(yPtr, yBuf, obj->size);
			for (i = 0, j = 0; i < (obj->size)/2 ; i += 2, j++)
			{
				uPtr[i]		= uBuf[j];
				uPtr[i+1]	= uBuf[j];
				vPtr[i]		= vBuf[j];
				vPtr[i+1]	= vBuf[j];
			}

			fwrite(outPtr, 1, size*2, outputFile);

			free(outPtr);
			break;
		case YUV_422P_YV16:
			outPtr = (Uint8*)malloc(obj->width * obj->height * 2 *sizeof(Uint8));
			if (NULL == outPtr)
			{
				printf("wrong malloc\n");
				return -1;
			}

			yPtr = outPtr;
			uPtr = outPtr + obj->size;
    		vPtr = outPtr + (obj->size)*3/2;
    		
			sprintf(outName, "%s_%d_%d.yuv", formatChars[obj->outType - 1], obj->width, obj->height);
			outputFile = fopen(outName, "wb");

			memcpy(yPtr, yBuf, obj->size);
			for (i = 0, j = 0; i < (obj->size)/2 ; i += 2, j++)
			{
				uPtr[i]		= vBuf[j];
				uPtr[i+1]	= vBuf[j];
				vPtr[i]		= uBuf[j];
				vPtr[i+1]	= uBuf[j];
			}

			fwrite(outPtr, 1, size*2, outputFile);

			free(outPtr);
			break;
		case YUV_422SP_NV16:
			outPtr = (Uint8*)malloc(obj->width * obj->height * 2 *sizeof(Uint8));
			if (NULL == outPtr)
			{
				printf("wrong malloc\n");
				return -1;
			}

			yPtr = outPtr;
			uvPtr = outPtr + obj->size;
    		
    		
			sprintf(outName, "%s_%d_%d.yuv", formatChars[obj->outType - 1], obj->width, obj->height);
			outputFile = fopen(outName, "wb");

			memcpy(yPtr, yBuf, obj->size);
			for (i = 0, j = 0; i < (obj->size) ; i += 4, j++)
			{
				uvPtr[i]	= uBuf[j];
				uvPtr[i+1]	= vBuf[j];
				uvPtr[i+2]	= uBuf[j];				
				uvPtr[i+3]	= vBuf[j];
			}

			fwrite(outPtr, 1, size*2, outputFile);

			free(outPtr);
			break;
		
		case YUV_422SP_NV61:
			outPtr = (Uint8*)malloc(obj->width * obj->height * 2 *sizeof(Uint8));
			if (NULL == outPtr)
			{
				printf("wrong malloc\n");
				return -1;
			}

			yPtr = outPtr;
			uvPtr = outPtr + obj->size;
    		
    		
			sprintf(outName, "%s_%d_%d.yuv", formatChars[obj->outType - 1], obj->width, obj->height);
			outputFile = fopen(outName, "wb");

			memcpy(yPtr, yBuf, obj->size);
			for (i = 0, j = 0; i < (obj->size) ; i += 4, j++)
			{
				uvPtr[i]	= vBuf[j];
				uvPtr[i+1]	= uBuf[j];
				uvPtr[i+2]	= vBuf[j];				
				uvPtr[i+3]	= uBuf[j];
			}

			fwrite(outPtr, 1, size*2, outputFile);

			free(outPtr);
			break;
		default:
			break;
	}


    return 0;
}


int main(int argc, char** argv)
{
	char inName[30];
	FILE* rgbFile = NULL;
	Uint8* inBuf = NULL;
	intputParm parm;

	printf("Input Parameters: Input format, Output format, Width, Height\n");
	printf("YUV_420P_I420 =1\n");
	printf("YUV_420P_YV12 =2\n");
	printf("YUV_420SP_NV12=3\n");
	printf("YUV_420SP_NV21=4\n");
	printf("YUV_422P_I422 =5\n");
	printf("YUV_422P_YV16 =6\n");
	printf("YUV_422SP_NV16=7\n");
	printf("YUV_422SP_NV61=8\n");
	printf("\n");
	printf("input:");
	scanf("%u%u%u%u",&(parm.inType), &(parm.outType), &(parm.width), &(parm.height));
	printf("parms:%d %d %u %u\n", parm.inType, parm.outType, parm.width, parm.height);

	parm.size = parm.width * parm.height;
	sprintf(inName, "%s_%d_%d.yuv", formatChars[parm.inType - 1], parm.width, parm.height);
	rgbFile=fopen(inName,"rb");//打开down.rgb
	if (rgbFile == NULL)
	{
		printf("cannot find rgb file\n");
		exit(1);
	}

	inBuf = (unsigned char*)malloc(parm.width * parm.height * 3 * sizeof(unsigned char));
	fread(inBuf, 1, parm.width * parm.height * 3, rgbFile);//读取down.rgb数据
	if (inBuf == NULL)
	{
		printf("wrong fread\n");
		exit(1);
	}
	
	yuv420p_I420(inBuf, &parm);

	return(0);
}

void VOS_FREE(void *pData)
{
    if (NULL != pData)
    {
        free(pData);
        pData = NULL;
    }
    return;
}


/*
			yBuf = (Uint8*)malloc(obj->width * obj->height * sizeof(Uint8));
			uBuf = (Uint8*)malloc(sizeof(Uint8) * (obj->width * obj->height) / 4);
			vBuf = (Uint8*)malloc(sizeof(Uint8) * (obj->width * obj->height) / 4);
			if (NULL == yBuf || NULL == uBuf || NULL == vBuf)
			{
				printf("wrong malloc\n");
				exit(1);
			}
			sprintf(outName, "%s_%d_%d.yuv", formatChars[obj->outType - 1], obj->width, obj->height);
			outputFile = fopen(outName, "wb");
			memcpy(yBuf, input, size);
			memcpy(uBuf, input + size, size/4);
			memcpy(vBuf, input + size*5/4, size/4);
			fwrite(yBuf, 1, size, outputFile);
			fwrite(vBuf, 1, size/4, outputFile);
			fwrite(uBuf, 1, size/4, outputFile);
			*/
/*2*/
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值