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,9,10,11,12};
//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,9,10,11,12};
//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);
分配得来得10和20字节的区域就在堆区。
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修饰的函数作用域只是声明的文件中
-
修饰局部变量:(编译器一般不对局部变量进行初始化,除非显示的赋值),静态局部变量使用static修饰符定义,即使在声明时未赋初值,编译器也会把它初始化为0。且静态局部变量存储于进程的全局数据区,即使函数返回,它的值也会保持不变。该变量的内存只被分配一次,因此其值在下次调用时仍维持上次的值
-
修饰全局变量:
全局变量定义在函数体外部,在全局数据区分配存储空间,且编译器会自动对其初始化。
普通全局变量对整个工程可见,其他文件可以使用extern外部声明后直接使用。也就是说其他文件不能再定义一个与其相同名字的变量了(否则编译器会认为它们是同一个变量)。
静态全局变量仅对当前文件可见,其他文件不可访问,其他文件可以定义与其同名的变量,两者互不影响。
-
函数
函数的使用方式与全局变量类似,在函数的返回类型前加上static,就是静态函数。其特性如下:
-
静态函数只能在声明它的文件中可见,其他文件不能引用该函数
-
不同的文件可以使用相同名字的静态函数,互不影响。
-
-
在类中的static成员变量属于整个类所拥有,对类的所有对象只有一份拷贝
-
在类中的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关键字
- 可以理解为“编译器警告指示字”
- 用于告诉编译器必须每次去内存中取变量值
- 主要修饰可能被多个线程访问的变量
- 也可以修饰可能被未知因素修改的变量
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(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的区别?
- #define宏常量只是简单的进行值替换,枚举常量是真正意义上的常量
- #define无法被调试,nume可以
- #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*/