solidityでメモリを動的に割り当てる方法


場合によってはsolidityでbufferを構築したい場合があります.まず、このbufferにメモリを割り当てる必要があります.solidityではbytesのような構造しか使われていませんが、現在は対応する位置のデータをスライスしたり置換したりする操作はbytesでは容易ではありません.まずbufferにメモリを割り当てることです.直接コード:
struct buffer {
    bytes buf;
    uint capacity;
}

function init(buffer memory buf, uint capacity) internal pure returns(buffer memory) {
    if (capacity % 32 != 0) {
      capacity += 32 - (capacity % 32);
    }
    // Allocate space for the buffer data
    buf.capacity = capacity;
    assembly {
      let ptr := mload(0x40)
      mstore(buf, ptr)
      mstore(ptr, 0)
      mstore(0x40, add(32, add(ptr, capacity)))
    }
    return buf;
  }

まず、その内容bufと総容量capacityを含む構造体bufferを定義し、initメソッドを定義する(bufferは転送され、resizeにも使用できる).以太坊保は0 x 40アドレスに次の利用可能なポインタ(free pointer)を保存した.let ptr := mlod(0x40)
注意関数の最初のパラメータbuffer memory bufには、memoryキーワードがあり、bufもメモリ内にあることを示し、bufはポインタの別名であり、その値はbufオブジェクトが格納しているアドレスである.mstore(buf, ptr)
利用可能なポインタのアドレスをbufのアドレスに置き換えたmstore(ptr ,0)
ptrアドレスの指向するデータを0にする、つまりbufを0に初期化する.EVMは0 x 40アドレスのポインタが全0データを指すことを保証しないからだ.mstore(0x40, add(32, add(ptr, capacity)))
この行の役割は、0 x 40のアドレスを更新し、次の使用可能なポインタを指すことです.EVMでは0 x 40の更新は処理されず、ユーザは自分で処理しなければならない.0 x 40の値をどのように更新しますか?開発したばかりのbufferをスキップして、次のアドレスを0 x 40に割り当てることができます.開いたばかりのスペースはcapacityサイズで、さらに上位32ビット(0 x 20)はデータの長さなので、0 x 40はptrに基づいてcapacity+32をオフセットします