全局静态变量:存放全局变量和静态变量,空间由系统管理,程序执行时开辟空间,程序结束空间回收,在程序运行期间其空间一直存在
常量区:存储常量,常量区的内容在程序运行期间不会发生改变,空间由系统管理,生命周期和系统的生命周期一致.
代码区:存放程序执行的CPU指令,其实就是程序开发中所有的字符,代码标点等;
栈区:在函数内部定义的局部变量局部数组,其内存都是开辟在栈区,栈区内存由系统管理,函数被调用时开辟空间,函数执行结束空间回收.
堆区:空间开发人员手动开发,手动回收,是我们今后主要操作的内存区域;
栈区空间
int a = 0;//变量a的空间在栈区
堆区
关键字malloc:在堆区开辟空间的重要函数.malloc(size_t --size) size_t就是在堆区要开辟字节数.
viod * 在此指的是泛型,其实就是开辟的空间任何类型数据都可以使用.
int *p = malloc(4);//在堆取开4个字节的空间,里面存放 整形的数
堆区开的空间 可以让任何类型的指针来接受
练习1:在堆取上开辟3个短整形的数据的空间 并且赋值
short *s = malloc(sizeof(short) * 3);
*s = 7;
*(s + 1) = 8;
*(s + 2) = 9;
printf("%d %d %d \n",*s,*(s+1),*(s+2));
练习2:将10个int型数据,存入对区中
int *p3 = malloc(sizeof(int) * 10);
for (int i = 0; i < 10;i++){
*(p3 + i) = arc4random() % ( 80 - 30 + 1 ) + 30;
printf("%d ",*(p3 + i));
}
free(p3);
p3 = NULL;
printf("");
练习3:定义short指针 堆区内存 10 个整形数据 范围[20,50] 求出最大值
int max = 0;
short *p4 = malloc(sizeof(short) * 10);
for (int i = 0; i < 10; i++) {
*p4++ = arc4random() % (50 - 20 + 1) + 20;
if (*(p4 - 1) > max) {
max = *(p4 - 1);
}
printf("%d ",*(p4 - 1));
}
for (int i = 0; i < 10; i++) {
p4--;
}
printf("\nmax = %d\n",max);
释放内存 free(void *); 释放任意类型的内存
//free(p4);
安全起见,释放的只是平指向的空间的所有权,但是此时p4仍然指向已经释放的空间所以....
p4 = NULL;
并且,C语言中释放内存只是释放对此块的内存的所有权,但是不会清除内存中的数据,这就是为什么我们声明变量需要初始化赋初始值.
注意 使用指针来释放指针所指的空间,必须保证指针指向的是空间的首地址
练习4 在堆取开辟空间,存储5个整形数据,赋值范围[30,70],并对这几个数进行生序排序
int *p5 = malloc(sizeof(int) * 5);
for (int i = 0; i < 5; i++) {
*(p5 + i) = arc4random() % (70 - 30 + 1) + 30;
}
for (int i = 0; i < 5 - 1; i++) {
for (int j = 0; j < 5 - 1 - i; j++) {
int temp = 0;
if (*(p5 + j) > *(p5 + j + 1)) {
temp = *(p5 + j);
*(p5 + j) = *(p5 + j + 1);
*(p5 + j + 1) = temp;
}
}
}
for (int i = 0; i < 5; i++) {
printf("%d ",*(p5 + i));
}
练习5:有一个已知的整形数组元素个数为10,赋随机值[20,40],将大于30的数存储到堆区空间中
int pArray[10];
int count = 0;
for (int i = 0; i < 10; i++) {
pArray[i] = arc4random() % (40 - 20 + 1) + 20;
printf("%d ",pArray[i]);
//这次for循环为了将大于30的数添加到堆区中
for (int i = 0; i < 10; i++) {
if (pArray[i] > 30) {
*p30++ = pArray[i];
}
}
p30--;
printf("\n");
for (int i = 0; i < count; i++) {
printf("%d ",*p30--);
}
练习6 :已知的字符串,其中包含数字和字符,提取其中的数字,存储到堆区空间上
char str[] = "h4fjid6hfiu479jkx2";
int num = 0; //存放数字的个数
for (int i = 0; i < strlen(str); i++) {
if (str[i] >= '0' && str[i] <= '9') {
num++;
}
}
//根据数字个数在堆区开空间,注意字符\0为了方便输出,我们可以把字符数组存储城字符串的格式
char *p7 = malloc(num + 1);// 1 要放\0
for (int i = 0; i < num; i++) {
if (str[i] >= '0' && str[i] <= '9') {
*p7++ = str[i];
}
}
//在末尾位置补上\0;
*p7= '\0';
//将指向最后一个元素首地址的指针设置重指向,指向字符串首地址
p7 = p7 - num;
printf("提取的数字为:%s\n", p7);
free(p7);
p7 = NULL;
其他内存分配函数
calloc(count , size);分配count个size大小的空间,比malloc多一个功能,就是clear清楚空间遗留数据的操作,但是执行效率较低,常用的还是malloc
int *q = calloc(5, 4);
for (int i = 0; i < 5; i++) {
q[i] = arc4random() % 21;
printf("%d",q[i]);
}
free(q);
q = NULL;
realloc(<#void *#>, <#size_t#>)将指针p所指向的空间字节数重置成size个(size可以比原来字节数大也可以比原来空间字节数小)
int *q1 = malloc(12);
*q1 = 10;
*(q1 + 1) = 20;
*(q1 + 2) = 30;
printf("%p \n",q1);
//重置为20 个字节
q1 = realloc(q1, 20);
*(q1 +3) = 67;
printf("%p \n",q1);
//-------以上三个函数都是操作与堆区中的----------------------
下面是内存操作函数(各种区域中都可使用)
1.依据指定字节重新赋值的函数;memset (开始地址 , n size)
//给定一个起始地址,将字节的数据设置为n,size为10,就意味着将10个字节的数据设置为0;
printf("清零之前:%d\n",*q1);
memset(q1, 0, 4);
printf("清零之后:%d\n",*q1);
2,memcpy(目的地址,原地址,size)
//从源地址中拷贝size个字节的数据到目的地址中
// 10 20 30
memcpy(q1 + 1, q1 + 2, 4);
printf("%d \n",*(q1 + 1));
3,memcmp (目的地址 原地址 size)
//将俩个地址开始的数据比较size个字节的大小
*(q1 + 1) = 20;
*(q1 + 2) = 30;
int result = memcmp(q1+1, q1+2, 4);
printf("result = %d\n",result);
练习7:定义俩个整形指针,分别用malloc calloc 对其分配3个整形氮元素的空间,但是malloc空间要使用memset做数据清空操作在赋值使用,随机对这俩块空间赋值[1,3],赋值后用memcmp比较俩个数组,如果值都相同就打印good,否则就打印no
int *q11 = calloc(sizeof(int) , 3);
int *q22 = malloc(sizeof(int) * 3);
memset(q11, 0, 12);
for (int i = 0; i < 3; i++) {
*(q11+i) = arc4random() % 3 + 1;
q22[i] = arc4random() % 3 + 1;
printf("q22 = %d, q11 = %d\n",q11[i]);
}
int result1 = memcmp(q11, q22, 12);
printf(result1==0 ? "Good" : "Oh");
//静态变量 --- 全局区/ 静态区;
static int a1 = 9;
int *q6 = &a1;
printf("\n%p\n",q6);
网友评论