简体   繁体   English

C'中结构的不同行为

[英]Different behaviour of struct in C'

I start learning C. It is fun.我开始学习C,挺好玩的。 But I came to the point when I was trying to play around with struct .但是当我尝试使用struct时,我已经到了关键点。 Below you have my program which I have created and I notice that behaviour of struct is different depend on how it was created.下面是我创建的程序,我注意到struct的行为因创建方式而异。

When I run the program below my output is surprising.当我运行下面的程序时,我的 output 令人惊讶。 Output: Output:

1. 1 0.000000 (some strange chars)
2. 0 0.000000 (null)

First of all like you can see the output of 1, 2 is different even if it is related to the same struct .首先就像你可以看到 1 的 output 一样,2 是不同的,即使它与相同的struct相关。 Second of all number 3 is not printed at all.第二个数字 3 根本没有打印。

I wonder why is that?我想知道这是为什么? I found on stackoverflow some explanation about the c struct but non of this post touch that issue.我在 stackoverflow 上找到了一些关于c struct的解释,但这篇文章没有涉及这个问题。 I was wonder if that is because of compiler?我想知道这是否是因为编译器? Or this is normal feature of C which I have to just understand?或者这是我必须了解的 C 的正常功能? Or do I have even think about it?还是我什至考虑过?

#include <stdio.h>

struct s1 {
  int int1;
  double double1;
  char *string;
} strc;

typedef struct {
  int int1;
  double double1;
  char *string;
} DStruct;

int main() {
  struct s1 defqu;
  DStruct defqu2;

  printf("1. %d %f %s\n", defqu.int1, defqu.double1, defqu.string);
  printf("2. %d %f %s\n", strc.int1, strc.double1, strc.string);
  printf("3. %d %f %s\n", defqu2.int1, defqu2.double1, defqu2.string);
  
  return 0;
}

You never initialized the instances you create, so it contains "garbage".您从未初始化您创建的实例,因此它包含“垃圾”。 Hence, you can expect "unexpected behavior":)因此,您可以期待“意外行为”:)

Change it to:将其更改为:


struct s1 {
  int int1;
  double double1;
  char *string;
} strc = {0};

typedef struct {
  int int1;
  double double1;
  char *string;
} DStruct;

int main() {
  struct s1 defqu = {0};
  DStruct defqu2 = {0};

  ...

The syntax = { 0 } initializes all the values in the struct to 0. From the C99 Standard:语法= { 0 }将结构中的所有值初始化为 0。来自 C99 标准:

If there are fewer initializers in a brace-enclosed list than there are elements or members of an aggregate, or fewer characters in a string literal used to initialize an array of known size than there are elements in the array, the remainder of the aggregate shall be initialized implicitly the same as objects that have static storage duration.如果大括号括起来的列表中的初始值设定项少于聚合的元素或成员,或者用于初始化已知大小数组的字符串文字中的字符少于数组中的元素,则聚合的其余部分应与具有 static 存储持续时间的对象一样被隐式初始化。

This will be better, but still not perfect.这样会更好,但仍不完美。 The numbers will all be initialized to 0, and the string pointers ( char * to be more accurate) will be initialized to NULL.数字将全部初始化为 0,字符串指针(更准确地说是char * )将初始化为 NULL。

Modern libc implementation will handle the NULL pointer you pass to %s gracefully, but that's actually undefined behavior as well.现代 libc 实现将优雅地处理您传递给%s的 NULL 指针,但这实际上也是未定义的行为。

strc is a global variable. strc是一个全局变量。 It's guaranteed(by C standard) to be initialized to zero.它保证(按 C 标准)初始化为零。 So all the members of strc will also be initialized to zero (including the string pointer).所以strc的所有成员也将被初始化为零(包括字符串指针)。 When you try to print the string in the second printf ( %s ), you invoke undefined behavior (dereferencing a null pointer).当您尝试在第二个 printf ( %s ) 中打印string时,您会调用未定义的行为(取消引用 null 指针)。 Most likely the program crashes/terminates when dereferencing a NULL pointer, but that's not guaranteed by the standard.当取消引用 NULL 指针时,程序很可能会崩溃/终止,但这不是标准所保证的。 Because, you know, it's undefined behavior!因为,你知道,这是未定义的行为!

defqu and defqu2 are local variables inside main function. Local variables are never auto-initialized in C. So they have some garbage value and can't be guaranteed to be zero like in the case of strc . defqudefqu2main function 中的局部变量。在 C 中,局部变量永远不会自动初始化。所以它们有一些垃圾值,不能像strc那样保证为零。 So the string pointer points to some random memory address and the first printf, most likely, printed the characters at that random memory location.因此, string指针指向某个随机地址 memory,而第一个 printf 最有可能在该随机 memory 位置打印字符。 You didn't see any output from the third printf because the program crashed/exited at the second printf because of the null dereference as explained above.您没有从第三个printf中看到任何 output,因为如上所述,由于 null 取消引用,程序在第二个printf崩溃/退出。 Move this printf to the end, you'll see the output for defqu2 too, but you can never be sure(because, undefined behavior!)将这个printf移到最后,你也会看到 defqu2 的defqu2 ,但你永远无法确定(因为,未定义的行为!)

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

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