繁体   English   中英

为什么在使用指针初始化用户定义的结构时需要输入强制类型?

[英]Why do I need to type cast when initializing a user-defined structure using pointer?

我有这个结构定义:

typedef struct node_bst
{
  int data;
  struct node_bst *lchild;
  struct node_bst *rchild;
  struct node_bst *parent;
} node_bst;

我试图用这个创建一个指向结构的指针:

node_bst *root;

和像这样分配内存:

root= malloc(sizeof(node_bst));

现在,为了初始化其中的数据项,我尝试了这个语句(从通常的结构变量初始化中得到提示):

*root= {0, NULL, NULL, NULL};

但是编译器抛出了一个错误

错误:'{'标记之前的预期表达式

我查了一下,发现我需要像这样对它进行类型化:

*root= (node_bst) {0, NULL, NULL, NULL};

现在它工作正常,但我的问题是,为什么我需要这样做?

我希望编译器已经知道root是指向node_bst类型结构变量的指针。 那么为什么需要对rvalue进行类型转换呢?

另一件奇怪的事:

int *a= malloc(sizeof(int));
*a= 4;

这很好用。

没有铸造。

在这个声明中

*root = (node_bst) {0, NULL, NULL, NULL};

使用了所谓的复合文字(node_bst) {0, NULL, NULL, NULL} ,它对应于node_bst类型的对象,并且该对象被分配给对象*root

来自C标准(6.5.2.5复合文字)

3由带括号的类型名称后跟括号括起的初始值列表组成的post fi x表达式是复合文字。 它提供了一个未命名的对象,其值由初始化列表给出。

另一种方法是分配动态分配的对象的每个数据成员。 例如

root->data   = 0;
root->lchil  = NULL;
root->rchil  = NULL;
root->parent = NULL;

至于这个说法

*root= {0, NULL, NULL, NULL};

那么从C的角度看它是无效的。 您可以仅在声明中使用支撑初始化。

如果将程序编译为C ++程序,则该语句将有效。

这里使用的语法不是类型转换,而是复合文字 这些在C标准的 6.5.2.5节中定义:

3后缀表达式由带括号的类型名称后跟括号括起的初始值设定项列表组成,是一个复合文字 它提供了一个未命名的对象,其值由初始化列表给出。

分配给整个struct时,复合文字是必需的。

在这种情况下,您不需要此语法:

int *a= malloc(sizeof(int));
*a= 4;

由于*a类型为int4是一个简单的整型常量,可以直接赋值给*a

还要注意,涉及指针的事实是无关紧要的。 在这种情况下你需要做同样的事情:

node_bst root;
root= (node_bst){0, NULL, NULL, NULL};

这不同于:

node_bst root = {0, NULL, NULL, NULL};

前一种情况是赋值 ,而后者是初始化 初始化只能在定义变量时完成(甚至在函数外部),而赋值可以在任何时间完成。

初始化的语法(参见标准的6.7.9节)只允许括号括起的值列表,而赋值则需要复合文字。

此外,如注释中所述,您仍然可以在初始化中使用复合文字,复合文字的生命周期为当前范围,您可以使用其地址。

这是一个有趣的例子:

char *str = (char[]){ "My string" };
str[3] = 'S';

这里,复合文字正在被修改,这是允许的。 但是如果你这样做:

char *str = "My string";
str[3] = 'S';

您将尝试修改字符串文字,并且很可能会出现分段错误。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM