Home > other >  Why doesn't a struct pointer later dereferenced not return the same value as a struct that wasn
Why doesn't a struct pointer later dereferenced not return the same value as a struct that wasn

Time:02-15

I came across this post discussing how to print file permissions from the stat library, but I'm confused on how the definition of the struct works.

When I've defined structs, I've always defined them like struct struct_type *name. But in the example the struct is defined like struct struct_type name (without being a pointer). From what I can tell, there should be two different ways to access the information depending on how you define the struct.

Option One Notation

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

Option Two Notation

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

BUT when I switch things from option one notation in the provided example to option two I get VERY different results. What is different about these two options? Isn't it effectively doing the same thing?

Example Code

Option One Notation Program

#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;
}

Option One Notation Output

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

Option Two Notation Program

#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;
}

Option Two Notation Output

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

CodePudding user response:

This is not an alternate notation

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

it is invalid code. You have created a pointer that doesnt point anywhere. It needs to point at an instance of a stat. Like this

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

or create one on the heap

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

In your 'second notation' example, once you did this

stat("filename", fileStat)

all bets were off. Stat has written data to an unspecified location. This results in 'Undefined Behavior'. You could be lucky and write to a location that cant be written to. In this case you program would abort immediately. Why is that lucky? well you would know something was wrong. The worst kind of behavior is that you end up writing to a location that's writable and is not being used for anything else at the moment. Your program will work and you will ship it, then a customer tries it with a file with a longer file name or after an OS upgrade or on a machine with a different amount of memory and 'boom' it gives wierd answers or dies. This is why langauges like Java, c#, go etc exist. So as not to get into this mess.

  • Related