当前位置: 首页 > news >正文

【CSAPP】家庭作业2.55~2.76

文章目录

  • 2.55*
  • 2.56*
  • 2.57*
  • 2.58**
  • 2.59**
  • 2.60**
  • 位级整数编码规则
  • 2.61**
  • 2.62***
  • 2.63***
  • 2.64*
  • 2.65****
  • 2.66***
  • 2.67**
  • 2.68**
  • 2.69***
  • 2.70**
  • 2.71*
  • 2.72**
  • 2.73**
  • 2.74**
  • 2.75***
  • 2.76*

2.55*

:在你能访问的不同的机器上,编译show_bytes.c并运行代码,确定这些机器的字节顺序。

// show_bytes.c
#include <stdio.h>typedef unsigned char *byte_pointer;void show_bytes(byte_pointer start, size_t len)
{for (size_t i = 0; i < len; ++i) {printf("%.2X ", start[i]);}printf("\n");
}void show_int(int x)
{show_bytes((byte_pointer)&x, sizeof(int));
}

x86_64上,运行结果为:

// show_int(0x87654321);
[liheng@localhost2 2]$ ./a.out 
21 43 65 87 

低位字节保存在低地址,该机器按小端顺序存储多字节对象。

2.56*

:试着用不同的示例值来运行show_bytes.c

// show_int(0x11223344);
[liheng@localhost2 2]$ ./a.out 
44 33 22 11 
// show_int(0x22);
[liheng@localhost2 2]$ ./a.out 
22 00 00 00 
// show_int(0x11000000);
[liheng@localhost2 2]$ ./a.out 
00 00 00 11 

2.57*

:编写并运行程序show_shortshow_longshow_double

void show_short(short x)
{show_bytes((byte_pointer)&x, sizeof(short));
}void show_long(long x)
{show_bytes((byte_pointer)&x, sizeof(long));
}void show_double(double x)
{show_bytes((byte_pointer)&x, sizeof(double));
}

x86_64上,运行结果为:

// show_short(0x1234);
// show_long(0x1234);
// show_double(0x1234);
[liheng@localhost2 2]$ ./a.out 
34 12 
34 12 00 00 00 00 00 00 
00 00 00 00 00 34 B2 40 
// show_short(0x1030);
// show_long(0x1030);
// show_double(0x1030);
[liheng@localhost2 2]$ ./a.out 
30 10 
30 10 00 00 00 00 00 00 
00 00 00 00 00 30 B0 40 

2.58**

:编写过程is_little_endian,当在小端法机器上运行时返回1,否则返回0

int is_little_endian()
{uint32_t x = 0x12345678; // #include <stdint.h>return *(uint8_t *)&x == (uint8_t)0x78;
}

x86_64上,运行结果为:

// printf("is_little_endian: %d\n", is_little_endian());
[liheng@localhost2 2]$ ./a.out 
is_little_endian: 1

2.59**

:编写一个C表达式,它生成一个字,由x的最低有效字节和y中剩下的字节组成。对于x = 0x89ABCDEFy = 0x76543210得到0x765432EF
:表达式为(x & 0xFF) | (y & ~0xFF)

2.60**

:假设我们将一个w位的字中的字节从0(最低位字节)到w / 8 - 1(最高位字节)编号,写出下面C函数的代码,它会返回一个无符号值,其中参数x的字节i被替换成字节b

unsigned replace_byte(unsigned x, int i, unsigned char b);
// replace_byte(0x12345678, 2, 0xAB) --> 0x12AB5678
// replace_byte(0x12345678, 0, 0xAB) --> 0x123456AB


replace_byte的实现:

unsigned replace_byte(unsigned x, int i, unsigned char b)
{unsigned bits = i << 3;unsigned x1 = x & ~(0xFF << bits);unsigned b1 = b << bits;return x1 | b1;
}

x86_64上的运行结果:

// printf("%p\n", replace_byte(0x12345678, 4, 0xAB));
// printf("%p\n", replace_byte(0x12345678, 3, 0xAB));
// printf("%p\n", replace_byte(0x12345678, 2, 0xAB));
// printf("%p\n", replace_byte(0x12345678, 1, 0xAB));
// printf("%p\n", replace_byte(0x12345678, 0, 0xAB));
[liheng@localhost2 2]$ ./a.out 
0x123456ab
0xab345678
0x12ab5678
0x1234ab78
0x123456ab

