【问题标题】:Why doesn't a struct pointer later dereferenced not return the same value as a struct that wasn't defined as a pointer?为什么后来取消引用的结构指针不返回与未定义为指针的结构相同的值?
【发布时间】:2022-02-15 05:32:21
【问题描述】:

我看到this 帖子讨论如何从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

【问题讨论】:

  • 您的“选项 2”显然是错误的。 fileStat 是未初始化的指针。
  • 在选项二中,您没有为 stat 结构分配空间。
  • 这与stat 无关。它只是基本的 C。struct stat *fileStat; 是一个未初始化的指针。访问任何未初始化的指针都会导致未定义的行为。将其与 &amp;fileStat 进行比较,后者也是一个指针,但它指向一个实际有效的内存块(fileStat 变量)。

标签: c pointers struct linked-list


【解决方案1】:

这不是替代符号

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

在你的“第二个符号”示例中,一旦你这样做了

stat("filename", fileStat)

所有赌注都取消了。 Stat 已将数据写入未指定的位置。这会导致“未定义的行为”。您可能会很幸运并写入无法写入的位置。在这种情况下,您的程序将立即中止。为什么这么幸运?好吧,您会知道出了点问题。最糟糕的行为是您最终写入一个可写的位置,并且目前没有用于其他任何事情。您的程序将工作并且您将交付它,然后客户使用具有更长文件名的文件或在操作系统升级后或在具有不同内存量的机器上尝试它并且“繁荣”它给出奇怪的答案或死亡。这就是为什么存在 Java、c#、go 等语言的原因。以免陷入这种混乱。

【讨论】:

  • 啊,是的,我知道我只是个白痴。谢谢。
猜你喜欢
  • 2013-01-04
  • 2011-02-04
  • 2017-02-24
  • 2017-06-17
  • 1970-01-01
  • 1970-01-01
  • 2013-07-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多