• C

C Programming: pointer dereferencing

I am so confused.


char   *gr_name;      // this is clearly a pointer

gid_t   gr_gid;           // this is clearly not a pointer

From my limited knowledge of C, I learned that if you have a struct such as:

struct group *grp  = getgrname(arg2); // arg2 is a group name

then, in order to call the members of a struct, you need to know if the members are pointers or not.

If it's a pointer, you should use arrows like (grp->gr_name)
If it's NOT a pointer, use a regular period like (grp.gr_gid)

If this is the case, why am I getting an error message:

Line 68: request for member gr_gid in something not a structure or union

#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <fcntl.h>
#include <string.h>
#include <stdio.h>
#include <pwd.h>
#include <grp.h>

static int writeLine(const char *b, const char *u, int filedes);
static char* readInput(const char *u, char buffer[]);
static char* getUser();
static int getFlag(const char *arg);
static void changePerm(const char* arg1, const int perm);
static int changeGroup(const char *arg1, const char *arg2);

int main( int argc, char *argv[] ) {

   int fd, chmod_returned, flag = -1;
   int max_input = 200;
   char buffer[max_input];

   // get command line args
   if(argc > 2) {
      flag = getFlag(argv[2]);
      if(argc == 3) {
        changeGroup(argv[1], argv[3]);
      if(flag == 1) { // y
        changePerm(argv[1], 0777);
      else if(flag == 0) { // n
        changePerm(argv[1], 0700);

   // get username
   char *myUser = getUser();

   //open file
   fd = open(argv[1], O_RDWR);

   while(1) {
     char *buf = readInput(myUser, buffer);
     if(writeLine(buf, myUser, fd) < 0)

// Change Group Membership
static int changeGroup(const char *arg1, const char *arg2) {
   struct group *grp;
   int chown_returned;
   gid_t grpID;

   if(arg2 == NULL || *arg2 == '\0')
      return -1;

   grp = getgrnam(arg2);
   if(grp == NULL) {
      perror("getgrnam() error");
      return -1;

   grpID = grp.gr_gid;

   if( (chown_returned = chown(arg1, -1, grpID)) == -1)
      perror("chown() error");

// Change Permissions
static void changePerm(const char* arg1, const int perm) {
   int chmod_returned;
   if( (chmod_returned = chmod(arg1, perm)) == -1)
      perror("chmod() error");

// Get Flag used (y or n)
static int getFlag(const char *arg) {
   if(*arg == 'y')
        return 1;
   else if(*arg == 'n')
        return 0;
        return -1;

static char* getUser() {
   struct passwd *mypasswd;
   char *mytty;

   if( (mypasswd = getpwuid(geteuid())) != NULL ) {
      char *user = mypasswd->pw_name;

      if(( mytty = ttyname(STDIN_FILENO)) == NULL)
         perror("ttyname() error");

      int userLen = strlen(user);
      int ttyLen = strlen(mytty);
      char *usr = malloc(sizeof(char) * (userLen + ttyLen + 5));

      strcpy(usr, user);
      strcat(usr, "@");
      strcat(usr, mytty);
      strcat(usr, ": ");

      return usr;

static char* readInput(const char *u, char buffer[]) {

   ssize_t bytes_read;
   size_t count = 200;

   //buffer[0] = '\0';
   //strcpy(b, "");
   //printf("%s", u);

   // display UserName
   if(write(STDOUT_FILENO, u, strlen(u)) < 0)
      perror("write() error");

   // read
   if(( bytes_read = read(STDIN_FILENO, buffer, count)) == -1) {
        perror("read() error");
   else if( bytes_read == 0) {
   else {

   //fgets(buffer, count, stdin);
   // append user input to *b string
   //strcat(b, u);
   //strcat(b, buffer);

   return buffer;

static int writeLine(const char *b, const char *u, int filedes) {
   size_t ulen, blen;

   blen = strlen(b);
   ulen = strlen(u);

   if(write(filedes, u, ulen) < 0 || write(filedes, b, blen) < 0 ) {
        perror("write() error");
        return -1;
   return 0;

Open in new window

Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

grp is a pointer. It is defined as a pointer. You could either use this:
grpID = grp->gr_gid;

Open in new window

or this:
grpID = *grp.gr_gid;

Open in new window

You are right phoffric. The brackets are required for the second case:
grpID = (*grp).gr_gid;

Open in new window

Hey MSSPs! What's your total cost of ownership?

WEBINAR: Managed security service providers often deploy & manage products from a variety of solution vendors. But is this really the best approach when it comes to saving time AND money? Join us on Aug. 15th to learn how you can improve your total cost of ownership today!

mccarlIT Business Systems Analyst / Software DeveloperCommented:
then, in order to call the members of a struct, you need to know if the members are pointers or not.
That's not quite true. It not the members of the struct that determine whether you use -> or . it is what ever you are accessing it with that determine this. In other words, in your example you have "grp.gr_gid" so it is whatever is on the left-hand side of that expression which determines which operator NOT what is on the right-hand side.

So the fact that you are accessing gr_gid, makes NO difference to which operator -> or . that you use. It is because grp is defined "struct group *grp" (ie. it is a pointer to a group structure) that you need to use -> as in "grpID = grp->gr_gid;"

On a different note...
gid_t   gr_gid;           // this is clearly not a pointer
Are you making that assertion because you KNOW how gid_t is defined? Or are you saying that because there is no * in that line?

In this case, it happens that you are right, that gid_t is not a pointer, but not because there is no * there. Consider the following code snippet...
typdef char *pChar;


pChar myVar;    // Here myVar IS a pointer even though you don't see an * on this line

Open in new window


Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
pzozulkaAuthor Commented:
Wow, thanks all for that educational lesson. I always thought you use -> or . based on the right-hand side. Glad this was cleared up. I'm clearly still learning C.
pzozulkaAuthor Commented:
Sorry forgot to ask one more question related to this:

So would I access both members the same way, even though one is a pointer and other isn't?

char   *gr_name;    
gid_t   gr_gid;        




It does not matter whether gr_name or gr_gid are pointers.
It matters whether grp is a pointer
mccarlIT Business Systems Analyst / Software DeveloperCommented:
Sorry forgot to ask one more question related to this
Isn't that just the same question?

So to repeat, yes they are both accessed in the same way because they are both accessed by "grp" (the left-hand side) which is a pointer, and so you use ->
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today

From novice to tech pro — start learning today.