【问题标题】:Check if 2d pointer array has user defined value in C?检查二维指针数组是否在 C 中具有用户定义的值?
【发布时间】:2011-06-01 23:40:02
【问题描述】:

示例代码:

float** a;  
a = (float**) malloc(numNodes * sizeof(float*));  
for(int i=0; i<`numNodes`; i++)  
{  
    a[i] = (float*)malloc((numNodes-1) * sizeof(float));  
}

我在上面创建了一个动态二维数组。在填充之前,我注意到数组中的每个块都已经保存了这个值:-431602080.000000 而不是 NULL。这是为什么呢?
在某些情况下,并非数组中的所有空格都被使用。
所以,我的查询很简单,有没有一种优雅的方法来检查每个块是否具有此默认值或用户定义的值?

提前致谢。

【问题讨论】:

    标签: c multidimensional-array dynamic-arrays


    【解决方案1】:

    在 C 中,自动变量不会自动初始化。如果需要,您需要将变量显式设置为 0。

    malloc 也是如此,它不会初始化它分配的堆上的空间。如果要初始化,可以使用calloc

    a = malloc( numNodes*sizeof(float*) ); // no need to initialize this
    for ... {
      a[i] = calloc( numNodes-1, sizeof(float) );
    }
    

    【讨论】:

    • Peoro:如果它没有初始化它,那么这个 -431602080.000000 是什么?每个街区似乎都有?
    • 如果你在调试模式下运行,那么这应该是一个神奇的值,可以帮助你看到你正在使用未初始化的数据。
    • 它可以是任何东西。它可能是您调用之前那部分内存所包含的值。
    • @Freddy,谁知道呢?这取决于您的操作系统、malloc 实现以及到目前为止您的应用程序中发生了什么。下一次运行可能会有所不同。它是未定义的,不要依赖它也不要担心它——无论如何你都必须初始化分配的空间
    • 如果您在babbage.cs.qc.edu/IEEE-754/Decimal.html 使用计算器,您会发现它是十六进制值 0xCDCDCDCD。大概是为了调试而初始化了一些东西?
    【解决方案2】:

    C 运行时不需要初始化您自己未初始化的任何内存,它们所保存的值本质上是上次使用该内存时留下的随机垃圾。您必须先将它们全部显式设置为 NULL 或使用 calloc。

    【讨论】:

      【解决方案3】:

      在填充之前,我注意到数组中的每个块都已经保存了这个值:-431602080.000000 而不是 NULL。这是为什么呢?

      malloc() 不会初始化它分配的内存。如果你想要0初始化,你需要使用calloc()

      void *calloc(size_t nelem, size_t elsize);
      

      calloc() 函数为 nelem 元素的数组分配未使用的空间,每个元素的字节大小为 elsize。空间应初始化为所有位 0。

      【讨论】:

      • 谢谢普拉松。我发现从现在开始,每当我使用 malloc 时,我都必须使用 calloc。
      【解决方案4】:

      malloc 分配的内存内容(以及在堆栈上分配的变量)是未定义的,所以它很可能是任何东西。通常你会得到用零填充的空间(因为操作系统会清除其他进程使用的内存页面)或之前使用这些内存页面的残留物(如果内存页面属于你的进程,这通常是这种情况),但这是幕后发生的事情,C 标准不提供任何保证。

      所以,一般来说,没有“默认值”,也没有办法检查你的记忆是否已经改变;但是,您可以使用您确定不会用作“真实数据”的魔法值来初始化您使用的内存块,但这只是您的应用程序内部的约定。

      幸运的是,对于浮点变量,您可以使用几个神奇的值,例如安静的 NaN;一般来说,您可以使用&lt;math.h&gt; 中定义的宏NANfloat 设置为NaN。

      顺便说一句,您不应该阅读未初始化的 floats 和 doubles,因为它们存储的常用格式 (IEEE 754) 包含一些可能引发算术异常的魔法值(如信号 NaN)当它们被读取时,因此如果您未初始化的内存恰好包含这种位模式,您的应用程序可能会崩溃。

      【讨论】:

      • +1,一个疑问:你说'os blanks memory pages used by other proc'是这样吗?我的意思是为什么操作系统应该费心将长内存范围设置为零。有什么(明显的)原因吗?
      • @Vikram.exe:假设您有一个处理信用卡号码的应用程序;如果您释放的内存页面不会被完全不相关的进程所触及,您会高兴吗?
      • 不,我不会,所以我会自己明确地取消设置内存内容(来自我的程序)。底层操作系统不会。正确的?操作系统执行此类(可能是不必要的)操作会产生额外的开销。
      • @Vikram.exe:AFAIK 所有现代抢占式操作系统都这样做(或者,至少,Tanenbaum :) 这么说); IIRC 它是一个低优先级线程,当没有更好的事情可做(或需要它们时)时,它会将未使用的页面清空。请记住,内存页面不仅在您释放内存时会被重用,而且在内存不足且操作系统需要换出您的内存页面以将物理 RAM 提供给需要它的另一个进程时;您的进程没有任何机会自行清理敏感数据(也因为任务切换对应用程序是透明的)。
      【解决方案5】:

      扩展 Matteo Italia 的好答案:

      单个数组的初始化代码如下:

      float* row;
      
      row = malloc( numNodes*sizeof(float) );
      for (int i=0; i<numNodes; ++i) {
          row[i] = nanf(); // set a Not-a-Number magic value of type float
      }
      

      (我会让你为你的多维数组改变这个)

      然后某处:

      float value = ...; // read the array
      if (isnan(value)) {
          // not initialized
      } else {
          // initialized - do something with this
      }
      

      记住一点很重要:NaN == NaN 会产生错误,所以最好使用isnan(),而不是== 来测试这个值是否存在。

      【讨论】:

      • 哦,处理神奇的 fp 值总是很有趣 :)
      猜你喜欢
      • 2012-10-03
      • 1970-01-01
      • 1970-01-01
      • 2023-03-29
      • 2014-05-15
      • 1970-01-01
      • 2017-04-26
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多