位级整数编码规则

在接下来的作业中,我们特意限制了你能使用的编程结构,来帮助你更好地理解C语言的位级、逻辑和算术运算。你的代码必须遵守以下规则:

  • 假设
  1. 整数用补码形式表示。
  2. 有符号数的右移是算术右移。
  3. 数据类型intw(一定是8的整数倍)位长的。某些题目会给出w的值。
  • 禁止使用
  1. 条件语句if? : 、循环、分支语句、函数调用和宏调用。
  2. 除法、模运算和乘法。
  3. 相对比较运算<><=>=
  • 允许的运算
  1. 所有的位级和逻辑运算。
  2. 左移和右移,位移量只能在0 ~ w-1之间。
  3. 加法和减法。
  4. 相等==和不相等!=
  5. 整型常数INT_MININT_MAX
  6. intunsigned进行隐式或显式强制类型转换。

个别题目有特殊的限制。

2.61**

:写一个C表达式,在下列描述的条件下产生1,在其他情况下得到0,假设xint类型。

  1. x的任何位都等于1
!~x
  1. x的任何位都等于0
!x;
  1. x的最低有效字节中的位都等于1
!~(x | ~0xFF)
  1. x的最高有效字节中的位都等于0
!((0xFF << ((sizeof(int) - 1) << 3)) & x);

2.62***

:编写一个函数int_shifts_are_arithmetic(),在对int类型的数使用算术右移的机器上运行时这个函数返回1,其他情况下返回0

int int_shifts_are_arithmetic()
{int x = -1;return (x >> 8) == x;  // return !(x ^ (x >> 8));
}

x86_64上的运行结果:

// printf("%d\n", int_shifts_are_arithmetic());
[liheng@localhost2 2]$ ./a.out 
1

2.63***

:将下面的C函数代码补充完整。函数srl用算术右移(由值xsra给出)完成逻辑右移,后面的操作不包括右移或者除法。函数sra用逻辑右移(由值xsrl给出)来完成算术右移,后面的操作不包括右移或者除法。w = sizeof(int) * 8k的取值范围是0 ~ w-1

unsigned srl(unsigned x, in k)
{unsigned xsra = (int)x >> k;  // 算术右移的值int mask = ((1 << k) - 1) << ((sizeof(int) << 3) - k);return xsra & ~mask;
}int sra(int x, int k)
{int xsrl = (unsigned)x >> k;  // 逻辑右移的值int sign = !!(x & (1 << ((sizeof(int) << 3) - 1)));int mask = ((sign << k) - sign) << ((sizeof(int) << 3) - k);return xsrl | mask;
}

x86_64上的运行结果:

// printf("%p\n", srl(-1, 0));
// printf("%p\n", srl(-1, 16));
// printf("%p\n", srl(-1, 31));
// printf("%p\n", sra(-1, 0));
// printf("%p\n", sra(-1, 16));
// printf("%p\n", sra(-1, 31));
// printf("%p\n", sra(0x0F000000, 16));
[liheng@localhost2 2]$ ./a.out 
0xffffffff
0xffff
0x1
0xffffffff
0xffffffff
0xffffffff
0xf00

2.64*

:实现一个函数,入参是一个整型xw = 32),如果有一个奇数位是1,就返回1,否则返回0

首先需要构造32位的掩码10[10]...,使用该掩码去掉x中的偶数位,再判断奇数位是否存在一个1
32位的掩码10[10]...的十六进制表示为0x55555555

int any_odd_one(unsigned x)
{int mask = 0x55555555;return x & mask;
}

x86_64机器上的运行结果:

// printf("%d\n", any_odd_one(0x1));
// printf("%d\n", any_odd_one(0x2));
[liheng@localhost2 2]$ ./a.out 
1
0

2.65****

:实现一个函数,入参是一个整型xw = 32),当x有奇数个值为1的位时,返回1,否则返回0

int odd_ones(unsigned x)
{x ^= x >> 16;x ^= x >> 8;x ^= x >> 4;x ^= x >> 2;x ^= x >> 1;return x & 0x1;
}

