【问题标题】:About default C struct values, what about this code?关于默认的 C 结构值,这段代码呢?
【发布时间】:2011-03-28 22:43:44
【问题描述】:

我正在尝试使用默认值创建结构。我不知道如何做到这一点,因为我看到的每个代码都是关于初始化的,我希望它以自然的方式......

struct stuff {
  int stuff_a = 1;
  int stuff_b = 2...
  ...and so on...
};

环顾四周,我发现了这个 (C++) 代码:

struct a{   a() : i(0), j(0) {};  INT i;   INT j;}

我从来没有见过这样的 C 语言。请帮助我理解它;我觉得挺好看的!

更新:等等,我在问 C !!!!为什么改变我的问题?如果这在 C 中是不可能的,就说...我不知道 C++,我不知道那是关于 C++...

【问题讨论】:

  • 这在 C 中是不可能的。也就是说,C 不支持默认初始化器。你可以在 C99 中实现在 C++ 中无法实现的各种效果,反之亦然,但你不能做你看起来正在做的事情,这就是你的编译器抱怨的原因。
  • 您可以通过将结构初始化为您想要的值并在每次创建结构时在“init”函数中进行复制来伪造它。在纯 C 中没有这样做的干净方法。此外,您可以使用执行分配的“工厂”创建对象并将其初始化为默认值。

标签: c struct


【解决方案1】:

如果你想一次性设置一个结构对象并且你有一个 C99 编译器,试试这个:

struct stuff {
    int stuff_a;
    int stuff_b;
    // and so on...
};

struct stuff foo;
/* ... code ... */
foo = (struct stuff){.stuff_b = 42, .stuff_a = -1000};

否则,使用 C89 编译器,您必须一个一个地设置每个成员:

foo.stuff_b = 42;
foo.stuff_a = -1000;

运行示例@ideone:http://ideone.com/1QqCB


原行

struct a{   a() : i(0), j(0) {}   INT i;   INT j;}

是 C 中的语法错误。

【讨论】:

  • 我认为这是一个很好的答案,尤其是因为它在 C99 中演示了类似的语法。
  • 那里的语法非常性感!为我的教育 +1!
  • 由于 foo 不是指向 struct foo 的指针,我认为在分配值时不需要强制转换。
  • 不幸的是,你确实需要那里的演员表——这有点令人困惑。 typedef struct { int stuff_a; int stuff_b; } 东西;东西 foo = (东西) {.stuff_b = 42, .stuff_a = -1000}; // 如果 (Stuff) 类型转换不存在则错误 printf("stuff_a: %i, stuff_b: %i \n",foo.stuff_a, foo.stuff_b);
【解决方案2】:

正如您可能从其他答案中了解到的那样,在 C 中您不能同时声明一个结构并初始化它的成员。这些是不同的任务,必须分开完成。

初始化结构的成员变量有几个选项。我将在下面展示几种方法。现在,我们假设在文件开头定义了以下结构

struct stuff {
  int stuff_a;
  int stuff_b;
};

然后在您的 main() 代码中,假设您想要声明一个这种类型的新变量:

struct stuff custom_var;

这是您必须初始化结构的时刻。说真的,我的意思是你真的必须!即使您不想为它们分配特定值,也必须至少将它们初始化为零。这是强制性的,因为操作系统不保证它会给你一个干净的内存空间来运行你的应用程序。因此,始终将变量初始化为某个值(通常为 0),包括其他默认类型,例如 char、int、float、double 等...

将我们的结构初始化为零的一种方法是通过memset()

memset(&custom_var, 0, sizeof(struct stuff));

另一个是单独访问每个成员:

custom_var.stuff_a = 0;
custom_var.stuff_b = 0;

第三种可能会让初学者感到困惑的选项是当他们看到结构成员的初始化在声明的那一刻完成时:

struct stuff custom_var = { 1, 2 };

上面的代码相当于:

struct stuff custom_var;
custom_var.stuff_a = 1;
custom_var.stuff_b = 2;

