c基础-10(内存分配、位运算)

本文详细介绍了C语言中的内存分配原理,包括栈、堆以及静态存储区的使用,涉及malloc和free的申请与释放注意事项。同时讲解了位运算的基础概念及其在编程中的应用,以及无参宏定义的使用方法,提升代码可读性和效率。
摘要由CSDN通过智能技术生成

(内容为学习笔记,如有错误,还望指正,如有遗漏,还望补充) 

1.内存分配

1)内存分区(变量可能被分配的内存分区)

:函数中的参数局部变量存储在栈上

:程序中一块预留的内存空间,可由程序自由使用,堆中被程序申请使用的内存在被主动释放前将一直有效

静态全局变量静态局部变量

2)堆空间内存的申请释放

a.头文件:

#include<stdlib.h>

b.申请内存

void *malloc(size_t size);  
//申请后的结果是void地址,赋值给指针变量

//malloc前的(int *)表示将malloc申请的void类型地址强制转换位int类型地址
//10*sizeof(int)表示申请的地址大小是10个int类型地址大小,即40个字节
//这样申请出来的地址就可以当作数组来用,如p[0],p[1]..
int* p = (int *)malloc(10*sizeof(int));

c.释放内存

void free(void *p);
p = NULL;

//free只是释放了指针p指向位置内存上的数据,并没有改变指针p的指向
//如果在此调用可能会发生错误
//free释放指针后应该将指针置空

3)注意事项

a.malloc 和 free 成对去写。(malloc 申请的空间,使用结束后,要及时的free )malloc不free会造成 内存泄漏。

b. malloc 申请内存,会成功或失败,如果成功,则可以使用申请来的堆空间。 如果失败,会返回 NULL(NULL就是0 空指针。内存不够就会失败)。

c. 在堆内存被释放掉之后,及时将指针 p 归零,以防出现使用这块已经被释放掉的内存,造成不必要的风险(野指针)。

2.位运算

1)左移右移

<< //左移
>> //右移

左移示例

#include <stdio.h> 
​
int main()
{
    char a = 1;            //二进制0000 0001
    a = a<<1;              //左移1位,0000 0010
    printf("%d\n", a);     //输出2
    a = a<<2;              //再左移2位,0000 1000
    printf("%d\n", a);     //输出8
    return 0;
}

右移示例

#include <stdio.h> 
​
int main()
{
    unsigned char a = 8;  //二进制位0000 1000
    a = a>>1;             //右移1位,0000 0100
    printf("%d\n", a);    //输出4
    a = a>>2;             //右移2位,0000 0001
    printf("%d\n", a);    //1
    return 0;
}

2)按位取反

~

将变量中所有的位,1变成0,0变成1

#include<stdio.h>

int main()
{
    unsigned char a = 0x0f; //十六进制0f 二进制0000 1111
    printf("%x\n",a);       //输出f
    a = ~a;                 //取反为0xf0 二进制1111 0000
    printf("%x\n",a);       //输出f0
    return 0;
}

3)按位与

&

双目运算 对应的位,有一个为0结果就是0

#include <stdio.h> 

int main()
{
	unsigned char a = 0xA5;    //二进制1010 0101
	unsigned char b = 0x8C;    //二进制1000 1100
	unsigned char c = a&b;     //有0得0
	printf("%#x\n", c);        //输出0x84,二进制1000 0100
	return 0;
}

4)按位或

|

双目运算 对应的位,有一个为0结果就是0

指定的二进制位,写1

#include <stdio.h> 

int main()
{
	unsigned char a = 0xA5;    //二进制1010 0101
	unsigned char b = 0x8C;    //二进制1000 1100
	unsigned char c = a|b;     //有1得1
	printf("%#x\n", c);        //输出0xAD,二进制1010 1101
	return 0;
}

5)按位异或

^

指定位取反 对应的位,相同得0,不同得1

#include <stdio.h> 

int main()
{
	unsigned char a = 0xA5;    //二进制1010 0101
	unsigned char b = 0x8C;    //二进制1000 1100
	unsigned char c = a^b;     //相同得0,不同得1
	printf("%#x\n", c);        //输出0x29,二进制0010 1001
	return 0;
}

 3.宏定义(无参)

1)为什么使用无参宏定义

        因为程序中有时可能会出现多次使用的某个特定数值,例如我想用0代表上,1代表下,2代表左,3代表右,在开发过程中这样的数值不好记忆使用,对阅读程序的人也是一种折磨,这时候使用无参宏定义就可以解决这个问题,将这样特定的数值用自定义的名字来代替,可以增强程序的可读性。

2)定义无参宏

#define 宏定义名字 值

3)举例说明

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

//上下左右
#define UP 0
#define DOWN 1
#define LEFT 2
#define RIGHT 3

int main()
{
    srand(time(0));
    int dir  = rand()%4;
    if(dir == UP) printf("UP is %d\n",dir);
    else if(dir == DOWN) printf("DOWN is %d\n",dir);
    else if(dir == LEFT) printf("LEFT is %d\n",dir);
    else if(dir == RIGHT) printf("RIGHT is %d\n",dir);
    else printf("error\n"); 

    return 0;
}

小知识:

1)如何将某个特定位置0?

unsigned char a;
a = a&~(1<<n);//将变量a的n位写0
//例如unsigned char a = 0x1D; 即0001 1101
//a = a&~(1<<5);
//1<<5,1左移5位,即0001 0000
//按位取反,即1110 1111
//按位与,有0得0,结果为0000 1101
//a == 0x0D

2)如何将某个特定位置1?

unsigned char a;
a = a|1<<n;
//a = 0x20,即0010 0000
//a = a|1<<5;
//1左移5位,即0001 0000
//按位或,有1得1
//a == 0x30,即0011 0000

 

  • 5
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值