第一个^=运算把x0~15位和16~31位的^运算结果放在了x0~15位;第二个^=运算把x(上一步的运算结果)的0~7位和8~15位的^运算结果放在了x0~7位,以此类推。最终x的第0位上放的就是初值的x的所有位的^结果。

1 ^ 1 = 00 ^ 0 = 01 ^ 0 = 1,异或会抵消掉相同的位,把值归0,且异或具有结合律。因此只要把x中的所有位按任意顺序异或一遍,最终结果为1的话就说明它包含奇数个值为1的位。

x86_64机器上的运行结果:

// printf("%d\n", odd_ones(0x0));  // 0个值为1的位
// printf("%d\n", odd_ones(0x1));  // 1个值为1的位
// printf("%d\n", odd_ones(0x3));  // 2个值为1的位
// printf("%d\n", odd_ones(-1));  // 32个值为1的位
// printf("%d\n", odd_ones(369));  // 5个值为1的位
// printf("%d\n", odd_ones(11825));  // 7个值为1的位
[liheng@localhost2 2]$ ./a.out 
0
1
0
0
1
1

2.66***

:实现一个函数,入参是一个整型xw = 32),返回一个掩码指示最高位的1的位置。如输入0xFF00返回0x8000,输入0x6600返回0x4000,输入0返回0

int leftmost_one(unsigned x)
{x |= x >> 1;x |= x >> 2;x |= x >> 4;x |= x >> 8;x |= x >> 16;return (x >> 1) + !!x;
}

x的值为1的最高位算起往它的低位开始数,第一次|=运算的结果把2个位设置为1,第二次|=运算的结果把4个位设置为1,以此类推,把全32位都设置为1。最后把结果右移1位再加1,就得到了指示最高位的1的位置的数。

x86_64机器上的运行结果:

// printf("%d\n", leftmost_one(0x0));
// printf("%p\n", leftmost_one(0xF));
// printf("%p\n", leftmost_one(0x6600));
// printf("%p\n", leftmost_one(0x8000));
// printf("%p\n", leftmost_one(0x46531));
// printf("%p\n", leftmost_one(-1));
[liheng@localhost2 2]$ ./a.out 
0
0x8
0x4000
0x8000
0x40000
0x80000000

2.67**

:实现一个函数,当在一个int32位的机器上运行时,该程序产生1,其他情况产生0。不允许使用sizeof
下面是开始的尝试:

int bad_int_size_is_32()
{int set_msb = 1 << 31;int beyond_msb = 1 << 32;// set_msb非零时,int_size >= 32;beyond_msb为零时,int_size <= 32return set_msb && !beyond_msb;  
}

当我们在SUN SPARC这样的32位机器上编译运行时,这个过程返回的却是0。编译器打印了一句warning

warning: left shift count >= width of type

  1. 我们的代码在哪个方面没有遵守C语言标准?
    C标准没有明确规定当移位操作的位数大于等于变量的宽度时的行为。有的机器上1 << 32是零,有的机器上1 << 32是非零(移位的位数%(取模)变量的宽度)。上述代码预期在这种情况下,1 << 32是零。
    为了保证程序的可移植性,需要程序员保证移位数的取值范围是[0, w)
  2. 修改代码,使得它在int至少为32位的机器上都能正确地运行。
int int_size_is_32()
{int set_msb = 1 << 31;int beyond_msb = set_msb << 1;  // 确保在不同的机器上,程序的行为是一致的。// set_msb非零时,int_size >= 32;beyond_msb为零时,int_size <= 32return set_msb && !beyond_msb;  
}
  1. 修改代码,使得它在int至少为16位的机器上都能正确地运行。
int int_size_is_32()
{int set_msb = 1 << 15 << 15 << 1;  // 保证左移行为符合预期int beyond_msb = set_msb << 1;// set_msb非零时,int_size >= 32;beyond_msb为零时,int_size <= 32return set_msb && !beyond_msb;  
}

2.68**

:实现一个函数,输入正整数n(1≤n≤w)(1 \le n \le w)(1nw),返回低n位均为1的掩码值。如输入6返回0x3F,输入17返回0x1FFFF

