-1

I have the following file structure. I am aware that a pointer needs allocated memory. File A is generated by DaVinci. The main is written by me.

// File A
typedef struct {
    int v1;
}s1;

struct s2{
    s1 *p1;
};

extern const struct s2 * const p3;  // Expr 1
#define untilp1() (*(&p3->p1))  // Expr 2

// File main
#include <stdio.h>
#include "FileA.h"
int main()
{
    int v2 = 10;
    untilp1()->v1 = v2;  // This line results in failure
    return 0;
}
    

Q1 - I don't understand the expression 1. Specifically, I do not understand the use of so many const keywords in expr 1. I am aware of the meaning of the term extern. In this case, I guess a constant pointer p3 is undefined, undeclared but the compiler knows it points to constant structure s2. Is this correct? Please elaborate if you can make it clearer.

Q2 - I do not understand expression 2. Specifically, I don't understand what's happening with (*(&p3->p2)). I know the meaning of #define. Please explain the expression in a detailed way.

Q3 - In general coding, I allocate memory e.g. using malloc before I declare using pointers. I am not sure how is this handled when these files are generated by DaVinci. But I haven't seen any of my colleagues using malloc etc. Does anyone know if I can allocate the value of v2 to v1 using p3 or untilp1()?

Thank You.

  • `// This line results in failure` what error do you get? – kiner_shah Nov 03 '21 at 10:42
  • 2
    `Expr 1` means `p3` is a `const` pointer to a `const struct s2`. Read more [here](https://stackoverflow.com/a/31331389/4688321). – kiner_shah Nov 03 '21 at 10:43
  • 3
    You might find this site interesting: [cdecl](https://cdecl.org/?q=const+struct+s2+*+const+p3%3B) – Gerhardh Nov 03 '21 at 10:45
  • 2
    `Expr 2` will replace the line `untilp1()->v1 = v2;` with `*(&p3->p1)->v1`. – kiner_shah Nov 03 '21 at 10:47
  • I am not sure what error you get, but `&p3->p1` doesn't make sense. I understand it as **"address of `p3` object pointing to `p1`"** (I don't know how to put this in words). Since `p3` is a pointer, I think `p3->p1` should work. – kiner_shah Nov 03 '21 at 10:48
  • 2
    `*(&p3->p1)` is just a confused way of writing `(p3->p1)`. The only reason for writing such code is that the programmer is unaware of operator precedence. This code base seems to have major code smell. – Lundin Nov 03 '21 at 10:49
  • Also `untilp1()->v1` results in even more operator precedence bugs because the macro isn't written as taught in the function-like macro chapter of your average beginner-level C programming book. – Lundin Nov 03 '21 at 10:53
  • BTW, using `p3->p1` without initializing `p3` (using `malloc`, etc.) can lead to error (segmentation fault probably) – kiner_shah Nov 03 '21 at 10:59
  • (a) Provide a URL or complete citation for “DaVinci”. There are multiple software packages using that name. (b) Asking multiple questions in one post is not proper Stack Overflow procedure. Some people may have an answer for one question, not another, and it results in scattered answers. Stack Overflow is intended to be a durable repository of questions and matched answers, so answers should be on point for future readers with the same question. Asking multiple questions muddles that. – Eric Postpischil Nov 03 '21 at 12:06
  • 1
    (c) `#define untilp1() *(&p3->p1)` is a badly designed definition for two reasons. One, `*(&p3->p1)` is equivalent to `p3->p1`, and no reason to use the former form is apparent. Two, it is very well known good practice to using surrounding parentheses in macros, as in `#define untilp1() (*(&p3->p1))`, to avoid problems with precedence where the macro is used, which is what happened in `untilp1()->v1 = v2;` that caused an error. (`->` is higher precedence than `*`, so it is parsed as `*((&p3->p1)->v1)`.) If that code was generated by DaVinci software, these call into question its quality. – Eric Postpischil Nov 03 '21 at 12:09

1 Answers1

0

Q1: p3 is a const pointer (meaning that the pointer itself may not be changed) to a const struct s2 meaning that the struct s2 can not be changed either.

Q2: *(&p3->p1) takes the address of struct p3's member p1 and then dereferences it. With that macro definition the assignment needs to be: (untilp1())->v1 = v2;. See Operator Precedence. My recommendation is to put the parantheses in the macro instead.

Q3: "In general coding" - I think that needs a separate question. It may be opinion based.

Demo

Ted Lyngmo
  • 93,841
  • 5
  • 60
  • 108
  • 1
    The recommendation should be to put surrounding parentheses in the macro definition, `#define untilp1() (*(&p3->p1))`, not to put surrounding parentheses around its use, `(untilp1())`. That is standard practice for avoiding bugs. OP says the file containing it is generated by DaVinci, but that should be examined to see if it can be changed. – Eric Postpischil Nov 03 '21 at 12:00
  • @EricPostpischil Oh, I thought the macro was given to OP who then used it incorrectly. Updated the answer. – Ted Lyngmo Nov 03 '21 at 12:06