数据类型
数据类型是由编译器创建的,目的是为了更好的管理内存;
可以理解为创建变量的模具,固定大小内存的别名。

数据类型别名:typedef使用
起别名 - 简化struct关键字
区分数据类型
提高代码移植性
示例
struct person
{
char name[64];
int age;
};
typedef struct person myPerson;
void test()
{
struct person p = { "aaa",16 };
myPerson p2 = { "bbb",18 };
}
void test1()
{
char* p1, p2;
typedef char* PCHAR;
PCHAR p3, p4;
char* p5, * p6;
}
typedef long long MYINT;
void test3()
{
MYINT a = 10;
MYINT b = 10;
}
int main(void)
{
system("pause");
return EXIT_SUCCESS;
}
void使用
不可以利用void创建变量 无法给无类型变量分配内存
用途:限定函数返回值,函数参数
void * 万能指针 可以不通过强制类型转换就转成其他类型指针
示例
void test01()
{
}
void test02(void)
{
}
void test03()
{
void* p = NULL;
int* pint = NULL;
char* pchar = NULL;
pchar = (char*)pint;
pchar = p;
}
int main(void)
{
system("pause");
return EXIT_SUCCESS;
}
sizeof用法
本质:不是一个函数,是一个操作符
返回值类型 unsigned int无符号整型
用途:可以统计数组长度
示例
void test01()
{
printf("size of int =%d\n", sizeof(int));
double d = 3.14;
printf("size of d = %d\n", sizeof d);
}
void test02()
{
unsigned int a = 10;
if (sizeof(int)-10 > 0)
{
printf("大于0\n");
}
else
{
printf("小于0\n");
}
if (a - 20 > 0)
{
printf("大于0\n");
}
else
{
printf("小于0\n");
}
}
void calArr(int arr[])
{
printf("calArr length =%d\n", sizeof(arr));
}
void test03()
{
int arr[] = { 1,2,3,4,5,6,7,8 };
printf("arr length =%d\n", sizeof(arr));
calArr(arr);
}
int main(void)
{
test02();
system("pause");
return EXIT_SUCCESS;
}
变量的修改方式
直接修改
直接赋值
间接修改
通过指针修改
示例:对自定义数据类型做练习
void test01()
{
int a = 10;
a = 20;
int* p = &a;
*p = 30;
printf("a =%d\n", a);
}
struct Person
{
char a;
int b;
char c;
int d;
};
void test02()
{
struct Person p = { 'a',10,'b',20 };
p.d = 1000;
struct Person* pp = &p;
pp->d = 100;
printf("%d\n", pp);
printf("%d\n", pp + 1);
char* pc = &p;
*(int*)(pc + 12) =2000;
printf("p的d属性为:%d\n", p.d);
printf("p的d属性为:%d\n", *(int*)(pc + 12));
printf("p的d属性为:%d\n", *(int*)((int*)pc + 3));
}
int main(void)
{
test02();
system("pause");
return EXIT_SUCCESS;
}
内存分区
运行前
程序编译过程:
1)预处理:宏定义展开、头文件展开、条件编译,不检查语法
2)编译:检查语法,将预处理后的文件编译生成汇编文件
3)汇编:将汇编文件生成目标文件(二进制文件)
4)链接:将目标文件链接为可执行程序

代码区text:
放代码; 共享 只读
数据区
存放数据:全局变量、静态变量、常量
已初始化数据区:data
存放数据:已赋初值的全局变量 、静态变量、常量
未初始化数据区:bss
存放数据:未赋初值的全局变量、静态变量、常量
在程序执行前被内核初始化为0或NULL(空)
运行后
栈stack:
栈是一种先进后出的内存结构,由编译器自动分配释放,存放函数的参数值、返回值、局部变量等。
在程序运行过程中实时加载和释放,因此,局部变量的生存周期为申请到释放该段栈空间。
编译器自动管理分配和释放,有限容量
堆heap:
是一个大容器,容量远远大于栈,不是无限。
没有栈那样先进后出的顺序,用于动态内存分配,堆在内存中位于BSS区和栈区之间。
手动开辟 malloc 手动释放 free。
若不释放,程序执行完后由系统回收。
栈区
符合先进后出数据结构
注意事项:不要返回局部变量的地址,局部变量在函数执行之后就被释放了,释放的内存就没有权限取操作了,如果操作结果未知。

示例
int myFunc()
{
int a = 10;
return &a;
}
void test01()
{
int* p = myFunc();
printf("*p =%d\n", *p);
printf("*p=%d\n", *p);
}
char* getString()
{
char str[] = "hello world";
return str;
}
void test02()
{
char* p = NULL;
p = getString();
printf("%s\n", p);
}
int main(void)
{
test02();
system("pause");
return EXIT_SUCCESS;
}
堆区
利用malloc在堆区创建数据
利用free释放堆区
注意事项:主调函数没有分配内存,被调函数需要用更高级的指针去修饰低级指针,进行分配内存
同级指针修饰内存失败解析图

高级指针给修饰低级指针成功解析图

示例
int* getSpace()
{
int* p = malloc(sizeof(int) * 5);
if(p==NULL)
{
return;
}
for (int i = 0; i < 5; i++)
{
p[i] = i + 100;
}
return p;
}
void test01()
{
int* p = getSpace();
for (size_t i = 0; i < 5; i++)
{
printf("%d\n",p[i]);
}
free(p);
p = NULL;
}
void allocateSpace(char* pp)
{
char* temp = malloc(100);
memset(temp, 0, 100);
strcpy(temp, "helloworld");
pp = temp;
}
void test02()
{
char* p = NULL;
allocateSpace(p);
printf("%s\n", p);
}
void allocateSpace1(char** ppc)
{
char* temp = malloc(100);
memset(temp, 0, 100);
strcpy(temp, "helloworld");
* ppc = temp;
}
void test03()
{
char* pc = NULL;
allocateSpace1(&pc);
printf("%s\n", pc);
}
int main(void)
{
test03();
system("pause");
return EXIT_SUCCESS;
}
static 和extern 区别
static:特点:在运行前分配内存,程序运行结束 生命周期结束 ,在本文件内都可以使用静态变量
静态变量只能调用一次。
extern:可以提高变量作用域,在c语言下,全局变量前都隐式的加了extern关键字
示例
static int a = 10;
void test01()
{
static int b = 20;
}
int main(void)
{
extrern int p;
system("pause");
return EXIT_SUCCESS;
}
常量
const修饰的变量
全局变量
直接修改 失败 ,间接修改 语法通过,运行失败,受到常量区保护
局部变量
直接修改 失败 , 间接修改 成功,放在栈上
字符串常量
vs 将多个相同字符串常量看成一个;
不可以修改字符串常量
ANSI并没有制定出字符串是否可以修改的标准,根据编译器不同,可能最终结果也是不同的
示例
const int a = 10;
void test01()
{
int* p = &a;
*p = 100;
printf("%d\n", a);
}
void test02()
{
const int b = 10;
int* p = &b;
*p = 20;
printf("%d\n", b);
}
void test03()
{
char* p1 = "hello world";
char* p2 = "hello world";
char* p3 = "hello world";
printf("%d\n", &"hello world");
printf("%d\n", p1);
printf("%d\n", p2);
printf("%d\n", p3);
}
void test04()
{
char* str = "hello world";
str[0] = 'x';
}
int main(void)
{
test04();
system("pause");
return EXIT_SUCCESS;
}