int lower_one_mask(int n)
{return (unsigned)-1 >> ((sizeof(int) << 3) - n);
}

x86_64机器上的运行结果:

// printf("%d\n", lower_one_mask(0));
// printf("%p\n", lower_one_mask(6));
// printf("%p\n", lower_one_mask(17));
// printf("%p\n", lower_one_mask(31));
// printf("%p\n", lower_one_mask(32));
[liheng@localhost2 2]$ ./a.out 
0
0x3f
0x1ffff
0x7fffffff
0xffffffff

2.69***

:实现循环左移,0≤n<w0 \le n <w0n<w。如x = 0x12345678w = 32n = 4返回0x23456781n = 20返回0x67812345

unsigned rotate_left(unsigned x, int n)
{unsigned low = x >> ((sizeof(unsigned) << 3) - n);unsigned high = x << n;return high | low;
}

x86_64机器上的运行结果:

// printf("%p\n", rotate_left(0x12345678, 0));
// printf("%p\n", rotate_left(0x12345678, 4));
// printf("%p\n", rotate_left(0x12345678, 8));
// printf("%p\n", rotate_left(0x12345678, 12));
// printf("%p\n", rotate_left(0x12345678, 16));
// printf("%p\n", rotate_left(0x12345678, 20));
// printf("%p\n", rotate_left(0x12345678, 24));
// printf("%p\n", rotate_left(0x12345678, 28));
// printf("%p\n", rotate_left(0x12345678, 31));
[liheng@localhost2 2]$ ./a.out 
0x12345678
0x23456781
0x34567812
0x45678123
0x56781234
0x67812345
0x78123456
0x81234567
0x91a2b3c

2.70**

:实现一个函数,如果x能被表示成n(1≤n≤w)(1 \le n \le w)(1nw)的二进制补码,就返回1,否则返回0

int fits_bits(int x, int n)
{int w = sizeof(int) << 3;int offset = w - n;return ((x << offset) >> offset) == x;  // 如果x不能用n个比特位表示,移位操作会使它丢失最高的有效位
}

x86_64机器上的运行结果:

// printf("%d\n", fits_bits(-4, 3));
// printf("%d\n", fits_bits(3, 3));
// printf("%d\n", fits_bits(-5, 3));
// printf("%d\n", fits_bits(4, 3));
[liheng@localhost2 2]$ ./a.out 
1
1
0
0

2.71*

packed_t类型是将4个有符号字节封装成一个32位的unsigned,字节从0(最低有效字节)编码到3最高有效字节。有如下一个函数xbyte,提取出特定的字节,再把它符号扩展成一个int

typedef unsigned packed_t;
int xbyte(packed_t word, int byteNum)
{return (word >> (byteNum << 3)) & 0xFF;
}

  1. 写上述代码的人被解雇了,这段代码错在哪里?
    编译器会把(word >> (byteNum << 3)) & 0xFF的结果当作无符号数,扩展时使用零扩展而非符号扩展
// printf("%d\n", xbyte(-1, 3));
[liheng@localhost2 2]$ ./a.out 
255
  1. 给出函数的正确实现。
typedef unsigned packed_t;
int xbyte(packed_t word, int byteNum)
{return (int8_t)((word >> (byteNum << 3)) & 0xFF);  // 把结果转成有符号数
}

x86_64机器上的运行结果:

// printf("%d\n", xbyte(-1, 3));
[liheng@localhost2 2]$ ./a.out 
-1

2.72**

:下面的函数将整数val复制到缓冲区buf中。

void copy_int(int val, void *buf, int maxbytes)
{if (maxbytes - sizeof(val) >= 0) {memcpy(buf, &val, sizeof(val));}
}

  1. sizeof的返回值类型是size_t,这段代码存在什么问题?
    size_t是无符号类型unsigned的别名,maxbytes是有符号数,无符号数和有符号数运算时,结果是无符号数(永远≥0\ge00),因此if分支的判断语句永远为truememcpy会造成缓冲区的写溢出。
  2. 改正代码。
