C 指针"type ** name"与作为参数的"type * name[]"



我有点困惑。下面是一个非常简单的示例:

#include <stdlib.h>
typedef struct 
{
  unsigned char one: 1;
  unsigned char two:1;
  unsigned char three: 1;
  unsigned char four: 1;
} nibble_bits;
typedef union
{
  unsigned char all : 4;
  nibble_bits bits;
} nibble;
void initArr(nibble ** arrLoc, unsigned int size)
{
  nibble * start = arrLoc[0];
  int i =0;
  for (i=0; i<size; i++)
    {
      start[i].all = 0;
    }
}
int main()
{
  nibble * fourNibbles = (nibble *) malloc(4 * sizeof(nibble));
  initArr(&fourNibbles,4);
}

这编译正常,没有警告。但是,当我更改main中的第一行时:

nibble * fourNibbles = (nibble *) malloc(4 * sizeof(nibble));

自:

nibble fourNibbles[4];

我得到以下信息:

警告: main.c: 在函数 'main' 中:main.c:150:警告:从不兼容的指针类型传递"initArr"的参数 1

运行时,我收到"总线错误 10"。

在我看来,这些行正在做同样的事情,除了 malloc 在堆上为数组分配空间,而数组声明在堆栈上。但是(我认为)无论哪种方式,"fourNibbles"都是"指向蚕食的指针"类型,因此"fourNibbles"的地址将是指向半字节的指针(nibble **)。

我在这里错过了什么?

这些甚至远不相同。这

nibble * fourNibbles = (nibble *) malloc(4 * sizeof(nibble));

声明一个指针fourNibbles,而这个

nibble fourNibbles[4];

声明一个数组。数组和指针是两个完全不同的东西,它们(在对象级别)没有任何共同点。试图在对象上下文(如&运算符)中互换使用它们只会导致灾难。在SO(搜索"数组指针差异")以及这个[事实上的标准] C常见问题解答中有很多关于这个主题的信息:http://c-faq.com/aryptr/index.html

不过,在您的代码中还有另一件事引起了人们的注意。您的职能

void initArr(nibble ** arrLoc, unsigned int size)

专门针对第一个变体进行定制,因为它需要一个指向指针的指针作为其第一个参数。如果您尝试强制指向第一个参数的数组指针(您已经有机会亲眼观察),它将不起作用。

然而,这里真正的问题是为什么你的initArr函数以如此奇怪的方式编写。此序列

void initArr(nibble ** arrLoc, unsigned int size)
{
  ...
  nibble * start = arrLoc[0];
  ...
    start[i].all = 0;

看起来很不寻常。为什么要将指针传递到指针而不是普通的单级指针?例如,你可以简单地做

void initArr(nibble *start, unsigned size)
{
  unsigned i;
  for (i = 0; i < size; ++i)
    start[i].all = 0;
}

此版本将称为

initArr(fourNibbles,4); /* note: no `&` operator */

它将与 malloc -ed 数组和显式声明的数组兼容。

附言在C语言中,一个更好的malloc习语是

nibble * fourNibbles = malloc(4 * sizeof *fourNibbles);

请注意,在此变体类型中,名称nibble仅提及一次。

您缺少数组的地址与在表达式中使用纯数组名称时变为的指针的类型不同。

那是:

int *a1 = ...;
int a2[] = { ... };
some_func(&a1);
some_func(&a2);

除非some_func()期望void *,否则不能正确。 第一个调用传递一个int ** — 指向int的指针;第二个调用传递一个int (*)[] — 指向int数组的指针。 从数组中删除&

但是,在代码中,问题更为复杂。 因为函数需要nibble **,所以你有问题。 你应该做的是通过一个nibble *

void initArr(nibble *arrLoc, unsigned int size)
{
    for (unsigned int i = 0; i < size; i++)
        start[i].all = 0;
}
int main(void)
{
    nibble *fourNibbles_1 = (nibble *) malloc(4 * sizeof(nibble));
    nibble fourNibbles_2[4];
    initArr(fourNibbles_1, 4);
    initArr(fourNubbles_2, 4);
    initArr(&fourNubbles_2[0], 4);
}

你的实际代码正在做一些非常奇怪的事情。 它造成的伤害程度可能取决于指针与nibble相比有多大。

相关内容

  • 没有找到相关文章

最新更新