2016-2-16

1. (1)学习了Qt的QRegExp正则表达式类,

关于正则表达式:点击打开链接

Note: The C++ compiler transforms backslashes in strings. To include a \ in a regexp, enter it twice, i.e. \\. To match the backslash character itself, enter it four times, i.e. \\\\.(C++编译器将反斜杠当作转移字符,所以输入\时需要输入\\,匹配\时输入\\\\)

(2)。通配符的四种形式:字符,?,*, [...]

2. inline, __forceinline和__inline

点击打开链接:详细

(1)后面的两个是微软的关键字

(2)inline只能用于C++,后两者可用于C和C++

(3)inline和__inline:编译器在衡量了将代码嵌入到调用处和进行函数调用的cost之后才决定是否将此函数进行inlined,是一种建议

__forceinline覆盖了cost分析,由编码者决定,但是如果compiling with /clr,也不能inlined

(4)不能inline的情况见链接,常见的两种:递归不能;Functions that are referred to through a pointer elsewhere in the translation unit.

(5)inline VS macros

相同点:都是在编译时将函数代码在被调用处展开:the function code is expanded at the point of the call at compile time

不同点:由于 inline是由编译器解释的,macross是由预处理器展开的

所以

  • Inline functions follow all the protocols of type safety enforced on normal functions.(inline函数遵守强加在正常函数上的类型安全协议)

  • Inline functions are specified using the same syntax as any other function except that they include the inline keyword in the function declaration.(除了函数声明时的inline关键字外,与其他函数的有相同的语法)

  • Expressions passed as arguments to inline functions are evaluated once. In some cases, expressions passed as arguments to macros can be evaluated more than once.(传作为inline函数的表达式只能计算一次,对于macros,有些情况下,赋给macros的表达式可以计算不止一次)

3.__stdcall, __cdecl , __fastcall

 blog1点击打开链接

blog2点击打开链接

MS点击打开链接

__stdcall点击打开链接

__cdecl点击打开链接

__fastcall点击打开链接

   以下系转载:     

     在C语言中,假设我们有这样的一个函数:
  
  int function(int a,int b)
  
  调用时只要用result = function(1,2)这样的方式就可以使用这个函数。但是,当高级语言被编译成计算机可以识别的机器码时,有一个问题就凸现出来:在CPU中,计算机没有办法知道一个函数调用需要多少个、什么样的参数,也没有硬件可以保存这些参数。也就是说,计算机不知道怎么给这个函数传递参数,传递参数的工作必须由函数调用者和函数本身来协调。为此,计算机提供了一种被称为栈的数据结构来支持参数传递。

  栈是一种先进后出的数据结构,栈有一个存储区、一个栈顶指针。栈顶指针指向堆栈中第一个可用的数据项(被称为栈顶)。用户可以在栈顶上方向栈中加入数据,这个操作被称为压栈(Push),压栈以后,栈顶自动变成新加入数据项的位置,栈顶指针也随之修改。用户也可以从堆栈中取走栈顶,称为弹出栈(pop),弹出栈后,栈顶下的一个元素变成栈顶,栈顶指针随之修改。
  函数调用时,调用者依次把参数压栈,然后调用函数,函数被调用以后,在堆栈中取得数据,并进行计算。函数计算结束以后,或者调用者、或者函数本身修改堆栈,使堆栈恢复原装。
  在参数传递中,有两个很重要的问题必须得到明确说明:
  
  当参数个数多于一个时,按照什么顺序把参数压入堆栈 
  函数调用后,由谁来把堆栈恢复原装 
  在高级语言中,通过函数调用约定来说明这两个问题。常见的调用约定有:
  stdcall 
  cdecl 
  fastcall 
  thiscall 
  naked call

  stdcall调用约定
  stdcall很多时候被称为pascal调用约定,因为pascal是早期很常见的一种教学用计算机程序设计语言,其语法严谨,使用的函数调用约定就是stdcall。在Microsoft C++系列的C/C++编译器中,常常用PASCAL宏来声明这个调用约定,类似的宏还有WINAPI和CALLBACK。
  stdcall调用约定声明的语法为(以前文的那个函数为例):
  
  int __stdcall function(int a,int b)
  
  stdcall的调用约定意味着:1)参数从右向左压入堆栈,2)函数自身修改堆栈 3)函数名自动加前导的下划线,后面紧跟一个@符号,其后紧跟着参数的尺寸
  以上述这个函数为例,参数b首先被压栈,然后是参数a,函数调用function(1,2)调用处翻译成汇编语言将变成:
  push 2        第二个参数入栈
  push 1        第一个参数入栈
  call function    调用参数,注意此时自动把cs:eip入栈
  而对于函数自身,则可以翻译为: 
  push ebp       保存ebp寄存器,该寄存器将用来保存堆栈的栈顶指针,可以在函数退出时恢复
  mov ebp, esp    保存堆栈指针
  mov eax,[ebp + 8H] 堆栈中ebp指向位置之前依次保存有ebp, cs:eip, a, b, ebp +8指向a
  add eax,[ebp + 0CH] 堆栈中ebp + 12处保存了b
  mov esp, ebp    恢复esp
  pop ebp
  ret 8
  而在编译时,这个函数的名字被翻译成_function@8
  注意不同编译器会插入自己的汇编代码以提供编译的通用性,但是大体代码如此。其中在函数开始处保留esp到ebp中,在函数结束恢复是编译器常用的方法。
  从函数调用看,2和1依次被push进堆栈,而在函数中又通过相对于ebp(即刚进函数时的堆栈指针)的偏移量存取参数。函数结束后,ret 8表示清理8个字节的堆栈,函数自己恢复了堆栈。
  
  cdecl调用约定
  cdecl调用约定又称为C调用约定,是C语言缺省的调用约定,它的定义语法是:
  int function (int a ,int b) //不加修饰就是C调用约定
  int __cdecl function(int a,int b)//明确指出C调用约定
  在写本文时,出乎我的意料,发现cdecl调用约定的参数压栈顺序是和stdcall是一样的,参数首先由右向左压入堆栈。所不同的是,函数本身不清理堆栈,调用者负责清理堆栈。由于这种变化,C调用约定允许函数的参数的个数是不固定的,这也是C语言的一大特色。对于前面的function函数,使用cdecl后的汇编码变成:
  调用处
  push 1
  push 2
  call function
  add esp, 8     注意:这里调用者在恢复堆栈
  被调用函数_function处
  push ebp       保存ebp寄存器,该寄存器将用来保存堆栈的栈顶指针,可以在函数退出时恢复
  mov ebp,esp     保存堆栈指针
  mov eax,[ebp + 8H] 堆栈中ebp指向位置之前依次保存有ebp,cs:eip,a,b,ebp +8指向a
  add eax,[ebp + 0CH] 堆栈中ebp + 12处保存了b
  mov esp,ebp     恢复esp
  pop ebp
  ret         注意,这里没有修改堆栈
  MSDN中说,该修饰自动在函数名前加前导的下划线,因此函数名在符号表中被记录为_function,但是我在编译时似乎没有看到这种变化。
  由于参数按照从右向左顺序压栈,因此最开始的参数在最接近栈顶的位置,因此当采用不定个数参数时,第一个参数在栈中的位置肯定能知道,只要不定的参数个数能够根据第一个后者后续的明确的参数确定下来,就可以使用不定参数,例如对于CRT中的sprintf函数,定义为: 
  int sprintf(char* buffer,const char* format,...)
  由于所有的不定参数都可以通过format确定,因此使用不定个数的参数是没有问题的。

4. pugixml: 点击打开链接  DOM

5. 虚拟地址空间: 点击打开链接

虚拟地址空间

当处理器读或写入内存位置时,它会使用虚拟地址。作为读或写操作的一部分,处理器将虚拟地址转换为物理地址。通过虚拟地址访问内存有以下优势:

  • 程序可以使用一系列相邻的虚拟地址来访问物理内存中不相邻的大内存缓冲区。

  • 程序可以使用一系列虚拟地址来访问大于可用物理内存的内存缓冲区。当物理内存的供应量变小时,内存管理器会将物理内存页(通常大小为 4 KB)保存到磁盘文件。数据或代码页会根据需要在物理内存与磁盘之间移动。

  • 不同进程使用的虚拟地址彼此隔离。一个进程中的代码无法更改正在由另一进程或操作系统使用的物理内存。

进程可用的虚拟地址范围称为该进程的“虚拟地址空间”。每个用户模式进程都有其各自的专用虚拟地址空间。 对于 32 位进程,虚拟地址空间通常为 2 GB,范围从 0x00000000 至 0x7FFFFFFF。对于 64 位进程,虚拟地址空间为 8 TB,范围从 0x000'00000000 至 0x7FF'FFFFFFFF。一系列虚拟地址有时称为一系列“虚拟内存”

此图说明了虚拟地址空间的一些重要功能。

图:两个进程的虚拟地址空间

该图显示了两个 64 位进程的虚拟地址空间:Notepad.exe 和 MyApp.exe。每个进程都有其各自的虚拟地址空间,范围从 0x000'0000000 至 0x7FF'FFFFFFFF。每个阴影框都表示虚拟内存或物理内存的一个页面(大小为 4 KB)。注意,Notepad 进程使用从 0x7F7'93950000 开始的虚拟地址的三个相邻页面。但虚拟地址的这三个相邻页面会映射到物理内存中的非相邻页面。而且还注意,两个进程都使用从 0x7F7'93950000 开始的虚拟内存页面,但这些虚拟页面都映射到物理内存的不同页面。

用户空间和系统空间

诸如 Notepad.exe 和 MyApp.exe 的进程在用户模式下运行。核心操作系统组件和多个驱动程序在更有特权的内核模式下运行。有关处理器模式的详细信息,请参阅用户模式和内核模式。每个用户模式进程都有其各自的专用虚拟地址空间,但在内核模式下运行的所有代码都共享称为“系统空间”的单个虚拟地址空间。当前用户模式进程的虚拟地址空间称为“用户空间”

