位运算
一,按位运算
按位运算,把整数当作2进制的数字进行运算?
&按位与,|按位或,~按位取反,^按位的异或,<<左移, >>右移
1.1 &按位与
·如果(x)i==1并且(y)i==1,那么(x&y)=1
否则的话(x & y)i=0
按位与常用于两种应用:
·让某一位或某些位为 0 : x & 0xFE
·取一个数中的一段: x & 0xFF
1.2 |按位或
如果(x)i== 1或(y)i== 1,那么(x|y)i= 1
否则的话,(x|y)== 0
按位或常用于两种应用:
使得一位或几个位为1: x | 0x01
把两个数拼起来: 0x00FF I 0xFF00
1.3 ~按位取反
(~x)i= 1 -(x)i
把1位变0,0位变1
想得到全部位为1的数:~0
7的二进制是0111,x7使得低3位为1,而 x&~7,就使得低3位为0
和补码不一样补码是用1减?
#include<stdio.h>
int main(){
unsigned char c=0xAA;
printf("c=%hhx\n",c);
printf("~c=%hhx\n",(char)~c);//~-的运算结果是INT,希望看到字节大小的整数输出?类型转换
printf("-c=%hhx\n",(char)-c);
//aa,55,56
return 0;
}
对于逻辑运算,它只看到两个值:0和1
可以认为逻辑运算相当于把所有非0值都变成1,然后做按位运算
5 & 4->4而5&&4->1&1->1
5 | 4->5而5/4->111->1
~4->3而!4->!1->0
1.4 ^按位的异或
如果(x)i==(y)i,那么(x^ y)i= 0否则的话,(x^ y)i== 1
如果两个位相等,那么结果为0;不相等,结果为1
如果x和y相等,那么x^y的结果为0
对一个变量用同一个值异或两次,等于什么也没做x^y^y->x
二,移位运算
2.1 <<左移
i<<j, i中所有的位向左移动i个位置,而右边填入0
所有小于int的类型,移位以int的方式来做,结果是int
x<<= 1等价于x*=2
x<<= n等价于x*= 2^n
最多可以移位多少,取决于INT多大
#include<stdio.h>
int main(){
unsigned char c=0xA5;
printf(" c=%x\n",c);
printf("c<<2=%x\n",c<<2);
printf(" c=%d\n",c);
printf("c<<2=%d\n",c<<2);
return 0;
}
2.2 >>右移
i >> j
i中所有的位向右移j位
所有小于int的类型,移位以int的方式来做,结果是int
对于unsigned的类型,左边填入0 对于signed的类型,左边填入原来的最高位(保持符号不变)
x>>= 1 等价于x /= 2
x>>= n等价于 x /= 2^n
#include<stdio.h>
int main(){
int a=0x80000000;//4字节的整数所能表达的最大的负数,高位为1,负数
unsigned b =0x80000000;
printf("a=%d\n",a);
printf("b=%u\n",b);
printf("a>>1=%d\n",a>>1);
printf("b>>1=%u\n",b>>1);
//左移不管符号位
printf("a<<1=%d\n",a<<1);
printf("b<<1=%u\n",b<<1);
return 0;
}
移位的位数不要用负数,这是没有定义的行为
x<< -2 //!!NO!!
三,位运算例子
3,1 输出一个数字的二进制
#include<stdio.h>
int main(){
int num;
scanf("%d",&num);
unsigned mask=1u<<31;
//unsigned ,,,mask==unsigned int mask,省略
//1最低位为1,U是一个UNSIGNED的数,左移31位
//其实就是0X80000000,最高位为1的这个东西?
for( ;mask;mask>>=1){
printf("%d",num&mask?1:0);
//依次右移,每次结果和MAASK取余?
//逐一检查每一位是0 OR 1
}
printf("\n");
return 0;
}
3.2 MCU的SFR--不懂
什么单片机的特殊功能寄存器???
四,位段--不懂
上一小节的东西?只能控制一个比特,不能控制多个
位段——类似结构的结构,成员后面冒号+数字,表示这个成员占几个比特
把表的内容变成一个位段里面的一个个变量?
#include<stdio.h>
struct U0{
unsigned int leading:3;
unsigned int FLAG1:1;
unsigned int FLAG2:1;
int trailing:27;//3+1+2+27=32
};
void prtBin(unsigned int number);
int main(){
struct U0 uu;
uu.leading=2;
uu.FLAG1=0;
uu.FLAG2=1;
uu.trailing=0;//初始化
printf("sizeof(uu)=%lu\n",sizeof(uu));
prtBin(*(int*)&uu);//把UU当作一个整数,输出2进制
//取得uu的地址,&UU是一个指向U0的指针,强制类型转换为指向INT的指针
//再取指针,取得一个INT
return 0;
}
void prtBin(unsigned int number){
unsigned mask=1u<<31;
for( ;mask;mask>>=1){
printf("%d",number&mask?1:0);
}
printf("\n");
}
sizeof(uu)=4,最后5位是10010,1-0-010 ==FLAG2-FLAG1-leading,【写错FLAG2:2的时候,sizeof(uu)=8,所有的位段加起来超过32了,需要两个INT来表达他】
可以直接用位段的成员名称来访问,比移位、与、或还方便
编译器会安排其中的位的排列,不具有可移植性
当所需的位超过一个int时会采用多个int
用于比较底层的操作硬件的场所
可变数组--不懂
一,可变数组
可调整大小的阵列
考虑一组提供可调整大小的int数组机制的函数。
1,可生长的,2, 获取当前大小,3,对元素的访问
通过函数实现可增长数组的机制
create创建数组
free回收空间
size单元数量
at访问单元【数组可以读也可以写,可以做左值也可以做右值……】
INFLATE核心形式,让数组长大
定义的时候不要直接定义指针,指针虽然在传入函数的时候比较方便,但是指针使用的时候想调用一个变量,他是从某个地方调出来的,不是本地变量,看起来也充满欺骗性说用指针有两个风险,1是如果A指向NULL,2是如果A已经指向了一个有的数组,那么还要先做FREE的事情……抽象,感觉后面几节课听的都是“呵呵呵他在说些什么”
二,可变数组的数据访问,自动增长--不懂
我真的,根本听不明白还听着男神 “ 嗯哼~ ”
#ifndef _ARRAY_H_
#define _ARRAY_H_
typedef struct{
int *array;
int size;
}Array;
//不要直接定义指针
Array array_creat(int init_size);
void array_free(Array *a);
int array_size(const Array *a);
int* array_at(Array *a,int index);
void array_inflate(Array *a,int more_size);
#endif
MALLOC出来的东西不能长大,我们重新申请一块新的空间
前面还跑着,后面两个函数就错了,我也不知道错哪里
不懂代码在干什么根本无力调试……
#include <stdio.h>
#include <stdlib.h>
#include "araay.h"
const BLOCK_SIZE=20;
//typedef struct{
// int *array;
// int size;
//}Array;
Array array_creat(int init_size)
{
Array a;
a.size=init_size;
a.array=(int*)malloc(sizeof(int)*a.size);
return a; //返回一个本地变量?
}
void array_free(Array *a)
{
free(a->array);
a->array=NULL;//保险,防止别人调两次
a->size=0;
}
//封装,把a保护起来了,也许随着算法改进,A的SIZE不能直接给你?
//把内部的实现细节保护起来,你不知道我怎么做的?
int array_size(const Array *a)
{
return a->size;
}
//为什么返回指针
int* array_at(Array *a,int index)
{
if(index>=a->size){
//array_inflate(a,index-a->size+1);
//每次长一个,太慢,一个单位BLOCK的概念
array_inflate(a,(index/BLOCK_SIZE+1)*BLOCK_SIZE-a->size+1);
// 从1开始数的序号?
}//越界,还有-1的情况没写
return &(a->array[index]);
}
//给接受不了的
int array_get(const Array*a,int index)
{
return a->array[index];
}
void array_set(Array *a,int index,int value)
{
a->array[index]=value;
}//end
void array_inflate(Array *a,int more_size)
{
int *p=(int*)malloc(sizeof(int)(a->size+more_size));//error
int i;
for(i=0;i<a->size;i++){
p[i]=a->array[i];
}//遍历拷贝,可以用标准库MEMCTY替代,效率更高
free(a->array);
a->array=p;
a->size+=more_size;
}
int main(int argc, char *argv[]) {
Array a=array_creat(100); //函数返回的是一个结构,可以赋值
printf("%d\n",array_size(&a));
//printf("%d\n",a.size);
*array_at(&a,0)=10;//做赋值,a[0]位置上的值 ,*函数调用 ,接受不了就
printf("%d\n",*array_at(&a,0));
int number;
int cnt=0;
while(number!=-1){
scanf("%d",number);
if(number!=-1)
*array_at(&a,cnt++)=number;
//scanf("%d",array_at(&a,cnt++));
}
array_free(&a);
return 0;
}
我真的,后面的讲义放的都是英文,我怕我听懂了吗
链表--全不懂
一,可变数组的缺陷
每次膨胀时分配新内存是一种简单而干净的方法【每次都需要重新申请一块内存,全部拷贝】。但是复制需要时间,而且在内存受限的情况下可能会失败可能还有那么多空间,但是,没有办法申请这么多内存了
二,链表
HEAD,链表,结节
#ifndef _NODE_H_
#define _NODE_H_
typedef struct _node {
int value;
struct _node*next;//第6行没有Node出现
}Node;
#endif
#include <stdio.h>
#include <stdlib.h>
#include "node.h"
//typedef struct _node {
// int value;
// struct _node*next;
//}Node;
int main(int argc, char const* argv[])
{
Node*head=NULL;
int number;
do{
scanf("%d",&number);
if(number!=1){
//add to linked-list
Node*p=(Node*)malloc(sizeof(Node));
p->value=number;
p->next=NULL;//这是最后面的一个,新的一个
//find the last
Node*last=head;
if(last){
while(last->next){
last=last->next;
} //只要last指向有东西,那么就会一直循环,最后一个指向NULL,0循环停下
//attach
last->next=p;
}else{
head=p;//第一个是一个特殊的情况
}
}
}while(number!=1);
return 0;
}
三,链表的函数
神他的四种还是五种办法……呵呵不懂……炒一下代码得了
……算了,剩下几节先放放,我补一下前面的东西,刷点题,听都听不懂也不是办法
苦笑,哀嚎,扭曲
四,链表的搜索
五,链表的删除
六,链表的清除
呵呵,希望我4月到来之前能学懂
标签:听懂,int,number,链表,20240328,printf,array,Array,size From: https://blog.csdn.net/qq_51583806/article/details/137093421