为什么结构指针后来没有取消引用 return 与未定义为指针的结构相同的值?

Why doesn't a struct pointer later dereferenced not return the same value as a struct that wasn't defined as a pointer?

我遇到 this post 讨论如何从 stat 库打印文件权限,但我对结构的定义如何工作感到困惑。

当我定义结构时,我总是像 struct struct_type *name 那样定义它们。但在示例中,结构定义为 struct struct_type name(不是指针)。据我所知,根据您定义结构的方式,应该有两种不同的方式来访问信息。

选项一表示法

struct stat fileStat;           //definition of struct
stat("<filename>", &fileStat);  //execute the stat function
fileStat.member_name;           //access a member of a struct

选项二表示法

struct stat *fileStat;          //definition of struct
stat("<filename>", fileStat);   //execute the stat function
fileStat->member_name;          //access a member of a struct

但是当我将所提供示例中的选项一符号切换为选项二时,我得到了非常不同的结果。这两个选项有什么不同?它不是在有效地做同样的事情吗?

示例代码

选项一符号程序

#include <unistd.h>
#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>

int main(int argc, char **argv)
{
    struct stat fileStat;
    stat("main", &fileStat);

    printf("Information for %s\n", argv[1]);
    printf("---------------------------\n");
    printf("File Size: \t\t%lld bytes\n", fileStat.st_size);
    printf("Number of Links: \t%d\n", fileStat.st_nlink);
    printf("File inode: \t\t%llu\n", fileStat.st_ino);

    printf("File Permissions: \t");
    printf( (S_ISDIR(fileStat.st_mode)) ? "d" : "-");
    printf( (fileStat.st_mode & S_IRUSR) ? "r" : "-");
    printf( (fileStat.st_mode & S_IWUSR) ? "w" : "-");
    printf( (fileStat.st_mode & S_IXUSR) ? "x" : "-");
    printf( (fileStat.st_mode & S_IRGRP) ? "r" : "-");
    printf( (fileStat.st_mode & S_IWGRP) ? "w" : "-");
    printf( (fileStat.st_mode & S_IXGRP) ? "x" : "-");
    printf( (fileStat.st_mode & S_IROTH) ? "r" : "-");
    printf( (fileStat.st_mode & S_IWOTH) ? "w" : "-");
    printf( (fileStat.st_mode & S_IXOTH) ? "x" : "-");
    printf("\n\n");

    printf("The file %s a symbolic link\n", (S_ISLNK(fileStat.st_mode)) ? "is" : "is not");
    return 0;
}

选项一符号输出

Information for (null)
---------------------------
File Size:      49960 bytes
Number of Links:    1
File inode:         58527531
File Permissions:   -rwxr-xr-x

The file is not a symbolic link

选项二符号程序

#include <unistd.h>
#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>

int main(int argc, char **argv)
{
    struct stat *fileStat;
    stat("main", fileStat);

    printf("Information for %s\n", argv[1]);
    printf("---------------------------\n");
    printf("File Size: \t\t%lld bytes\n", fileStat->st_size);
    printf("Number of Links: \t%d\n", fileStat->st_nlink);
    printf("File inode: \t\t%llu\n", fileStat->st_ino);

    printf("File Permissions: \t");
    printf( (S_ISDIR(fileStat->st_mode)) ? "d" : "-");
    printf( (fileStat->st_mode & S_IRUSR) ? "r" : "-");
    printf( (fileStat->st_mode & S_IWUSR) ? "w" : "-"); 
    printf( (fileStat->st_mode & S_IXUSR) ? "x" : "-");
    printf( (fileStat->st_mode & S_IRGRP) ? "r" : "-");
    printf( (fileStat->st_mode & S_IWGRP) ? "w" : "-");
    printf( (fileStat->st_mode & S_IXGRP) ? "x" : "-");
    printf( (fileStat->st_mode & S_IROTH) ? "r" : "-");
    printf( (fileStat->st_mode & S_IWOTH) ? "w" : "-");
    printf( (fileStat->st_mode & S_IXOTH) ? "x" : "-");
    printf("\n\n");

    printf("The file %s a symbolic link\n", (S_ISLNK(fileStat->st_mode)) ? "is" : "is not");
    return 0;
}

选项二符号输出

Information for (null)
---------------------------
File Size:      5193343115435036343 bytes
Number of Links:    12487
File inode:         930377443599221576
File Permissions:   -r-x--x---

The file is not a symbolic link

这不是替代符号

struct stat *fileStat;          //definition of struct
stat("<filename>", fileStat);   //execute the stat function
fileStat->member_name;          //access a member of a struct

这是无效代码。您创建了一个不指向任何地方的指针。它需要指向一个统计实例。像这样

struct stat other_stat;
struct stat *fileStat;          //definition of struct
fileStat = &other_stat;       // make it point at the instance we just made
stat("<filename>", fileStat);   //execute the stat function
fileStat->member_name;          //access a member of a struct

或者在堆上创建一个

struct stat *fileStat = (struct stat*)malloc(sizeof(struct stat));
stat("<filename>", fileStat);   //execute the stat function
fileStat->member_name;          //access a member of a struct

在您的 'second notation' 示例中,一旦您这样做了

stat("filename", fileStat)

所有的赌注都落空了。 Stat 已将数据写入未指定的位置。这导致 'Undefined Behavior'。您可能很幸运,可以写入无法写入的位置。在这种情况下,您的程序将立即中止。为什么这么幸运?好吧,您会知道出了什么问题。最糟糕的行为是您最终写入了一个可写的位置,并且目前没有被用于其他任何地方。您的程序将运行并且您将发布它,然后客户使用具有更长文件名的文件或在 OS 升级后或在具有不同内存量的机器上尝试它并且 'boom' 它给出奇怪的答案或死亡。这就是 Java、c#、go 等语言存在的原因。以免惹上麻烦