2

I'm confused about the syntax of struct namect * within the function declarations of getinfo, makeinfo, showinfo and cleanup.

Normally I'd expect that a variable name would follow the asterisk ante-ceding "namect" to create a pointer to a structure namect. Does this simply mean that the argument passed to the function is a pointer to data of type struct namect?

// names3.c -- use pointers and malloc()
#include <stdio.h>
#include <string.h>   // for strcpy(), strlen()
#include <stdlib.h>   // for malloc(), free()
#define SLEN 81
struct namect {
    char * fname;  // using pointers
    char * lname;
    int letters;
};

void getinfo(struct namect *);        // allocates memory
void makeinfo(struct namect *);
void showinfo(const struct namect *);
void cleanup(struct namect *);        // free memory when done
char * s_gets(char * st, int n);

int main(void)
{
    struct namect person;

    getinfo(&person);
    makeinfo(&person);
    showinfo(&person);
    cleanup(&person);

    return 0;
}

void getinfo (struct namect * pst)
{
    char temp[SLEN];
    printf("Please enter your first name.\n");
    s_gets(temp, SLEN);
    // allocate memory to hold name
    pst->fname = (char *) malloc(strlen(temp) + 1);
    // copy name to allocated memory
    strcpy(pst->fname, temp);
    printf("Please enter your last name.\n");
    s_gets(temp, SLEN);
    pst->lname = (char *) malloc(strlen(temp) + 1);
    strcpy(pst->lname, temp);
}

void makeinfo (struct namect * pst)
{
    pst->letters = strlen(pst->fname) +
    strlen(pst->lname);
}

void showinfo (const struct namect * pst)
{
    printf("%s %s, your name contains %d letters.\n",
           pst->fname, pst->lname, pst->letters);
}

void cleanup(struct namect * pst)
{
    free(pst->fname);
    free(pst->lname);
}

char * s_gets(char * st, int n)
{
    char * ret_val;
    char * find;

    ret_val = fgets(st, n, stdin);
    if (ret_val)
    {
        find = strchr(st, '\n');   // look for newline
        if (find)                  // if the address is not NULL,
            *find = '\0';          // place a null character there
        else
            while (getchar() != '\n')
                continue;          // dispose of rest of line
    }
    return ret_val;
}
Clifford
  • 88,407
  • 13
  • 85
  • 165
  • See https://riptutorial.com/c/example/4467/typedef-structs – Alexander May 20 '21 at 16:30
  • What specifically are you confused about: The syntax of a pointer to a structure? Or the difference between a pointer to a mutable structure vs a pointer to a non-mutable (const) structure? Both should be covered in [a decent text on C](https://stackoverflow.com/questions/562303/the-definitive-c-book-guide-and-list), including the reasons and situations to use both. – WhozCraig May 20 '21 at 16:32
  • i'm just confused as to why 'void getinfo(struct namect *); ' isnt ' void getinfo(struct namect * pointer_name);' – amsdecember May 20 '21 at 16:34
  • In C, argument types are required, but the formal argument names need only be specified where actually used. They are not "used" in the prototype (usually) and thus not required. This is [generally bad form](https://stackoverflow.com/questions/8174886/put-name-of-parameters-in-c-function-prototypes), but it doesn't stop most engineers I know from doing it regardless. There are even compilers that will warn you about unused arguments if you specify their names in the function implementations, but then don't actually use them in the function bodies (effectively an unreferenced var). – WhozCraig May 20 '21 at 16:41
  • @WhozCraig not necessarily bad, especially for user-defined types, as long is it very clear what the argument is used for. This seems to be one example of such non-bad usage. – SergeyA May 20 '21 at 16:47
  • @WhozCraig type matters not name. Warning can be issued only in the function definition – 0___________ May 20 '21 at 16:49
  • @0___________ Yeah, I know, thus the apparently cryptic : "argument types are required, but the formal argument names need only be specified where actually used." – WhozCraig May 20 '21 at 16:50
  • @WhozCraig Arguments cannot be used in function prototypes per definition. There is no way of using them there. – 0___________ May 20 '21 at 16:51
  • @0___________ why not? For example (with gcc extensions): `void foo(int k, typeof(k) );` – SergeyA May 20 '21 at 16:54
  • 1
    @0___________ Um.. oh yes they can. C support for VLAs is one example. `void foo(size_t N, size_t M, int arr[][N]);` – WhozCraig May 20 '21 at 16:55
  • @WhozCraig good point – 0___________ May 20 '21 at 18:02

3 Answers3

2

Since there is no typedef struct namect namect;, only struct namect exists. There is no namect.

Thus, const struct namect * is just a non-constant pointer to a constant struct namect.

Alexander
  • 59,041
  • 12
  • 98
  • 151
  • how does it answer the question? – 0___________ May 20 '21 at 16:46
  • I wrote this before OP's comment "i'm just confused as to why 'void getinfo(struct namect *); ' isnt ' void getinfo(struct namect * pointer_name);'" – Alexander May 20 '21 at 16:47
  • I still stand by this being a perfectly reasonable parsing of the quote "It's up to how you interpret "Normally I'd expect that a variable name would follow the asterisk ante-ceding "namect" to create a pointer to a structure namect. Does this simply mean that the argument passed to the function is a pointer to data of type struct namect?" – Alexander May 20 '21 at 16:48
2

void getinfo(struct namect *);

It is called function prototype and it informs the compiler that somewhere in the code there is a definition of the function called getinfo which takes one parameter of type "pointer to struct namect" and does not return anything.

This information compiler needs to call this function correctly.

i'm just confused as to why void getinfo(struct namect *); isnt void getinfo(struct namect * pointer_name);

The pointer_name is not required in the function prototype. But you can also declare it as

void getinfo(struct namect * pointer_name);

Both versions are correct.

0___________
  • 60,014
  • 4
  • 34
  • 74
  • @amsdecember in function prototype nothing. That name does not matter. Only the **type** is important – 0___________ May 20 '21 at 16:47
  • thank you. i'm typing too quickly and asking too many questions. your first clarified everything. – amsdecember May 20 '21 at 16:50
  • @amsdecember https://meta.stackoverflow.com/questions/294902/what-is-the-best-way-to-say-thank-you-to-stack-overflow – 0___________ May 20 '21 at 16:53
  • Minor correction needed: you mistakenly mention const in the description, but don't show it in the function prototype/declaration. It looks like only `showinfo` has `const`. – Gabriel Staples May 20 '21 at 16:57
  • 1
    @amsdecember Worth noting also that if you do name parameters in the prototype, they do not need to match those in the definition -only the type must match. That is not to say that it is a good idea though, but you may come across it, so worth knowing. – Clifford May 20 '21 at 18:53
0

Yes. The function declaration void getinfo(struct namect *); (for example) just says:

  1. The argument is a pointer to data of type struct namect.
  2. The argument name will be specified later in the function definition.

In void showinfo(const struct namect *);, the declaration says:

  1. Imagine a structure of type struct namect.
  2. Imagine a constant of the above type (once set, it can't be changed).
  3. Imagine a pointer to the above constant structure. (Note - the pointer isn't a constant, a slightly different syntax can make a pointer to be constant, I won't mention it here.)
  4. The argument name will be specified later in the function definition.
Dharman
  • 30,962
  • 25
  • 85
  • 135