为了账号安全,请及时绑定邮箱和手机立即绑定

什么是C#中的memset?

什么是C#中的memset?

C#
呼如林 2019-11-13 12:49:44
我需要byte[]用一个非零值填充。如何在C#中做到这一点而又不遍历byte数组中的每个数组?更新:评论似乎将其分为两个问题-是否有一种Framework方法来填充可能类似于的byte [] memset当我们处理非常大的数组时,最有效的方法是什么?我完全同意,正如Eric和其他人指出的那样,使用简单的循环就可以了。问题的关键是看我是否可以学习有关C#的新知识:)我认为Juliet的并行操作方法应该比简单的循环还要快。基准测试: 感谢Mikael Svenson:http : //techmikael.blogspot.com/2009/12/filling-array-with-default-value.html事实证明,for除非您要使用不安全的代码,否则简单的循环是必经之路。抱歉,我的原始帖子不够清晰。Eric和Mark的评论都是正确的。当然需要有更集中的问题。感谢大家的建议和回应。
查看完整描述

3 回答

?
四季花海

TA贡献1811条经验 获得超5个赞

您可以使用Enumerable.Repeat:


byte[] a = Enumerable.Repeat((byte)10, 100).ToArray();

第一个参数是您想要重复的元素,第二个参数是重复它的次数。


对于小型阵列,这是可以的,但是如果要处理大型阵列,并且性能是一个问题,则应使用循环方法。


查看完整回答
反对 回复 2019-11-13
?
撒科打诨

TA贡献1934条经验 获得超2个赞

实际上,很少有称为Initblk(英文版)的IL操作可以做到这一点。因此,让我们将其用作不需要“不安全”的方法。这是帮助程序类:


public static class Util

{

    static Util()

    {

        var dynamicMethod = new DynamicMethod("Memset", MethodAttributes.Public | MethodAttributes.Static, CallingConventions.Standard,

            null, new [] { typeof(IntPtr), typeof(byte), typeof(int) }, typeof(Util), true);


        var generator = dynamicMethod.GetILGenerator();

        generator.Emit(OpCodes.Ldarg_0);

        generator.Emit(OpCodes.Ldarg_1);

        generator.Emit(OpCodes.Ldarg_2);

        generator.Emit(OpCodes.Initblk);

        generator.Emit(OpCodes.Ret);


        MemsetDelegate = (Action<IntPtr, byte, int>)dynamicMethod.CreateDelegate(typeof(Action<IntPtr, byte, int>));

    }


    public static void Memset(byte[] array, byte what, int length)

    {

        var gcHandle = GCHandle.Alloc(array, GCHandleType.Pinned);

        MemsetDelegate(gcHandle.AddrOfPinnedObject(), what, length);

        gcHandle.Free();

    }


    public static void ForMemset(byte[] array, byte what, int length)

    {

        for(var i = 0; i < length; i++)

        {

            array[i] = what;

        }

    }


    private static Action<IntPtr, byte, int> MemsetDelegate;


}

表现如何?这是Windows / .NET和Linux / Mono(不同PC)的结果。


Mono/for:     00:00:01.1356610

Mono/initblk: 00:00:00.2385835 


.NET/for:     00:00:01.7463579

.NET/initblk: 00:00:00.5953503

因此值得考虑。请注意,生成的IL将不可验证。


查看完整回答
反对 回复 2019-11-13
?
收到一只叮咚

TA贡献1821条经验 获得超4个赞

有点晚了,但是下面的方法可能是一个不错的折衷方案,而无需恢复为不安全的代码。基本上,它使用常规循环初始化数组的开头,然后恢复为Buffer.BlockCopy(),该速度应与使用托管调用所能获得的速度一样快。


public static void MemSet(byte[] array, byte value) {

  if (array == null) {

    throw new ArgumentNullException("array");

  }

  const int blockSize = 4096; // bigger may be better to a certain extent

  int index = 0;

  int length = Math.Min(blockSize, array.Length);

  while (index < length) {

    array[index++] = value;

  }

  length = array.Length;

  while (index < length) {

    Buffer.BlockCopy(array, 0, array, index, Math.Min(blockSize, length-index));

    index += blockSize;

  }

}


查看完整回答
反对 回复 2019-11-13
  • 3 回答
  • 0 关注
  • 870 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信