void copy_int(int val, void *buf, int maxbytes)
{if (maxbytes >= sizeof(val) {  // 无符号数之间的比较memcpy(buf, &val, sizeof(val));}
}

2.73**

:实现饱和加法:正溢出时返回TMax,负溢出时返回TMin

int saturating_add(int x, int y)
{int s = x + y;int mask = 1 << ((sizeof(int) << 3) - 1);int neg_overflow = (x & mask) && (y & mask) && !(s & mask);int pos_overflow = !(x & mask) && !(y & mask) && (s & mask);(neg_overflow && (s = INT_MIN)) || (pos_overflow && (s = INT_MAX));return s;
}

x86_64机器上的运行结果:

// printf("%d\n", saturating_add(123, 456));
// printf("%d\n", saturating_add(-123, -456));
// printf("%d\n", saturating_add(INT_MAX, 123));
// printf("%d\n", saturating_add(INT_MIN, -123));
[liheng@localhost2 2]$ ./a.out 
579
-579
2147483647
-2147483648

2.74**

:实现一个函数,两数相减不溢出就返回1,否则返回0

int tsub_ok(int x, int y)
{int s = x - y;return !((x > 0 && y < 0 && s < 0) || (x < 0 && y > 0 && s > 0));
}

x86_64机器上的运行结果:

// printf("%d\n", tsub_ok(-1, 3));
// printf("%d\n", tsub_ok(INT_MIN, 1));
// printf("%d\n", tsub_ok(INT_MAX, -1));
[liheng@localhost2 2]$ ./a.out 
1
0
0

正常情况:正数+正数=正数;溢出情况:正数+正数=负数。
正常情况:负数+负数=负数;溢出情况:负数+负数=正数。
正常情况:正数-负数=正数;溢出情况:正数-负数=负数。
正常情况:负数-正数=负数;溢出情况:负数-正数=正数。

2.75***

:假设我们要计算x * y的完整的2w位表示,其中xy都是无符号数,并且w=32,乘积的低w位能够用表达式x * y计算。所以我们只需要额外计算它的高w位,声明如下:

unsigned unsigned_high_prod(unsigned x, unsigned y);

我们使用一个库函数,它计算在xy采用补码形式的情况下,x * y的高w位。声明如下:

int signed_high_prod(int x, int y);

编写代码调用signed_high_prod,实现unsigned_high_prod


假设xy是无符号数,x′x'xy′y'y分别是它们的补码数。有x=x′+xw−12wx=x'+x_{w-1}2^wx=x+xw12wy=y′+yw−12wy=y'+y_{w-1}2^wy=y+yw12w,因此
x∗y=(x′+xw−12w)∗(y′+yw−12w)=x′∗y′+(x′yw−1+y′xw−1)2w+xw−1yw−122wx*y=(x'+x_{w-1}2^w)*(y'+y_{w-1}2^w)=x'*y'+(x'y_{w-1}+y'x_{w-1})2^w+x_{w-1}y_{w-1}2^{2w}xy=(x+xw12w)(y+yw12w)=xy+(xyw1+yxw1)2w+xw1yw122w
取低2w位,结果是x′∗y′+(x′yw−1+y′xw−1)2wx'*y'+(x'y_{w-1}+y'x_{w-1})2^wxy+(xyw1+yxw1)2w,获取其中的高w位的实现如下:

unsigned unsigned_high_prod(unsigned x, unsigned y)
{int a = signed_high_prod(x, y);return a + x * (y >> 31) + y * (x >> 31);
}

2.76*


库函数calloc声明如下:

void *calloc(size_t nmemb, size_t size);

函数calloc为一个数组分配内存,并将内存设置为0。该数组有nmemb个元素,每个元素的大小为size字节。如果nmembsize0calloc返回NULL
编写calloc的实现,通过malloc分配内存,再通过memset将内存设置为0。你的代码应该没有任何由算术溢出引起的漏洞,且无论size_t用多少位表示,代码都应该正常工作。mallocmemset的声明如下:

void *malloc(size_t size);
void *memset(void *s, inc c, size_t n);


calloc的实现如下:

void *calloc(size_t nmemb, size_t size)
{size_t bytes = nmemb * size;if ((bytes == 0) || (bytes / nmemb != size)) {  // 分配0字节或溢出return NULL;}void *addr = malloc(bytes);if (addr == NULL) {return NULL;}return memset(addr, 0x00, bytes);
}

相关文章:

【CSAPP】家庭作业2.55~2.76

文章目录2.55*2.56*2.57*2.58**2.59**2.60**位级整数编码规则2.61**2.62***2.63***2.64*2.65****2.66***2.67**2.68**2.69***2.70**2.71*2.72**2.73**2.74**2.75***2.76*2.55* 问&#xff1a;在你能访问的不同的机器上&#xff0c;编译show_bytes.c并运行代码&#xff0c;确定…...

Python操作MySQL数据库详细案例

Python操作MySQL数据库详细案例一、前言二、数据准备三、建立数据库四、处理和上传数据五、下载数据六、完整项目数据和代码一、前言 本文通过案例讲解如何使用Python操作MySQL数据库。具体任务为&#xff1a;假设你已经了解MySQL和知识图谱标注工具Brat&#xff0c;将Brat标注…...

MicroBlaze系列教程(8):AXI_CAN的使用

文章目录 @[toc]CAN总线概述AXI_CAN简介MicroBlaze硬件配置常用函数使用示例波形实测参考资料工程下载本文是Xilinx MicroBlaze系列教程的第8篇文章。 CAN总线概述 **CAN(Controller Area Network)**是 ISO 国际标准化的串行通信协议,是由德国博世(BOSCH)公司在20世纪80年代…...

网络安全领域中八大类CISP证书

CISP​注册信息安全专业人员 注册信息安全专业人员&#xff08;Certified Information Security Professional&#xff09;&#xff0c;是经中国信息安全产品测评认证中心实施的国家认证&#xff0c;对信息安全人员执业资质的认可。该证书是面向信息安全企业、信息安全咨询服务…...

stm32学习笔记-5EXIT外部中断

5 EXIT外部中断 [toc] 注&#xff1a;笔记主要参考B站 江科大自化协 教学视频“STM32入门教程-2023持续更新中”。 注&#xff1a;工程及代码文件放在了本人的Github仓库。 5.1 STM32中断系统 图5-1 中断及中断嵌套示意图 中断 是指在主程序运行过程中&#xff0c;出现了特定…...

MySQL Workbench 图形化界面工具

Workbench 介绍 MySQL官方提供了一款免费的图形工具——MySQL Workbench&#xff0c;它是一款功能强大且易于使用的数据库设计、管理和开发工具&#xff0c;总之&#xff0c;MySQL Workbench是一款非常好用的MySQL图形工具&#xff0c;可以满足大多数MySQL用户的需求。 目录 W…...

雪花算法(SnowFlake)

简介现在的服务基本是分布式、微服务形式的&#xff0c;而且大数据量也导致分库分表的产生&#xff0c;对于水平分表就需要保证表中 id 的全局唯一性。对于 MySQL 而言&#xff0c;一个表中的主键 id 一般使用自增的方式&#xff0c;但是如果进行水平分表之后&#xff0c;多个表…...

Linux防火墙

一、Linux防火墙Linux的防火墙体系主要在网络层&#xff0c;针对TCP/IP数据包实施过滤和限制&#xff0c;属于典型的包过滤防火墙&#xff08;或称为网络层防火墙&#xff09;。Linux系统的防火墙体系基于内核编码实现&#xff0c;具有非常稳定的性能和极高的效率&#xff0c;因…...

网络安全系列-四十七: IP协议号大全

IP协议号列表 这是用在IPv4头部和IPv6头部的下一首部域的IP协议号列表。 十进制十六进制关键字协议引用00x00HOPOPTIPv6逐跳选项RFC 246010x01ICMP互联网控制消息协议(ICMP)RFC 79220x02IGMP...

HTTP协议格式以及Fiddler用法

目录 今日良言:焦虑和恐惧改变不了明天,唯一能做的就是把握今天 一、HTTP协议的基本格式 二、Fiddler的用法 1.Fidder的下载 2.Fidder的使用 今日良言:焦虑和恐惧改变不了明天,唯一能做的就是把握今天 一、HTTP协议的基本格式 先来介绍一下http协议: http 协议(全称为 &q…...

自动写代码?别闹了!

大家好&#xff0c;我是良许。 这几天&#xff0c;GitHub 上有个很火的插件在抖音刷屏了——Copilot。 这个神器有啥用呢&#xff1f;简单来讲&#xff0c;它就是一款由人工智能打造的编程辅助工具。 我们来看看它有啥用。 首先就是代码补全功能&#xff0c;你只要给出函数…...

项目心得--网约车

一、RESTFULPost&#xff1a;新增Put&#xff1a;全量修改Patch&#xff1a;修改某个值Delete: 删除Get&#xff1a;查询删除接口也可以用POST请求url注意&#xff1a;url中不要带有敏感词&#xff08;用户id等&#xff09;url中的名词用复数形式url设计&#xff1a;api.xxx.co…...

【二叉树广度优先遍历和深度优先遍历】

文章目录一、二叉树的深度优先遍历0.建立一棵树1. 前序遍历2.中序遍历3. 后序遍历二、二叉树的广度优先遍历层序遍历三、有关二叉树练习一、二叉树的深度优先遍历 学习二叉树结构&#xff0c;最简单的方式就是遍历。 所谓二叉树遍历(Traversal)是按照某种特定的规则&#xff…...

Spring Cloud微服务架构必备技术

单体架构 单体架构&#xff0c;也叫单体应用架构&#xff0c;是一个传统的软件架构模式。单体架构是指将应用程序的所有组件部署到一个单一的应用程序中&#xff0c;并统一进行部署、维护和扩展。在单体架构中&#xff0c;应用程序的所有功能都在同一个进程中运行&#xff0c;…...

TCP三次握手与四次挥手(一次明白)

TCP基本信息 默认端口号:80 LINUX中TIME_WAIT的默认时间是30s TCP三次握手 三次握手过程:每行代表发起握手到另一方刚刚收到数据包时的状态 客户端服务端客户端状态服务端状态握手前CLOSELISTEN客户端发送带有SYN标志的数据包到服务端一次握手SYN_SENDLISTEN二次握手服务端发送…...

pyside6@Mouse events实例@QApplication重叠导致的报错@keyboardInterrupt

文章目录报错内容鼠标事件演示报错内容 在pyside图形界面应用程序开发过程中,通常只允许运行一个实例 假设您重复执行程序A,那么可能会导致一些意向不到的错误并且,从python反馈的信息不容易判断错误的真正来源 鼠标事件演示 下面是一段演示pyside6的鼠标事件mouseEvent对象…...

订单30分钟未支付自动取消怎么实现?

目录了解需求方案 1&#xff1a;数据库轮询方案 2&#xff1a;JDK 的延迟队列方案 3&#xff1a;时间轮算法方案 4&#xff1a;redis 缓存方案 5&#xff1a;使用消息队列了解需求在开发中&#xff0c;往往会遇到一些关于延时任务的需求。例如生成订单 30 分钟未支付&#xff0…...

< 开源项目框架:推荐几个开箱即用的开源管理系统 - 让开发不再复杂 >

文章目录&#x1f449; SCUI Admin 中后台前端解决方案&#x1f449; Vue .NetCore 前后端分离的快速发开框架&#x1f449; next-admin 适配移动端、pc的后台模板&#x1f449; django-vue-admin-pro 快速开发平台&#x1f449; Admin.NET 通用管理平台&#x1f449; RuoYi 若…...

内网渗透-基础环境

解决依赖&#xff0c;scope安装 打开要给cmd powershell 打开远程 Set-ExecutionPolicy RemoteSigned -scope CurrentUser; 我试了好多装这东西还是得科学上网&#xff0c;不然不好用 iwr -useb get.scoop.sh | iex 查看下载过的软件 安装sudo 安装git 这里一定要配置bu…...

Go语言学习的第一天(对于Go学习的认识和工具选择及环境搭建)

首先学习一门新的语言&#xff0c;我们要知道这门语言可以帮助我们做些什么&#xff1f;为什么我们要学习这门语言&#xff1f;就小wei而言学习这门语言是为了区块链&#xff0c;因为自身是php出身&#xff0c;因为php的一些特性只能通过一些算法模拟的做一个虚拟链&#xff0c…...

JavaScript 中的 ES|QL:利用 Apache Arrow 工具

作者&#xff1a;来自 Elastic Jeffrey Rengifo 学习如何将 ES|QL 与 JavaScript 的 Apache Arrow 客户端工具一起使用。 想获得 Elastic 认证吗&#xff1f;了解下一期 Elasticsearch Engineer 培训的时间吧&#xff01; Elasticsearch 拥有众多新功能&#xff0c;助你为自己…...

【android bluetooth 框架分析 04】【bt-framework 层详解 1】【BluetoothProperties介绍】

1. BluetoothProperties介绍 libsysprop/srcs/android/sysprop/BluetoothProperties.sysprop BluetoothProperties.sysprop 是 Android AOSP 中的一种 系统属性定义文件&#xff08;System Property Definition File&#xff09;&#xff0c;用于声明和管理 Bluetooth 模块相…...

聊一聊接口测试的意义有哪些?

目录 一、隔离性 & 早期测试 二、保障系统集成质量 三、验证业务逻辑的核心层 四、提升测试效率与覆盖度 五、系统稳定性的守护者 六、驱动团队协作与契约管理 七、性能与扩展性的前置评估 八、持续交付的核心支撑 接口测试的意义可以从四个维度展开&#xff0c;首…...

Java面试专项一-准备篇

一、企业简历筛选规则 一般企业的简历筛选流程&#xff1a;首先由HR先筛选一部分简历后&#xff0c;在将简历给到对应的项目负责人后再进行下一步的操作。 HR如何筛选简历 例如&#xff1a;Boss直聘&#xff08;招聘方平台&#xff09; 直接按照条件进行筛选 例如&#xff1a…...

LINUX 69 FTP 客服管理系统 man 5 /etc/vsftpd/vsftpd.conf

FTP 客服管理系统 实现kefu123登录&#xff0c;不允许匿名访问&#xff0c;kefu只能访问/data/kefu目录&#xff0c;不能查看其他目录 创建账号密码 useradd kefu echo 123|passwd -stdin kefu [rootcode caozx26420]# echo 123|passwd --stdin kefu 更改用户 kefu 的密码…...

适应性Java用于现代 API:REST、GraphQL 和事件驱动

在快速发展的软件开发领域&#xff0c;REST、GraphQL 和事件驱动架构等新的 API 标准对于构建可扩展、高效的系统至关重要。Java 在现代 API 方面以其在企业应用中的稳定性而闻名&#xff0c;不断适应这些现代范式的需求。随着不断发展的生态系统&#xff0c;Java 在现代 API 方…...

windows系统MySQL安装文档

概览&#xff1a;本文讨论了MySQL的安装、使用过程中涉及的解压、配置、初始化、注册服务、启动、修改密码、登录、退出以及卸载等相关内容&#xff0c;为学习者提供全面的操作指导。关键要点包括&#xff1a; 解压 &#xff1a;下载完成后解压压缩包&#xff0c;得到MySQL 8.…...

全面解析数据库:从基础概念到前沿应用​

在数字化时代&#xff0c;数据已成为企业和社会发展的核心资产&#xff0c;而数据库作为存储、管理和处理数据的关键工具&#xff0c;在各个领域发挥着举足轻重的作用。从电商平台的商品信息管理&#xff0c;到社交网络的用户数据存储&#xff0c;再到金融行业的交易记录处理&a…...

深入解析光敏传感技术:嵌入式仿真平台如何重塑电子工程教学

一、光敏传感技术的物理本质与系统级实现挑战 光敏电阻作为经典的光电传感器件&#xff0c;其工作原理根植于半导体材料的光电导效应。当入射光子能量超过材料带隙宽度时&#xff0c;价带电子受激发跃迁至导带&#xff0c;形成电子-空穴对&#xff0c;导致材料电导率显著提升。…...

MLP实战二:MLP 实现图像数字多分类

任务 实战&#xff08;二&#xff09;&#xff1a;MLP 实现图像多分类 基于 mnist 数据集&#xff0c;建立 mlp 模型&#xff0c;实现 0-9 数字的十分类 task: 1、实现 mnist 数据载入&#xff0c;可视化图形数字&#xff1b; 2、完成数据预处理&#xff1a;图像数据维度转换与…...