在 32 位 Windows 中,可用的虚拟地址空间共计为 2^32 字节(4 GB)。通常较下的 2 GB 用于用户空间,较上的 2 GB 用于系统空间。

图:系统空间

在 32 位 Windows 中,你可以指定(在启动时)超过 2 GB 用于用户空间。结果是系统空间可用的虚拟地址更少。可以将用户空间的大小增至 3 GB,在这种情形下系统空间仅有 1 GB。若要增大用户空间的大小,请使用 BCDEdit /set increaseuserva

在 64 位 Windows 中,虚拟地址空间的理论大小为 2^64 字节(16 百亿亿字节),但实际上仅使用 16 百亿亿字节范围的一小部分。范围从 0x000'00000000 至 0x7FF'FFFFFFFF 的 8 TB 用于用户空间,范围从 0xFFFF0800'00000000 至 0xFFFFFFFF'FFFFFFFF 的 248 TB 的部分用于系统空间。

图:页面缓冲池和非页面缓冲池

用户模式下运行的代码可以访问用户空间,但不能访问系统空间。此限制可防止用户模式代码读或更改受保护的操作系统数据结构。内核模式下运行的代码既可以访问用户空间,也可以访问系统空间。即,在内核模式下运行的代码可以访问系统空间和当前用户模式进程的虚拟地址空间。

在内核模式下运行的驱动程序必须在直接从用户空间地址中读取或写入这些地址时非常小心。此方案说明了原因。

  1. 用户模式程序发起从设备读取某些数据的请求。程序提供缓冲区的起始地址以接收数据。

  2. 在内核模式下运行的设备驱动程序例程启动读取操作并将控制权返回到其调用程序。

  3. 然后,设备中断了当前运行的任何线程以显示读取操作完成。 中断由在此任意线程上运行的内核模式驱动程序例程进行处理,该例程属于任意进程。
  4. 此时,驱动程序不得将数据写入用户模式程序在步骤 1 中提供的开始地址。此地址位于发起请求的进程的虚拟地址空间,该进程可能很大程度上不同于当前进程。

页面缓冲池和非页面缓冲池

在用户空间中,所有物理内存页面都可以根据需要进行分页至磁盘文件。在系统空间中,某些物理页面可以分页,而其他页面不能。系统空间具有用于动态分配内存的两个区域:页面缓冲池和非页面缓冲池。在 64 位 Windows 中,页面缓冲池为 128 GB 的虚拟地址,范围从 0xFFFFA800'00000000 至 0xFFFFA81F'FFFFFFFF。非页面缓冲池为 128 GB 的虚拟地址,范围从 0xFFFFAC00'00000000 至 0xFFFFAC1F'FFFFFFFF。

在页面缓存池中分配的内存可以根据需要分页至磁盘文件。在非页面缓冲池中分配的内存永远无法分页至磁盘文件。

图:比较页面缓冲池中的内存分配与非页面缓冲池中的内存分配

5.  implicitly 暗含的,隐然,含蓄地

  • implicitly typed 隐式类型,隐含型别
  • link implicitly 若使用隐含链接

  • Assembly 装配,集结号,组装
  • assembly drawing 装配图,组合图,总图
  • constituent assembly 制宪议会,立宪会议,制宪会议
  • Caret 脱字符,插入符号,插入记号

codec


以下是一个简单的基于Transformer算法的代码示例,可以用来预测SNumber。 ```python import pandas as pd import numpy as np import matplotlib.pyplot as plt from sklearn.preprocessing import StandardScaler from sklearn.model_selection import train_test_split from tensorflow.keras.models import Model from tensorflow.keras.layers import Input, Dense, Dropout, LayerNormalization, MultiHeadAttention, TimeDistributed, concatenate # 加载数据 data = pd.read_csv('data.csv') X = data.drop(['SNumber'], axis='columns') y = data['SNumber'] # 标准化输入特征 scaler = StandardScaler() X = scaler.fit_transform(X) # 划分训练集和测试集 X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, shuffle=False) # 构建Transformer模型 def transformer_model(input_shape): inputs = Input(shape=input_shape) x = Dense(64, activation='relu')(inputs) x = LayerNormalization()(x) x = Dropout(0.2)(x) x = Dense(32, activation='relu')(x) x = LayerNormalization()(x) x = Dropout(0.2)(x) x = Dense(1)(x) model = Model(inputs=inputs, outputs=x) return model # 训练模型 model = transformer_model((X_train.shape[1],)) model.compile(optimizer='adam', loss='mean_squared_error') model.fit(X_train, y_train, epochs=100, batch_size=16, validation_data=(X_test, y_test)) # 预测结果 y_pred = model.predict(X_test) # 可视化预测结果 plt.plot(y_test.values, label='True') plt.plot(y_pred, label='Predicted') plt.legend() plt.show() ``` 需要注意的是,这只是一个简单的示例,实际上可能需要进行更多的特征工程和调整模型参数来获得更好的预测结果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值