转载并学习实现三重DES加密解密代码(一)

作者:finallyliuyu 出处:博客园

声明:此篇博文代码来自于邹德强先生。由于目前找到的版本是残缺版,所以我又进行了补全。读一份好代码,可以领略到作者的编程风格和语言驾驭能力,同时又能从其中汲取养分。现将我所修改后的DES加密解密代码全部张贴出来,有需要的也可以在上面继续改动

comon.h

 

#ifndef _COMMON_H
#define _COMMON_H
typedef 
bool (* PSubKey)[16][48];
#endif
ExpandedBlockStart.gifmyDES.h
#ifndef _myDES_H
#define _myDES_H
#include 
"common.h"
#include
<stdio.h>
class myDES
{
public:
    myDES();
    
~myDES();
     
void ByteToBit(bool *Out, const char *In, int bits);
     
void BitToByte(char *Out, const bool *In, int bits);
     
void RotateL(bool *In, int len, int loop);
     
void RotateR(bool *In,int len,int loop);
     
void Xor(bool *InA, const bool *InB, int len);
     
void Transform(bool *Out, bool *In, const char *Table, int len);
     
void S_func(bool Out[32], const bool In[48]);
     
void F_func(bool In[32], const bool Ki[48]);
     
bool RunDes(bool bType,char* In,char* Out,unsigned datalen,const char* Key,const unsigned char keylen);
     
bool RunPad(int nType,const char* In,unsigned datalen,char* Out,unsigned& padlen);
     
void SetSubKey(PSubKey pSubKey, const char Key[8]);
     
void DES(char Out[8], char In[8], const PSubKey pSubKey,bool nType);
     
bool myRunDES(bool bType,char* In,char* Out,unsigned datalen,const char* Key,const unsigned char keylen);







    
};
#endif

 

 

 

 

 

 

ExpandedBlockStart.gifmyDES.cpp
// DES.cpp: implementation of the myDES class.
//
//
#include "myDES.h"
#include 
"memory.h"



