2021年12月

PKprimary key 主键
NNnot null 非空
UQunique 唯一索引
BINbinary 二进制数据(比text更大的二进制数据)
UNunsigned 无符号 整数(非负数)
ZFzero fill 填充0 例如字段内容是1 int(4), 则内容显示为0001
AIauto increment 自增
Ggenerated column 生成列

在mysql查询语句中加\g、\G的意思:

\g 的作用是分号和在sql语句中写“;”是等效的
\G 的作用是将查到的结构旋转90度变成纵向(换行打印)

1位=1比特;

1字节=8位;

1字=2字节;

1字=16位。

1、位

位是计算机存储的最小单位,简记为b,也称为比特(bit)计算机中用二进制中的0和1来表示数据,一个0或1就代表一位。位数通常指计算机中一次能处理的数据大小;

2、比特

比特(bit)是由英文BIT音译而来,比特同时也是二进制数字中的位,是信息量的度量单位,为信息量的最小单位;

3、字节

字节,英文Byte,是计算机用于计量存储容量的一种计量单位,通常情况下一字节等于八位,字节同时也在一些计算机编程语言中表示数据类型和语言字符,在现代计算机中,一个字节等于八位;

4、字

字是表示计算机自然数据单位的术语,在某个特定计算机中,字是其用来一次性处理事务的一个固定长度的位(bit)组,在现代计算机中,一个字等于两个字节。

一、先给定义:

什么是大端?什么是小端?
主要针对的是CPU向内存写入数据的两种方式:

大端序:将高位字节保存在内存的低地址(高位字节在前)的方式。
小端序:将高位字节保存在内在存的高地址(低位字节在前)的方式。

二、下面引入详细说明:

假设在 0x20 号开始的地址中保存4字节 int 型数据 0x12345678,大端序CPU保存方式如下图所示:
1.png
上图1:整数 0x12345678 的大端序字节表示。
比如说1在高位就是高位字节,相反8就在低位是低位字节

对于大端序,最高位字节 0x12 存放到低位地址,最低位字节 0x78 存放到高位地址。小端序的保存方式如下图所示:
2.png
上图2:整数 0x12345678 的小端序字节表示。
比如说1在高位就是高位字节,相反8就在低位是低位字节

不同CPU保存和解析数据的方式不同(主流的Intel系列CPU为小端序),小端序系统和大端序系统通信时会发生数据解析错误。因此在发送数据前,要将数据转换为统一的格式——网络字节序(Network Byte Order)。网络字节序统一为大端序。主机A先把数据转换成大端序再进行网络传输,主机B收到数据后先转换为自己的格式再解析。网络字节序转换函数
sockaddr_in 结构体,其中就用到了网络字节序转换函数,如下所示:

//创建sockaddr_in结构体变量
struct sockaddr_in serv_addr;
memset(&serv_addr, 0, sizeof(serv_addr)); //每个字节都用0填充
serv_addr.sin_family = AF_INET; //使用IPv4地址
serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); //具体的IP地址
serv_addr.sin_port = htons(1234); //端口号

htons() 用来将当前主机字节序转换为网络字节序,其中
h代表主机(host)字节序,
n代表网络(network)字节序,
s代表shorthtonsh、to、n、s 的组合,可以理解为”将short型数据从当前主机字节序转换为网络字节序“。常见的网络字节转换函数有:htons()host to network short,将short类型数据从主机字节序转换为网络字节序。
ntohs():network to host short,将short类型数据从网络字节序转换为主机字节序。
htonl():host to network long,将long类型数据从主机字节序转换为网络字节序。
ntohl():network to host long,将long类型数据从网络字节序转换为主机字节序。

通常,以s为后缀的函数中,s代表2个字节short,因此用于端口号转换;以l为后缀的函数中,l代表4个字节的long,因此用于IP地址转换。举例说明上述函数的调用过程:

#include <stdio.h>
#include <stdlib.h>
#include <WinSock2.h>
#pragma comment(lib, "ws2_32.lib")
int main(){
unsigned short host_port = 0x1234, net_port;
unsigned long host_addr = 0x12345678, net_addr;

net_port = htons(host_port);
net_addr = htonl(host_addr);

printf("Host ordered port: %#x\n", host_port);
printf("Network ordered port: %#x\n", net_port);
printf("Host ordered address: %#lx\n", host_addr);
printf("Network ordered address: %#lx\n", net_addr);
system("pause");
return 0;
}

运行结果:

Host ordered port: 0x1234
Network ordered port: 0x3412
Host ordered address: 0x12345678
Network ordered address: 0x78563412

另外需要说明的是,sockaddr_in 中保存IP地址的成员为32位整数,而我们熟悉的是点分十进制表示法,例如 127.0.0.1,它是一个字符串,因此为了分配IP地址,需要将字符串转换为4字节整数。inet_addr() 函数可以完成这种转换。inet_addr() 除了将字符串转换为32位整数,同时还进行网络字节序转换。请看下面的代码:

#include <stdio.h>
#include <stdlib.h>
#include <WinSock2.h>
#pragma comment(lib, "ws2_32.lib")

int main(){
char *addr1 = "1.2.3.4";
char *addr2 = "1.2.3.256";

unsigned long conv_addr = inet_addr(addr1);
if(conv_addr == INADDR_NONE){
puts("Error occured!");
}else{
printf("Network ordered integer addr: %#lx\n", conv_addr);
}

conv_addr = inet_addr(addr2);
if(conv_addr == INADDR_NONE){
puts("Error occured!");
}else{
printf("Network ordered integer addr: %#lx\n", conv_addr);
}

system("pause");
return 0;
}

运行结果:
Network ordered integer addr: 0x4030201

Error occured!从运行结果可以看出,inet_addr() 不仅可以把IP地址转换为32位整数,还可以检测无效IP地址。注意:为 sockaddr_in 成员赋值时需要显式地将主机字节序转换为网络字节序,而通过 write()/send() 发送数据时TCP协议会自动转换为网络字节序,不需要再调用相应的函数。

本文摘自:https://www.jianshu.com/p/68735394db7a

不能将箭头函数用于定义对象的方法且内含有this

const cat = {
  lives: 9,
  jumps: () => {
    this.lives--;
  }
}

调用cat.jumps()时,如果是普通函数,该方法内部的this指向cat;如果写成上面那样的箭头函数,使得this指向全局对象,因此不会得到预期结果。这是因为对象不构成单独的作用域,导致jumps箭头函数定义时的作用域就是全局作用域。

关键问题是:对象不构成单独的作用域。

// 正确的写法
let x;
({x} = {x: 1});


// 错误的写法
let x;
{x} = {x: 1};
// SyntaxError: syntax error

  1. 当线程创建的时候,操作系统(OS)为每一个系统级(system-level)的线程分配栈。通常情况下,操作系统通过调用语言的运行时(runtime)去为应用程序分配堆。
  2. 栈附属于线程,因此当线程结束时栈被回收。堆通常通过运行时在应用程序启动时被分配,当应用程序(进程)退出时被回收。
  3. 当线程被创建的时候,设置栈的大小。在应用程序启动的时候,设置堆的大小,但是可以在需要的时候扩展(分配器向操作系统申请更多的内存)。
  4. 栈比堆要快,因为它存取模式使它可以轻松的分配和重新分配内存(指针/整型只是进行简单的递增或者递减运算),然而堆在分配和释放的时候有更多的复杂的 bookkeeping 参与。另外,在栈上的每个字节频繁的被复用也就意味着它可能映射到处理器缓存中,所以很快。

栈【Stack】:

a.和堆一样存储在计算机 RAM 中。
b.在栈上创建变量的时候会扩展,并且会自动回收。
c.相比堆而言在栈上分配要快的多。
d.用数据结构中的栈实现。
e.存储局部数据,返回地址,用做参数传递。
f.当用栈过多时可导致栈溢出(无穷次(大量的)的递归调用,或者大量的内存分配)。
g.在栈上的数据可以直接访问(不是非要使用指针访问)。
h.如果你在编译之前精确的知道你需要分配数据的大小并且不是太大的时候,可以使用栈。
i.当你程序启动时决定栈的容量上限。

堆【Heap】:

a.和栈一样存储在计算机RAM。
b.在堆上的变量必须要手动释放,不存在作用域的问题。数据可用 delete, delete[] 或者 free 来释放。
c.相比在栈上分配内存要慢。
d.通过程序按需分配。
e.大量的分配和释放可造成内存碎片。
f.在 C++ 中,在堆上创建数的据使用指针访问,用 new 或者 malloc 分配内存。
g.如果申请的缓冲区过大的话,可能申请失败。
h.在运行期间你不知道会需要多大的数据或者你需要分配大量的内存的时候,建议你使用堆。
i.可能造成内存泄露。