【讨论】:

    【解决方案3】:

    ...创建具有默认值的结构...

    这在 C 中是不可能的。类型不能有默认值。任何类型的对象都不能有除 0 以外的默认值,尽管它们可以初始化为任何需要的值。
    struct 的定义是类型的定义,而不是对象的定义。


    您的要求与将ints 默认设置为 42 的方法大致相同。

    /* WRONG CODE -- THIS DOES NOT WORK */
    typedef int int42 = 42;
    int42 a;
    printf("%d\n", a); /* print 42 */
    

    或者,适应你的例子

    /* WRONG CODE -- THIS DOES NOT WORK */
    struct stuff {
        int42 stuff_a;
        int65536 stuff_b;
    }
    struct stuff a;
    printf("%d\n", a.stuff_b); /* print 65536 */
    

    【讨论】:

    • 关于类型的优点,一般来说,在 C 中没有默认值。
    【解决方案4】:

    更新:此答案假设我们在谈论 C++,因为答案中发布的代码不是合法的 C。

     struct a {
         a() : i(0), j(0) {}   // constructor with initialization list
         int i;
         int j;
     }
    

    用注释标记的行只是struct a 实例的构造函数(提醒:结构就像类,除了默认成员可见性是public 而不是private)。

    : 之后的部分称为初始化列表:它允许您使用值(常量或作为构造函数参数传递)初始化struct 的成员。此列表中的成员的初始化发生在输入构造函数的主体之前。如果可能的话,以这种方式初始化类和结构的成员是preferable

    另见C++: Constructor versus initializer list in struct/class

    【讨论】:

    • 构造函数也是我的第一个想法——但这在 c 中有效吗?在 Ideone 中,当我使用 C 编译器时,它不会:Ideone。如果我克隆它并作为 C++ 执行它,它就可以工作。
    • 同意,我认为你的回答现在也更有说服力了。
    • 但它现在是问题的答案吗?是标记错误还是提问者需要一个 C 解决方案,因为它之前被标记了?
    • 等等,我在问C!!!!为什么改变我的问题?如果这在 C 中是不可能的,那就说...我不知道 C++,我不知道那是关于 C++...
    • 谢谢 MacGucky,我的问题是关于 C,感谢所有回答我的人,但它是关于 C...我不想使用 C++,但是谢谢,现在我知道了该代码是...
    【解决方案5】:

    在 C(C99 之前)中,以下内容也有效:

    #include <stdio.h>
    typedef struct
    {
        int a;  
        int b;
        int c;
     } HELLO;
    
    int main()
    {
    HELLO a = {1,2,3};
    
    printf("here: %d %d %d\n",a.a,a.b,a.c);
    exit(1);
    }
    

    codepad

    【讨论】:

      【解决方案6】:

      我不太确定您的问题是什么。在 c 中初始化结构的标准方法是这样的:

      struct a_struct my_struct = {1, 2};
      

      或者更新更安全的:

      struct a_struct my_struct = {.i1 = 1, .i2 = 2};
      

      如果结构有多个实例,或者需要重新初始化,则使用默认值定义一个常量结构然后分配它是很有用的。

      typedef struct a_struct {
         int i1;
         int i2;
      } sa;
      
      static const sa default_sa = {.i1 = 1, .i2 = 2};
      
      static sa sa1 = default_sa;
      static sa sa2 = default_sa;
      
      // obviously you can do it dynamically as well
      void use_temp_sa(void)
      {
           sa temp_sa = default_sa;
           temp_sa.i2 = 3;
           do_something_with(&temp_sa);
      }
      
      // And re-initialise
      void reset_sa(sa *my_sa)
      {
          *my_sa = default_sa;
      }
      

      【讨论】:

        【解决方案7】:

        类型初始化器在 C 中是不可能的。

        • 必须在内存中存储一​​个值。
        • 一个类型不占用内存,占用内存的是那个类型的变量。

          struct stuff; 是一个类型;不占内存

          struct stuff aStuff; 是该类型的变量; aStuff占用内存

        • 因为一个类型不占用内存,it is not possible to save values into a type

        • 1234563如果此功能可用,这将导致 C 效率较低。
        • 您需要多久保留一次此默认值?我认为这不太可能。您可以创建一个函数来使用默认值初始化变量,或者只使用您想要的值初始化每个字段。所以类型初始化器不是基本的东西。 C is about simplicity.

        【讨论】:

          【解决方案8】:

          无法在结构定义中初始化值。

          我建议:

          typedef struct {
             int stuff_a;
             int stuff_b;
          } stuff ;
          
          int stuffInit(int a, int b, stuff *this){
             this->stuff_a = a;
             this->stuff_b = b;
             return 0; /*or an error code, or sometimes '*this', per taste.*/
          }
          
          
          int main(void){
             stuff myStuff;
             stuffInit(1, 2, &myStuff);
          
             /* dynamic is more commonly seen */
             stuff *dynamicStuff;
             dynamicStuff = malloc(sizeof(stuff));  /* 'new' stuff */
             stuffInit(0, 0, dynamicStuff);
             free(dynamicStuff);                    /* 'delete' stuff */
          
             return 0;
          }
          

          在面向对象编程 (C++) 时代之前,我们学习的是“抽象数据类型”。

          纪律说“永远不要直接访问你的数据结构,总是为它创建一个函数”但这只是由程序员、讲师或高级开发人员强制执行的,而不是语言。

          最终,结构定义和相应的函数最终在它们自己的文件和标题中,稍后链接,进一步封装设计。

          但是那些日子已经一去不复返了,取而代之的是“类”和“构造函数”OOP 术语。

          “都是一样的,只是名字变了”——邦乔维。

          【讨论】:

          • 对于 C,这是您最好的选择。您必须记录 API,以便用户知道他们需要正确初始化该类型的变量。那些日子并没有“过去”;它们仍在使用中,但使用范围缩小了。打开任何操作系统的内核代码,查看嵌入式系统,甚至查看 GNOME 之类的东西。都是 C。但正如 C 的表现力是一个飞跃一样,C++ 之类的东西也是如此。
          猜你喜欢
          • 2010-10-19
          • 2012-11-22
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多