C 用零值而不是随机内存声明结构?

C 用零值而不是随机内存声明结构?,c,C,我有一个这样的结构: typedef struct string { unsigned long length; unsigned *data; } string; 我可以写点什么吗?这样当我这样做的时候: string s; length属性是零,而不是内存中发生的任何内容数据工作正常,因为它预设为零或空指针 现在发生的情况的示例: string s; printf("length: %lu\n", s.length); printf("pointer: %lu\n", (unsig

我有一个这样的结构:

typedef struct string {
 unsigned long length;
 unsigned *data;
} string;
我可以写点什么吗?这样当我这样做的时候:

string s;
length
属性是零,而不是内存中发生的任何内容<代码>数据工作正常,因为它预设为零或空指针

现在发生的情况的示例:

string s;
printf("length:  %lu\n", s.length);
printf("pointer: %lu\n", (unsigned long) s.data);
结果:

length:  140737488347584
pointer: 0
我不想为了将
length
设置为零而对每个新字符串调用初始化函数

更多信息

现在我考虑一下,在我的特殊情况下,可能没有必要这样做(尽管这样做很好),因为大多数人最初会通过
ctou
(从char-pointer导入UTF-8)设置字符串,并且该函数会将
长度设置为零。

您可以使用

string s = {0,NULL};
你可以用

string s = {0,NULL};
您可以使用宏“自动执行此操作”


您可以使用宏“自动执行此操作”

来组合前面的两个答案(某种程度上),我会定义如下

#define STRING_INITIALIZER {0, NULL}
.
.
string s = STRING_INITIALIZER;

顺便说一句,您的
struct
声明本身对于字符串来说看起来很奇怪。这不是我们在C语言中通常理解的字符串,而是一个动态的无符号数组,或者它实际上是一个字符串,然后它应该是
char*

,为了结合前面的两个答案(某种程度上),我定义如下

#define STRING_INITIALIZER {0, NULL}
.
.
string s = STRING_INITIALIZER;

顺便说一句,您的
struct
声明本身对于字符串来说看起来很奇怪。这不是我们在C语言中通常理解的字符串,而是一个动态的
无符号数组,或者它实际上是一个字符串,然后它应该是
char*

公认的答案回答了您提出的问题,但没有说明您是否应该这样做

字符串是一个类,具有类语义。对于每一条指令都有计数的内核代码,初始化器可能很好,但在应用程序代码中,静态初始化器丑陋且容易出错

可以用C编写类,stdio
文件
类型是一个极好的例子,下面是应用于字符串类的相同想法:

typedef struct {
  int length;
  char *data;
} String;

String *sopen() {
  String *s = malloc(sizeof(String));
  if(s) {
    s->length = 0;
    s->data = NULL;
  }
  return s;
}

int sclose(String *s) {
  free(s->data);
  free(s);
  return 0;
}

int main()
{
   String *s = sopen();
   return sclose(s);
}
出于隐喻的原因,我遵循了
文件*
函数名样式。是的,还有更多的代码。是的,您必须显式地取消分配结构;但是请注意,即使您在代码示例中指望
自动
类初始化,如果
数据
曾经分配过,您也不能指望离开作用域为您自动解除分配存储


这种方法还有一个优点,就是从类的用户中抽象出
数据的类型。由于对您真正想要使用的类型似乎有些困惑,这种灵活性可能会派上用场。

公认的答案回答了您提出的问题,但没有说明您是否应该这样做

字符串是一个类,具有类语义。对于每一条指令都有计数的内核代码,初始化器可能很好,但在应用程序代码中,静态初始化器丑陋且容易出错

可以用C编写类,stdio
文件
类型是一个极好的例子,下面是应用于字符串类的相同想法:

typedef struct {
  int length;
  char *data;
} String;

String *sopen() {
  String *s = malloc(sizeof(String));
  if(s) {
    s->length = 0;
    s->data = NULL;
  }
  return s;
}

int sclose(String *s) {
  free(s->data);
  free(s);
  return 0;
}

int main()
{
   String *s = sopen();
   return sclose(s);
}
出于隐喻的原因,我遵循了
文件*
函数名样式。是的,还有更多的代码。是的,您必须显式地取消分配结构;但是请注意,即使您在代码示例中指望
自动
类初始化,如果
数据
曾经分配过,您也不能指望离开作用域为您自动解除分配存储


这种方法还有一个优点,就是从类的用户中抽象出
数据的类型。由于对您真正想要使用的类型似乎有些困惑,这种灵活性可能会派上用场。

更好,但如果我可以在结构定义中设置一个选项来自动执行此操作,这将是最佳选择。对于可能使用此库的开发人员来说,每次都声明这样的新字符串可能没有那么好。
{0}
{0,NULL}
工作得更好。即使您更改了成员的实现和顺序,前一种方法仍然有效。如果您更改结构,后者会中断。更好的是,如果我可以在结构定义中设置一个选项来自动执行此操作,这将是最佳选择。对于可能使用此库的开发人员来说,每次都声明这样的新字符串可能没有那么好。
{0}
{0,NULL}
工作得更好。即使您更改了成员的实现和顺序,前一种方法仍然有效。如果您更改结构,后者将中断。这是一个Unicode结构,其中所有32位代码点全部存储在
数据中。
@Delan:啊,我明白了。然后我会根据你的需要选择
wchar\u t
uint32\u t
或者
uint32\u t
。为什么?在i386和amd64上,
int
都是32位值。另外,我不想要
wchar\u t
,因为这是一个16位的值。我刚刚在i686和x86\u 64上进行了测试,对我来说
wchar\u t
在这两种情况下都是32位宽的。使用另一种类型而不是
unsigned
更好地显示了您的意图,并明确了您的默认假设。但这是你的代码。愿便携性和健忘症之神咬你一口您应该对Unicode代码点使用
uint32\u t
,以确保不会使类型超过需要的大小。更重要的是,你应该使用
size\u t
而不是
unsigned long
来表示长度。它是一个Unicode结构,所有32位代码点都完整地存储在
数据中。@Delan:啊,我明白了。然后我会根据你的需要选择
wchar\u t
uint32\u t
或者
uint32\u t
。为什么?在i386和amd64上,
int
都是32位值。另外,我不想要
wchar\u t
,因为这是一个16位的值