stream_bucket_append函数:为队列添加数据 
stream_bucket_make_writeable函数:从操作的队列中返回一个数据对象
stream_bucket_new函数:为当前队列创建一个新的数据
stream_bucket_prepend函数:预备数据到队列 
stream_context_create函数:创建数据流上下文
stream_context_get_default函数:获取默认的数据流上下文
stream_context_get_options函数:获取数据流的设置
stream_context_set_option函数:对数据流、数据包或者上下文进行设置
stream_context_set_params函数:为数据流、数据包或者上下文设置参数
stream_copy_to_stream函数:在数据流之间进行复制操作
stream_filter_append函数:为数据流添加过滤器
stream_filter_prepend函数:为数据流预备添加过滤器
stream_filter_register函数:注册一个数据流的过滤器并作为PHP类执行
stream_filter_remove函数:从一个数据流中移除过滤器
stream_get_contents函数:读取数据流中的剩余数据到字符串
stream_get_filters函数:返回已经注册的数据流过滤器列表
stream_get_line函数:按照给定的定界符从数据流资源中获取行
stream_get_meta_data函数:从封装协议文件指针中获取报头/元数据
stream_get_transports函数:返回注册的Socket传输列表
stream_get_wrappers函数:返回注册的数据流列表
stream_register_wrapper函数:注册一个用PHP类实现的URL封装协议
stream_select函数:接收数据流数组并等待它们状态的改变
stream_set_blocking函数:将一个数据流设置为堵塞或者非堵塞状态
stream_set_timeout函数:对数据流进行超时设置
stream_set_write_buffer函数:为数据流设置缓冲区
stream_socket_accept函数:接受由函数stream_ socket_server()创建的Socket连接
stream_socket_client函数:打开网络或者UNIX主机的Socket连接
stream_socket_enable_crypto函数:为一个已经连接的Socket打开或者关闭数据加密
stream_socket_get_name函数:获取本地或者网络Socket的名称
stream_socket_pair函数:创建两个无区别的Socket数据流连接
stream_socket_recvfrom函数:从Socket获取数据,不管其连接与否
stream_socket_sendto函数:向Socket发送数据,不管其连接与否
stream_socket_server函数:创建一个网络或者UNIX Socket服务端
stream_wrapper_restore函数:恢复一个事先注销的数据包
stream_wrapper_unregister函数:注销一个URL地址包


定义形式如下:

struct books {
    int count;
    double average;
    double scores[];    //伸缩型数组成员
};

它必须满足以下几点:

1、伸缩型数组必须是结构的最后一个成员;
2、结构中必须至少有一个成员;
3、伸缩型数组类似普通数组,只是它的方括号内必须为空;

它存在的意义:

定义struct books 类型的变量,并不是为了让此数组中存值(初始值)而是希望声明
一个该变量的指针;然后在函数中使用时,动态的分配数组长度以后再赋值。

pf = malloc(sizeof(struct books) + n * sizeof(double)); //这里的n即为伸缩数组的长度

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define SLEN 81

struct namect {
    char * fname; //定义字符指针
    char * lname;
    int letters;
};

void getinfo(struct namect *); //传指针分配内存
void makeinfo(struct namect *);
void showinfo(const struct namect *); //只显示结构内容不能修改结构变量
void cleanup(struct namect *);
char * s_gets(char * st, int n);

int main(void)
{
    struct namect person;
    getinfo(&person);
    makeinfo(&person);
    showinfo(&person);
    cleanup(&person);

    return 0;
}

void getinfo(struct namect * pst)
{
    char temp[SLEN];
    printf("输入英文的姓\n");
    s_gets(temp, SLEN);
    //分配内存
    pst->fname = (char *) malloc(strlen(temp) + 1);
    //把名子拷贝到分配的内在中
    strcpy(pst->fname, temp);
    printf("输入英文的名\n");
    s_gets(temp, SLEN);
    pst->lname = (char *) malloc(strlen(temp) + 1);
    strcpy(pst->lname, temp);
}

void makeinfo(struct namect * pst)
{
    pst->letters = strlen(pst->fname) + strlen(pst->lname);
}

void showinfo(const struct namect * pst)
{
    printf("%s  %s, 你的 %d 字母\n", pst->fname, pst->lname, pst->letters);
}

void cleanup(struct namect * pst)
{
    free(pst->fname);
    free(pst->lname);
}

char * s_gets(char * st, int n)
{
    char * ret_val;
    char * find;

    ret_val = fgets(st, n, stdin);
    if(ret_val) {
        find = strchr(st, '\n');
        if(find) {
            *find = '\0';
        } else {
            while(getchar() != '\n') {
                continue;
            }
        }
    }
    return ret_val;
}