// initial permutation IP
const char IP_Table[64= {
    
585042342618102605244362820124,
        
625446383022146645648403224168,
        
574941332517,  91595143352719113,
        
615345372921135635547393123157
};
// final permutation IP^-1 
const char IPR_Table[64= {
    
408481656246432397471555236331,
        
386461454226230375451353216129,
        
364441252206028353431151195927,
        
34242105018582633141,  949175725
};
// expansion operation matrix
const char E_Table[48= {
    
32,  1,  2,  3,  4,  5,  4,  5,  6,  7,  8,  9,
        
8,  910111213121314151617,
        
161718192021202122232425,
        
2425262728292829303132,  1
};
// 32-bit permutation function P used on the output of the S-boxes 
const char P_Table[32= {
    
1672021291228171,  1523265,  183110,
        
2,  8241432273,  9,  1913306,  22114,  25
};
// permuted choice table (key) 
const char PC1_Table[56= {
    
574941332517,  9,  1585042342618,
        
10,  259514335271911,  360524436,
        
63554739312315,  7625446383022,
        
14,  661534537292113,  5282012,  4
};
// permuted choice key (table) 
const char PC2_Table[48= {
    
14171124,  1,  5,  32815,  62110,
        
231912,  426,  816,  7272013,  2,
        
415231374755304051453348,
        
444939563453464250362932
};
// number left rotations of pc1 
const char LOOP_Table[16= {
    
1,1,2,2,2,2,2,2,1,2,2,2,2,2,2,1
};
const char LOOPR_Table[16]={1,2,2,2,2,2,2,1,2,2,2,2,2,2,1,0};
// The (in)famous S-boxes 
const char S_Box[8][4][16= {
    
// S1 
    14,     4,    13,     1,  21511,  8,  310,  612,  5,  9,  0,  7,
        
015,  7,  414,  213,  110,  61211,  9,  5,  3,  8,
        
4,  114,  813,  6,  2111512,  9,  7,  310,  5,  0,
        
1512,  8,  2,  4,  9,  1,  7,  511,  31410,  0,  613,
        
// S2 
        15,  1,  814,  611,  3,  4,  9,  7,  21312,  0,  510,
        
313,  4,  715,  2,  81412,  0,  110,  6,  911,  5,
        
014,  71110,  413,  1,  5,  812,  6,  9,  3,  215,
        
13,  810,  1,  315,  4,  211,  6,  712,  0,  514,  9,
        
// S3 
        10,  0,  914,  6,  315,  5,  11312,  711,  4,  2,  8,
        
13,  7,  0,  9,  3,  4,  610,  2,  8,  514121115,  1,
        
13,  6,  4,  9,  815,  3,  011,  1,  212,  51014,  7,
        
11013,  0,  6,  9,  8,  7,  41514,  311,  5,  212,
        
// S4 
        71314,  3,  0,  6,  910,  1,  2,  8,  51112,  415,
        
13,  811,  5,  615,  0,  3,  4,  7,  212,  11014,  9,
        
10,  6,  9,  01211,  71315,  1,  314,  5,  2,  8,  4,
        
315,  0,  610,  113,  8,  9,  4,  51112,  7,  214,
        
// S5 
        212,  4,  1,  71011,  6,  8,  5,  31513,  014,  9,
        
1411,  212,  4,  713,  1,  5,  01510,  3,  9,  8,  6,
        
4,  2,  1111013,  7,  815,  912,  5,  6,  3,  014,
        
11,  812,  7,  114,  213,  615,  0,  910,  4,  5,  3,
        
// S6 
        12,  11015,  9,  2,  6,  8,  013,  3,  414,  7,  511,
        
1015,  4,  2,  712,  9,  5,  6,  11314,  011,  3,  8,
        
91415,  5,  2,  812,  3,  7,  0,  410,  11311,  6,
        
4,  3,  212,  9,  515101114,  1,  7,  6,  0,  813,
        
// S7 
        411,  21415,  0,  813,  312,  9,  7,  510,  6,  1,
        
13,  011,  7,  4,  9,  11014,  3,  512,  215,  8,  6,
        
1,  4111312,  3,  7141015,  6,  8,  0,  5,  9,  2,
        
61113,  8,  1,  410,  7,  9,  5,  01514,  2,  312,
        
// S8 
        13,  2,  8,  4,  61511,  110,  9,  314,  5,  012,  7,
        
11513,  810,  3,  7,  412,  5,  611,  014,  9,  2,
        
711,  4,  1,  91214,  2,  0,  6101315,  3,  5,  8,
        
2,  114,  7,  410,  8131512,  9,  0,  3,  5,  611
};


myDES::myDES()
{
    
}

myDES::
~myDES()
{
}

/*******************************************************************/
/*
  函 数 名 称:    ByteToBit
  功 能 描 述:    把BYTE转化为Bit流
  参 数 说 明:    Out:    输出的Bit流[in][out]
                In:        输入的BYTE流[in]
                bits:    Bit流的长度[in]

  返回值 说明:    void
  作       者:    邹德强
  更 新 日 期:    2003.12.19
/******************************************************************
*/
void myDES::ByteToBit(bool *Out, const char *In, int bits)
{
    
for(int i=0; i<bits; ++i)
        Out[i] 
= (In[i>>3]>>(7 - i&7)) & 1;
}

/*******************************************************************/
/*
  函 数 名 称:    BitToByte
  功 能 描 述:    把Bit转化为Byte流
  参 数 说 明:    Out:    输出的BYTE流[in][out]
                In:        输入的Bit流[in]
                bits:    Bit流的长度[in]

  返回值 说明:    void
  作       者:    邹德强
  更 新 日 期:    2003.12.19
/******************************************************************
*/
 
void myDES:: BitToByte(char *Out, const bool *In, int bits)
{
    memset(Out, 
0, bits>>3);
    
for(int i=0; i<bits; ++i)
        Out[i
>>3|= In[i]<<(7 - i&7);
}



/*******************************************************************/
/*
  函 数 名 称:    RotateL
  功 能 描 述:    把BIT流按位向左迭代
  参 数 说 明:    In:        输入的Bit流[in]
                len:    Bit流的长度[in]
                loop:    向左迭代的长度

  返回值 说明:    void
  作       者:    邹德强
  更 新 日 期:    2003.12.19
/******************************************************************
*/
 
void myDES::RotateL(bool *In, int len, int loop)
{
    
bool Tmp[256];

    memcpy(Tmp, In, loop);
    memcpy(In, In
+loop, len-loop);
    memcpy(In
+len-loop, Tmp, loop);
}
 
 
void myDES::RotateR(bool *In,int len,int loop)
 {
     
bool Tmp[256];
     memcpy(Tmp,In,len
-loop);
     memcpy(In,In
+len-loop,loop);
     memcpy(In
+len-loop,Tmp,len-loop);

 }



/*******************************************************************/
/*
  函 数 名 称:    Xor
  功 能 描 述:    把两个Bit流进行异或
  参 数 说 明:    InA:    输入的Bit流[in][out]
                InB:    输入的Bit流[in]
                loop:    Bit流的长度

  返回值 说明:    void
  作       者:    邹德强
  更 新 日 期:    2003.12.19
/******************************************************************
*/
 
void myDES::Xor(bool *InA, const bool *InB, int len)
{
    
for(int i=0; i<len; ++i)
        InA[i] 
^= InB[i];
}


/*******************************************************************/
/*
  函 数 名 称:    Transform
  功 能 描 述:    把两个Bit流按表进行位转化
  参 数 说 明:    Out:    输出的Bit流[out]
                In:        输入的Bit流[in]
                Table:    转化需要的表指针
                len:    转化表的长度

  返回值 说明:    void
  作       者:    邹德强
  更 新 日 期:    2003.12.19
/******************************************************************
*/
 
void myDES::Transform(bool *Out, bool *In, const char *Table, int len)
{
    
bool Tmp[256];

    
for(int i=0; i<len; ++i)
        Tmp[i] 
= In[ Table[i]-1 ];
    memcpy(Out, Tmp, len);
}



/*******************************************************************/
/*
  函 数 名 称:    S_func
  功 能 描 述:    实现数据加密S BOX模块
  参 数 说 明:    Out:    输出的32Bit[out]
                In:        输入的48Bit[in]

  返回值 说明:    void
  作       者:    邹德强
  更 新 日 期:    2003.12.19
/******************************************************************
*/
 
void myDES::S_func(bool Out[32], const bool In[48])
{
    
for(char i=0,j,k; i<8++i,In+=6,Out+=4
    {
        j 
= (In[0]<<1+ In[5];
        k 
= (In[1]<<3+ (In[2]<<2+ (In[3]<<1+ In[4];    //组织SID下标
        
        
for(int l=0; l<4++l)                                //把相应4bit赋值
            Out[l] = (S_Box[i][j][k]>>(3 - l)) & 1;
    }
}


/*******************************************************************/
/*
  函 数 名 称:    F_func
  功 能 描 述:    实现数据加密到输出P
  参 数 说 明:    Out:    输出的32Bit[out]
                In:        输入的48Bit[in]

  返回值 说明:    void
  作       者:    邹德强
  更 新 日 期:    2003.12.19
/******************************************************************
*/
 
void myDES::F_func(bool In[32], const bool Ki[48])
{
    
bool MR[48];
    Transform(MR, In, E_Table, 
48);
    Xor(MR, Ki, 
48);
    S_func(In, MR);
    Transform(In, In, P_Table, 
32);
}


/*******************************************************************/
/*
  函 数 名 称:    RunDes
  功 能 描 述:    执行DES算法对文本加解密
  参 数 说 明:    bType    :类型:加密ENCRYPT,解密DECRYPT
                bMode    :模式:ECB,CBC
                In        :待加密串指针
                Out        :待输出串指针
                datalen    :待加密串的长度,同时Out的缓冲区大小应大于或者等于datalen
                Key        :密钥(可为8位,16位,24位)支持3密钥
                keylen    :密钥长度,多出24位部分将被自动裁减

  返回值 说明:    bool    :是否加密成功
  作       者:    邹德强
  更 新 日 期:    2003.12.19
/******************************************************************
*/
bool myDES::RunDes(bool bType,char* In,char* Out,unsigned datalen,const char* Key,const unsigned char keylen)
{
    
//判断输入合法性
    if(!(In && Out && Key && datalen && keylen>=8))
        
return false;
    
//只处理8的整数倍,不足长度自己填充
    if(datalen & 0x00000007)
        
return false;
    
    
bool                m_SubKey[3][16][48];        //秘钥
    
//构造并生成SubKeys
    unsigned char nKey    =    (keylen>>3)>3 ? 3: (keylen>>3);
    
for(int i=0;i<nKey;i++)
    {
        SetSubKey(
&m_SubKey[i],&Key[i<<3]);
    }

        
//ECB模式
    
        
if(nKey    ==    1)    //单Key
        {
            
for(int i=0,j=datalen>>3;i<j;++i,Out+=8,In+=8)
            {
                DES(Out,In,
&m_SubKey[0],bType);
            }
        }
        
else
        
if(nKey == 2)    //3DES 2Key
        {
            
for(int i=0,j=datalen>>3;i<j;++i,Out+=8,In+=8)
            {
                DES(Out,In,
&m_SubKey[0],bType);
                DES(Out,Out,
&m_SubKey[1],!bType);
                DES(Out,Out,
&m_SubKey[0],bType);
            }
        }
        
else            //3DES 3Key
        {
            
for(int i=0,j=datalen>>3;i<j;++i,Out+=8,In+=8)
            {
                DES(Out,In,
&m_SubKey[bType? 2 : 0],bType);
                DES(Out,Out,
&m_SubKey[1],!bType);
                DES(Out,Out,
&m_SubKey[bType? 0 : 2],bType);    
            }
        }
        
    
    
    
return true;
}




/*******************************************************************/
/*
  函 数 名 称:    RunPad
  功 能 描 述:    根据协议对加密前的数据进行填充
  参 数 说 明:    bType    :类型:PAD类型
                In        :数据串指针
                Out        :填充输出串指针
                datalen    :数据的长度
                padlen    :(in,out)输出buffer的长度,填充后的长度

  返回值 说明:    bool    :是否填充成功
  作       者:    邹德强
  修 改 历 史:    

  更 新 日 期:    2003.12.19
/******************************************************************
*/
/*bool    myDES::RunPad(int nType,const char* In,unsigned datalen,char* Out,unsigned& padlen)
{
    int res = (datalen & 0x00000007);
    
    
    if(padlen< (datalen+8-res))
    {
        return false;
    }
    else
    {
        padlen    =    (datalen+8-res);
        memcpy(Out,In,datalen);
        if(nType==PAD_ISO_1)
        {
            memset(Out+datalen,0x00,8-res);
        }

        else if(nType==PAD_ISO_2)
        {
            memset(Out+datalen,0x80,1);
            memset(Out+datalen,0x00,7-res);
        }
        else if(nType==PAD_PKCS_7)
        {
            memset(Out+datalen,8-res,8-res);
        }
        else
        {
            return false;
        }

        return true;
    }
    
    
    
}
*/
bool    myDES::RunPad(int nType,const char* In,unsigned datalen,char* Out,unsigned& padlen)
{
    
int res = (datalen & 0x00000007);
    memcpy(Out,In,datalen);
    
if (res)
    {
        memset(Out
+datalen,0x00,8-res);
        
return true;

    }
    
else
    {
        
return false;
    }


    

            
}






//计算并填充子密钥到SubKey数据中
void myDES::SetSubKey(PSubKey pSubKey, const char Key[8])
{
    
bool K[64], *KL=&K[0], *KR=&K[28];
    ByteToBit(K, Key, 
64);
    Transform(K, K, PC1_Table, 
56);
    
for(int i=0; i<16++i) 
    {
        
        
            RotateL(KL, 
28, LOOP_Table[i]);
            RotateL(KR, 
28, LOOP_Table[i]);    
           Transform((
*pSubKey)[i], K, PC2_Table, 48);
    }
}



//DES单元运算
void myDES::DES(char Out[8], char In[8], const PSubKey pSubKey,bool nType)
{
    
bool M[64], tmp[32], *Li=&M[0], *Ri=&M[32];
    ByteToBit(M, In, 
64);
    Transform(M, M, IP_Table, 
64);
    
if( nType )
    {
        
for(int i=0; i<16++i)
        {
            memcpy(tmp, Ri, 
32);        //Ri[i-1] 保存
            F_func(Ri, (*pSubKey)[i]);    //Ri[i-1]经过转化和SBox输出为P
            Xor(Ri, Li, 32);            //Ri[i] = P XOR Li[i-1]
            memcpy(Li, tmp, 32);        //Li[i] = Ri[i-1]
        }
    }
    
else
    {
        
for(int i=15; i>=0--i) 
        {
            memcpy(tmp, Ri, 
32);        //Ri[i-1] 保存
            F_func(Ri, (*pSubKey)[i]);    //Ri[i-1]经过转化和SBox输出为P
            Xor(Ri, Li, 32);            //Ri[i] = P XOR Li[i-1]
            memcpy(Li, tmp, 32);        //Li[i] = Ri[i-1]
        }
    }
    RotateL(M,
64,32);                    //Ri与Li换位重组M
    Transform(M, M, IPR_Table, 64);        //最后结果进行转化
    BitToByte(Out, M, 64);                //组织成字符
}
bool myDES::myRunDES(bool bType,char* In,char* Out,unsigned datalen,const char* Key,const unsigned char keylen)
{


    
return true;
    
}

 

 

转载于:https://www.cnblogs.com/finallyliuyu/archive/2010/12/27/1917600.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/422971.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【OS学习笔记】三十 保护模式九:段页式内存管理机制概述

上几篇文章学习了任务切换相关知识&#xff0c;如下&#xff1a; 【OS学习笔记】二十六 保护模式八&#xff1a;任务门—任务切换【OS学习笔记】二十七 保护模式八&#xff1a;任务切换的方法之----jmp与call的区别以及任务的中断嵌套 今天继续学习保护模式下的分页机制。本篇…

真人拳皇项目第六次Scrum总结——史经浩

今天&#xff0c;我们组开始了正式的编码阶段&#xff0c;前期plan的时候天马行空&#xff0c;现在是脚踏实地的coding了。在Scrum上&#xff0c;大家sync了一下各自的进展&#xff0c;如下&#xff1a; 今天 进度 问题及解决 明天 田飞 work item 37528:DirectX动画的de…

【OS学习笔记】三十一 保护模式九:页目录、页表和页三者的关系详解

上一篇文章学习了&#xff1a;保护模式九&#xff1a;段页式内存管理机制概述 本篇文章接着学习以下内容&#xff1a; 页目录概念页表概念页目录、页表与页之间的关系虚拟地址&#xff08;线性地址&#xff09;到物理地址的具体变换过程。 1、页目录、页表和页的对应关系 第…

使用某个文件夹下的所有文件去替换另一个文件夹下及其子文件夹下存在的同名文件(Python实现)...

值此新年即将到来之际,在这献上今年最后一篇文章. 产生这个需求是在项目的一次图标替换上,当时给了我一堆新图标要替换原来的老图标,可是原来的老图标分布在某个文件夹下的各个子文件夹下面,而新图标全是在同一个目录下的. 手动替换的话,只能是搜索文件名后替换,但是文件很多太…

一款研发管理软件的对象标签介绍

如果你了解WIKI&#xff0c;WIKI中的所有信息链接以标签的方式网状关联。TOPO系统中实现了完整的TAG功能&#xff0c;区别于目前市面上的其他类似管理系统&#xff0c;TOPO系统中实现的标签功能更加彻底和全面&#xff0c;例如完全用户自定义TAG&#xff0c;系统中所有管理对象…

【OS学习笔记】三十四 保护模式十:中断和异常区别

上几篇文章学习了分页机制的一些原理&#xff1a; 【OS学习笔记】三十 保护模式九&#xff1a;段页式内存管理机制概述【OS学习笔记】三十一 保护模式九&#xff1a;页目录、页表和页三者的关系详解 今天继续学习保护模式下的关于中断与异常的概念。本文主要学习中断与异常的…

记录一次文件迁移

事情的经过是这样子的&#xff01;数据库A表添加一条记录&#xff0c;**系统中B目录下就会多出5n个文件。随着系统运行3年多&#xff0c;B目录中的文件数已高达2M多&#xff0c;而这些文件恰恰又是用户高度频繁访问的。于是问题就来了&#xff0c;一方面是用户访问文件速度变慢…

【OS学习笔记】三十五 保护模式十:中断描述符表、中断门和陷阱门

上一篇文章学习了中断与异常的概念&#xff1a;【OS学习笔记】三十四 保护模式十&#xff1a;中断和异常区别 本片文章接着学习以下内容&#xff1a; 中断描述符表中断门陷阱门 1 中断描述符表 我们前面讲了无数次&#xff0c;在实模式下&#xff0c;是由位于低地址的1M内存…

【OS学习笔记】三十六 保护模式十:通过中断发起任务切换----中断任务

上一篇文章学习了&#xff1a;OS学习笔记】三十五 保护模式十&#xff1a;中断描述符表、中断门和陷阱门 本篇文章接着上一篇文章学习中断任务。 我们在前面文章中一直在说通过中断发起任务切换&#xff0c;本文就是将之前没有说明白的内容&#xff1a;通过中断发起任务切换讲…

小议传统分层与新式分层,抑或与DDD分层

引言本文提到的分层只是软件架构上的分层。文中的传统分层指的是传统的三层结构&#xff1a;UI&#xff08;界面表现层&#xff09;,BLL&#xff08;业务逻辑层&#xff09;,DAL&#xff08;数据访问层&#xff09;。文中提出的观点也都是个人的一点认识&#xff0c;与任何组织…

WCF 第八章 安全 客户端认证

一个服务的客户端认证是通过向服务提供一系列信赖的声明。声明可以是任何形式&#xff0c;只要客户端和服务端理解这个格式并信赖它的来源就可以。 如果客户端和服务端共享一个秘密信息&#xff0c;比如一个用户名和密码&#xff0c;只要客户端通过一个合法认证发送数据&#x…

前端学习(205):animation动画库

动画库 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><meta http-equiv"X-UA-Compatible" conte…

【剑指offer - C++/Java】7、斐波那契数列

在线题目链接&#xff1a;斐波那契数列 文章目录1、题目描述2、题目分析3、代码3.1 递归方法3.11 Java代码3.12 C代码3.2 动态规划3.21 Java代码3.22 C代码3.3 循环方法3.31 Java代码3.32 C代码4、总结1、题目描述 大家都知道斐波那契数列&#xff0c;现在要求输入一个整数n&a…

【剑指offer - C++/Java】8、跳台阶

在线题目链接&#xff1a;跳台阶 文章目录1、题目描述2、题目分析3、代码3.1 递归方法3.11 Java代码3.12 C代码3.2 动态规划3.21 Java代码3.22 C代码3.3 循环方法3.31 Java代码3.32 C代码4、总结1、题目描述 一只青蛙一次可以跳上1级台阶&#xff0c;也可以跳上2级。求该青蛙跳…

【剑指offer - C++/Java】10、矩形覆盖

在线题目链接&#xff1a;矩形覆盖 文章目录1 题目描述2 题目分析3 代码3.1 递归方法3.11 Java代码3.12 C代码3.2 动态规划算法3.2 动态规划3.21 Java代码3.22 C代码3.3 循环方法3.31 Java代码3.32 C代码4、总结1 题目描述 我们可以用2*1的小矩形横着或者竖着去覆盖更大的矩形…

【剑指offer - C++/Java】12、数值的整数次方

在线题目链接&#xff1a;数值的整数次方 文章目录1 题目描述2 题目分析2.1 方法1 循环2.11 Java代码2.12 C代码2.2 方法2 递归2.21 Java代码2.22 C代码3 总结1 题目描述 给定一个double类型的浮点数base和int类型的整数exponent。求base的exponent次方。 2 题目分析 2.1 方…

【剑指offer - C++/Java】14、链表中倒数第k的节点

在线题目链接&#xff1a;链表中倒数第k的节点 文章目录1 题目描述2 题目分析2.1 Java代码2.2 C代码3 总结1 题目描述 输入一个链表&#xff0c;输出该链表中倒数第k个结点。 2 题目分析 这道题比较简单。常规做法是先求出链表的总的节点个数n&#xff0c;然后再从头开始找第n-…

beta:scrum5

今天的工作 周一的工作 困难 王佳磊 收集数据&#xff0c;build了online的数据库, 38934 38939&#xff0c;收集更多数据&#xff0c;在新的API环境下&#xff0c;逐步发现并fix掉以前姓名到ID映射的bug. API的改动&#xff0c;ID的合并 肖巍&#xff0c;兰翠玲 等待测…

【软件开发底层知识修炼】十三 链接器-如何写出不依赖C库函数的代码

本文将综合以下4篇文章&#xff0c;学习如何写出不依赖libc库的程序&#xff1a; 【软件开发底层知识修炼】九 链接器-可重定位文件与可执行文件【软件开发底层知识修炼】十 链接器-main函数不是第一个被执行的函数【软件开发底层知识修炼】十一 链接器-链接脚本【软件开发底层…

前端学习(218):属性选择器

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/ html4/strict.dtd"> <html><head><meta http-equiv"content-type" content"text/html; charsetutf-8"><title>属性选择器&…