Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.c > #162512 > unrolled thread

int(*const parse_packet)(const char *, size_t, char **);

Started by"hongy...@gmail.com" <hongyi.zhao@gmail.com>
First post2021-08-31 03:35 -0700
Last post2021-09-01 08:32 -0700
Articles 20 on this page of 22 — 12 participants

Back to article view | Back to comp.lang.c


Contents

  int(*const parse_packet)(const char *, size_t, char **); "hongy...@gmail.com" <hongyi.zhao@gmail.com> - 2021-08-31 03:35 -0700
    Re: int(*const parse_packet)(const char *, size_t, char **); Bonita Montero <Bonita.Montero@gmail.com> - 2021-08-31 12:59 +0200
      Re: int(*const parse_packet)(const char *, size_t, char **); "hongy...@gmail.com" <hongyi.zhao@gmail.com> - 2021-08-31 06:07 -0700
        Re: int(*const parse_packet)(const char *, size_t, char **); Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2021-08-31 08:01 -0700
    Re: int(*const parse_packet)(const char *, size_t, char **); Manfred <noname@add.invalid> - 2021-08-31 15:01 +0200
    Re: int(*const parse_packet)(const char *, size_t, char **); John Bode <jfbode1029@gmail.com> - 2021-08-31 16:08 -0500
      Re: int(*const parse_packet)(const char *, size_t, char **); "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> - 2021-08-31 14:32 -0700
        Re: int(*const parse_packet)(const char *, size_t, char **); Bart <bc@freeuk.com> - 2021-08-31 22:39 +0100
          Re: int(*const parse_packet)(const char *, size_t, char **); "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> - 2021-09-01 14:40 -0700
      Re: int(*const parse_packet)(const char *, size_t, char **); "hongy...@gmail.com" <hongyi.zhao@gmail.com> - 2021-08-31 18:21 -0700
        Re: int(*const parse_packet)(const char *, size_t, char **); Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2021-08-31 19:54 -0700
      Re: int(*const parse_packet)(const char *, size_t, char **); Kaz Kylheku <563-365-8930@kylheku.com> - 2021-09-01 05:07 +0000
        Re: int(*const parse_packet)(const char *, size_t, char **); "hongy...@gmail.com" <hongyi.zhao@gmail.com> - 2021-08-31 23:19 -0700
    Re: int(*const parse_packet)(const char *, size_t, char **); James Kuyper <jameskuyper@alumni.caltech.edu> - 2021-09-01 10:34 -0400
      Re: int(*const parse_packet)(const char *, size_t, char **); Bart <bc@freeuk.com> - 2021-09-01 16:22 +0100
        Re: int(*const parse_packet)(const char *, size_t, char **); "hongy...@gmail.com" <hongyi.zhao@gmail.com> - 2021-09-01 20:02 -0700
          Re: int(*const parse_packet)(const char *, size_t, char **); Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2021-09-01 21:01 -0700
            Re: int(*const parse_packet)(const char *, size_t, char **); "hongy...@gmail.com" <hongyi.zhao@gmail.com> - 2021-09-01 23:18 -0700
            Re: int(*const parse_packet)(const char *, size_t, char **); scott@slp53.sl.home (Scott Lurndal) - 2021-09-02 15:02 +0000
              Re: int(*const parse_packet)(const char *, size_t, char **); Lew Pitcher <lew.pitcher@digitalfreehold.ca> - 2021-09-02 15:24 +0000
          Re: int(*const parse_packet)(const char *, size_t, char **); Bart <bc@freeuk.com> - 2021-09-02 10:40 +0100
    Re: int(*const parse_packet)(const char *, size_t, char **); Paul N <gw7rib@aol.com> - 2021-09-01 08:32 -0700

Page 1 of 2  [1] 2  Next page →


#162512 — int(*const parse_packet)(const char *, size_t, char **);

From"hongy...@gmail.com" <hongyi.zhao@gmail.com>
Date2021-08-31 03:35 -0700
Subjectint(*const parse_packet)(const char *, size_t, char **);
Message-ID<83c10100-bedf-47eb-b595-7a8db983ac51n@googlegroups.com>
See the following c code snippet located at here [1]:

typedef struct protocol {
const int default_port;
int(*const parse_packet)(const char *, size_t, char **);
} protocol_t;

In the above definition, it seems to me that the `int ...' line is difficult to understand. Any hints will be highly appreciated.

[1] https://github.com/hongyi-zhao/shadowsocksr-libev/blob/1be671bd5fe7cd55d3823d4669786c9ba7913b9e/src/protocol.h#L29

Regards,
HY

[toc] | [next] | [standalone]


#162513

FromBonita Montero <Bonita.Montero@gmail.com>
Date2021-08-31 12:59 +0200
Message-ID<sgl23b$uh0$1@dont-email.me>
In reply to#162512
Am 31.08.2021 um 12:35 schrieb hongy...@gmail.com:
> See the following c code snippet located at here [1]:
> 
> typedef struct protocol {
> const int default_port;
> int(*const parse_packet)(const char *, size_t, char **);
> } protocol_t;
> 
> In the above definition, it seems to me that the `int ...' line is difficult to understand. Any hints will be highly appreciated.
> 
> [1] https://github.com/hongyi-zhao/shadowsocksr-libev/blob/1be671bd5fe7cd55d3823d4669786c9ba7913b9e/src/protocol.h#L29

That's just a pointer to a function that gets a const char *, a size_t
and a char ** and returns an int; you could assign a function-"name" to
it that returns an int and takes the same parameters in the same order.
For the above definition the parameters don't need to be named since
this isn't a function-definition, but just a variable-definition.

[toc] | [prev] | [next] | [standalone]


#162515

From"hongy...@gmail.com" <hongyi.zhao@gmail.com>
Date2021-08-31 06:07 -0700
Message-ID<b95e6981-068e-4abc-a446-6b913c522cd3n@googlegroups.com>
In reply to#162513
On Tuesday, August 31, 2021 at 7:00:07 PM UTC+8, Bonita Montero wrote:
> Am 31.08.2021 um 12:35 schrieb hongy...@gmail.com: 
> > See the following c code snippet located at here [1]: 
> > 
> > typedef struct protocol { 
> > const int default_port; 
> > int(*const parse_packet)(const char *, size_t, char **); 
> > } protocol_t; 
> > 
> > In the above definition, it seems to me that the `int ...' line is difficult to understand. Any hints will be highly appreciated. 
> > 
> > [1] https://github.com/hongyi-zhao/shadowsocksr-libev/blob/1be671bd5fe7cd55d3823d4669786c9ba7913b9e/src/protocol.h#L29
> That's just a pointer to a function that gets a const char *, a size_t 
> and a char ** and returns an int; you could assign a function-"name" to 
> it that returns an int and takes the same parameters in the same order. 
> For the above definition the parameters don't need to be named since 
> this isn't a function-definition, but just a variable-definition.

Do you mean this is something similar to lambda discussed here [1]?

[1] https://stackoverflow.com/questions/41700729/how-can-this-c-code-have-lambda

[toc] | [prev] | [next] | [standalone]


#162517

FromKeith Thompson <Keith.S.Thompson+u@gmail.com>
Date2021-08-31 08:01 -0700
Message-ID<878s0hirpk.fsf@nosuchdomain.example.com>
In reply to#162515
"hongy...@gmail.com" <hongyi.zhao@gmail.com> writes:
> On Tuesday, August 31, 2021 at 7:00:07 PM UTC+8, Bonita Montero wrote:
>> Am 31.08.2021 um 12:35 schrieb hongy...@gmail.com: 
>> > See the following c code snippet located at here [1]: 
>> > 
>> > typedef struct protocol { 
>> > const int default_port; 
>> > int(*const parse_packet)(const char *, size_t, char **); 
>> > } protocol_t; 
>> > 
>> > In the above definition, it seems to me that the `int ...' line is difficult to understand. Any hints will be highly appreciated. 
>> > 
>> > [1] https://github.com/hongyi-zhao/shadowsocksr-libev/blob/1be671bd5fe7cd55d3823d4669786c9ba7913b9e/src/protocol.h#L29
>> That's just a pointer to a function that gets a const char *, a size_t 
>> and a char ** and returns an int; you could assign a function-"name" to 
>> it that returns an int and takes the same parameters in the same order. 
>> For the above definition the parameters don't need to be named since 
>> this isn't a function-definition, but just a variable-definition.
>
> Do you mean this is something similar to lambda discussed here [1]?
>
> [1] https://stackoverflow.com/questions/41700729/how-can-this-c-code-have-lambda

It has some similarities to lambdas, but C doesn't have lambdas.  It's
best just to think of it as a function pointer (and learn what C
function pointers are if you don't already know).

-- 
Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
Working, but not speaking, for Philips
void Void(void) { Void(); } /* The recursive call of the void */

[toc] | [prev] | [next] | [standalone]


#162514

FromManfred <noname@add.invalid>
Date2021-08-31 15:01 +0200
Message-ID<sgl97j$1o4q$1@gioia.aioe.org>
In reply to#162512
On 8/31/2021 12:35 PM, hongy...@gmail.com wrote:
> See the following c code snippet located at here [1]:
> 
> typedef struct protocol {
> const int default_port;
> int(*const parse_packet)(const char *, size_t, char **);
> } protocol_t;
> 
> In the above definition, it seems to me that the `int ...' line is difficult to understand. Any hints will be highly appreciated.
> 
> [1] https://github.com/hongyi-zhao/shadowsocksr-libev/blob/1be671bd5fe7cd55d3823d4669786c9ba7913b9e/src/protocol.h#L29
> 
> Regards,
> HY
> 

That is a pointer-to-function declaration.
Declaring this pointer as member of struct protocol keeps it bound to 
the context of this structure.

Pointers to functions as struct members are often used as the C 
counterpart of what member functions are in C++, although their 
semantics would be somewhat different from this example.

[toc] | [prev] | [next] | [standalone]


#162520

FromJohn Bode <jfbode1029@gmail.com>
Date2021-08-31 16:08 -0500
Message-ID<sgm5pd$u9g$1@dont-email.me>
In reply to#162512
On 8/31/21 5:35 AM, hongy...@gmail.com wrote:
> See the following c code snippet located at here [1]:
> 
> typedef struct protocol {
> const int default_port;
> int(*const parse_packet)(const char *, size_t, char **);
> } protocol_t;
> 
> In the above definition, it seems to me that the `int ...' line is difficult to understand. Any hints will be highly appreciated.
> 
> [1] https://github.com/hongyi-zhao/shadowsocksr-libev/blob/1be671bd5fe7cd55d3823d4669786c9ba7913b9e/src/protocol.h#L29
> 
> Regards,
> HY
> 

When reading complex declarations, start by finding the leftmost
identifier and work your way out, remembering the following rules:

     T *ap[N];   // ap is an array of pointer to T
     T (*pa)[N]; // pa is a pointer to an array of T
     T *fp();    // fp is a function returning pointer to T
     T (*pf)();  // pf is a pointer to a function returning T

     T const *p; // p is a pointer to const T
     const T *p; // same as above

     T * const p; // p is a const pointer to T

Apply these rules recursively to any function parameters.  Given that,
this declaration breaks down as

             parse_packet                   -- parse_packet
     (*const parse_packet)                  -- is a const pointer to 

     (*const parse_packet)(             )   --   function taking
     (*const parse_packet)(             )   --     unnamed parameter
     (*const parse_packet)(           * )   --     is a pointer to
     (*const parse_packet)(const char * )   --       const char
     (*const parse_packet)(const char *,
                                        )   --     unnamed parameter
     (*const parse_packet)(const char *,
                           size_t       )   --     is a size_t
     (*const parse_packet)(const char *,
                           size_t,
                                        )   --     unnamed parameter
     (*const parse_packet)(const char *,
                           size_t,
                                *       )   --     is a pointer to
     (*const parse_packet)(const char *,
                           size_t,
                                **      )   --       a pointer to
     (*const parse_packet)(const char *,
                           size_t,
                           char **      )   --         char
int (*const parse_packet)(const char *,
                           size_t,
                           char **      )   --    returning int

In plain English, parse_packet is a const pointer to a function taking
three arguments of type const char *, size_t, and char **, and returning
an int.

[toc] | [prev] | [next] | [standalone]


#162521

From"Chris M. Thomasson" <chris.m.thomasson.1@gmail.com>
Date2021-08-31 14:32 -0700
Message-ID<sgm74u$eq6$1@gioia.aioe.org>
In reply to#162520
On 8/31/2021 2:08 PM, John Bode wrote:
> On 8/31/21 5:35 AM, hongy...@gmail.com wrote:
>> See the following c code snippet located at here [1]:
>>
>> typedef struct protocol {
>> const int default_port;
>> int(*const parse_packet)(const char *, size_t, char **);
>> } protocol_t;
>>
>> In the above definition, it seems to me that the `int ...' line is 
>> difficult to understand. Any hints will be highly appreciated.
>>
>> [1] 
>> https://github.com/hongyi-zhao/shadowsocksr-libev/blob/1be671bd5fe7cd55d3823d4669786c9ba7913b9e/src/protocol.h#L29 
>>
>>
>> Regards,
>> HY
>>
> 
> When reading complex declarations, start by finding the leftmost
> identifier and work your way out, remembering the following rules:
[...]

I must be misunderstanding you, however, I like to go from right to left:

struct foo const* const p = &foo;

p would be a constant pointer, to a constant foo structure.

[toc] | [prev] | [next] | [standalone]


#162522

FromBart <bc@freeuk.com>
Date2021-08-31 22:39 +0100
Message-ID<sgm7im$9lb$1@dont-email.me>
In reply to#162521
On 31/08/2021 22:32, Chris M. Thomasson wrote:
> On 8/31/2021 2:08 PM, John Bode wrote:
>> On 8/31/21 5:35 AM, hongy...@gmail.com wrote:
>>> See the following c code snippet located at here [1]:
>>>
>>> typedef struct protocol {
>>> const int default_port;
>>> int(*const parse_packet)(const char *, size_t, char **);
>>> } protocol_t;
>>>
>>> In the above definition, it seems to me that the `int ...' line is 
>>> difficult to understand. Any hints will be highly appreciated.
>>>
>>> [1] 
>>> https://github.com/hongyi-zhao/shadowsocksr-libev/blob/1be671bd5fe7cd55d3823d4669786c9ba7913b9e/src/protocol.h#L29 
>>>
>>>
>>> Regards,
>>> HY
>>>
>>
>> When reading complex declarations, start by finding the leftmost
>> identifier and work your way out, remembering the following rules:
> [...]
> 
> I must be misunderstanding you, however, I like to go from right to left:
> 
> struct foo const* const p = &foo;
> 
> p would be a constant pointer, to a constant foo structure.
> 

That doesn't work. Compare:

   const struct foo *p[];
   const struct foo (*p)[];

They can't both be array of pointer, and the 'const' shouldn't be at the 
end.

What about:

   int A[10][20];

Is is array 20 of array 10, or the other way around?

 >> When reading complex declarations, start by finding the leftmost
 >> identifier

This doesn't work either when there is no identifier (cast or unnamed 
parameter).

[toc] | [prev] | [next] | [standalone]


#162557

From"Chris M. Thomasson" <chris.m.thomasson.1@gmail.com>
Date2021-09-01 14:40 -0700
Message-ID<sgos0f$1jmo$1@gioia.aioe.org>
In reply to#162522
On 8/31/2021 2:39 PM, Bart wrote:
> On 31/08/2021 22:32, Chris M. Thomasson wrote:
>> On 8/31/2021 2:08 PM, John Bode wrote:
>>> On 8/31/21 5:35 AM, hongy...@gmail.com wrote:
>>>> See the following c code snippet located at here [1]:
>>>>
>>>> typedef struct protocol {
>>>> const int default_port;
>>>> int(*const parse_packet)(const char *, size_t, char **);
>>>> } protocol_t;
>>>>
>>>> In the above definition, it seems to me that the `int ...' line is 
>>>> difficult to understand. Any hints will be highly appreciated.
>>>>
>>>> [1] 
>>>> https://github.com/hongyi-zhao/shadowsocksr-libev/blob/1be671bd5fe7cd55d3823d4669786c9ba7913b9e/src/protocol.h#L29 
>>>>
>>>>
>>>> Regards,
>>>> HY
>>>>
>>>
>>> When reading complex declarations, start by finding the leftmost
>>> identifier and work your way out, remembering the following rules:
>> [...]
>>
>> I must be misunderstanding you, however, I like to go from right to left:
>>
>> struct foo const* const p = &foo;
>>
>> p would be a constant pointer, to a constant foo structure.
>>
> 
> That doesn't work. Compare:
> 
>    const struct foo *p[];

Its just a habit of mine. Basically, its similar to:

https://cseweb.ucsd.edu//~ricko/rt_lt.rule.html



>    const struct foo (*p)[];
> 
> They can't both be array of pointer, and the 'const' shouldn't be at the 
> end.
> 
> What about:
> 
>    int A[10][20];
> 
> Is is array 20 of array 10, or the other way around?
> 
>  >> When reading complex declarations, start by finding the leftmost
>  >> identifier
> 
> This doesn't work either when there is no identifier (cast or unnamed 
> parameter).

[toc] | [prev] | [next] | [standalone]


#162523

From"hongy...@gmail.com" <hongyi.zhao@gmail.com>
Date2021-08-31 18:21 -0700
Message-ID<7fc85399-c075-478a-b970-de43eb2ce8aan@googlegroups.com>
In reply to#162520
On Wednesday, September 1, 2021 at 5:09:13 AM UTC+8, jfbod...@gmail.com wrote:
> On 8/31/21 5:35 AM, hongy...@gmail.com wrote: 
> > See the following c code snippet located at here [1]: 
> > 
> > typedef struct protocol { 
> > const int default_port; 
> > int(*const parse_packet)(const char *, size_t, char **); 
> > } protocol_t; 
> > 
> > In the above definition, it seems to me that the `int ...' line is difficult to understand. Any hints will be highly appreciated. 
> > 
> > [1] https://github.com/hongyi-zhao/shadowsocksr-libev/blob/1be671bd5fe7cd55d3823d4669786c9ba7913b9e/src/protocol.h#L29 
> > 
> > Regards, 
> > HY 
> >
> When reading complex declarations, start by finding the leftmost 
> identifier and work your way out, remembering the following rules: 
> 
> T *ap[N]; // ap is an array of pointer to T 
> T (*pa)[N]; // pa is a pointer to an array of T 
> T *fp(); // fp is a function returning pointer to T 
> T (*pf)(); // pf is a pointer to a function returning T 
> 
> T const *p; // p is a pointer to const T 
> const T *p; // same as above 
> 
> T * const p; // p is a const pointer to T 

But cdecl [1-2] doesn't work with these rules, e.g.:

$ cdecl 
Type `help' or `?' for help
cdecl> explain T *ap[N]; 
syntax error
cdecl> 
 
But it works for the example discussed here:

cdecl> explain int(*const parse_packet)(const char *, size_t, char **); 
declare parse_packet as const pointer to function (pointer to const char, size_t, pointer to pointer to char) returning int

[1] https://github.com/ridiculousfish/cdecl-blocks
[2] https://github.com/paul-j-lucas/cdecl

HY

> Apply these rules recursively to any function parameters. Given that, 
> this declaration breaks down as 
> 
> parse_packet -- parse_packet 
> (*const parse_packet) -- is a const pointer to 
> 
> (*const parse_packet)( ) -- function taking 
> (*const parse_packet)( ) -- unnamed parameter 
> (*const parse_packet)( * ) -- is a pointer to 
> (*const parse_packet)(const char * ) -- const char 
> (*const parse_packet)(const char *, 
> ) -- unnamed parameter 
> (*const parse_packet)(const char *, 
> size_t ) -- is a size_t 
> (*const parse_packet)(const char *, 
> size_t, 
> ) -- unnamed parameter 
> (*const parse_packet)(const char *, 
> size_t, 
> * ) -- is a pointer to 
> (*const parse_packet)(const char *, 
> size_t, 
> ** ) -- a pointer to
> (*const parse_packet)(const char *, 
> size_t,
> char ** ) -- char 
> int (*const parse_packet)(const char *, 
> size_t, 
> char ** ) -- returning int 
> 
> In plain English, parse_packet is a const pointer to a function taking 
> three arguments of type const char *, size_t, and char **, and returning 
> an int.

[toc] | [prev] | [next] | [standalone]


#162524

FromKeith Thompson <Keith.S.Thompson+u@gmail.com>
Date2021-08-31 19:54 -0700
Message-ID<87wno1gg4l.fsf@nosuchdomain.example.com>
In reply to#162523
"hongy...@gmail.com" <hongyi.zhao@gmail.com> writes:
[...]
> But cdecl [1-2] doesn't work with these rules, e.g.:
>
> $ cdecl 
> Type `help' or `?' for help
> cdecl> explain T *ap[N]; 
> syntax error
> cdecl> 
[...]

cdecl's parser is relatively simple, certainly in comparison to the
parser in a C compiler.  In your example, it doesn't know what "T" or
"N" is, and isn't smart enough to assume that T is a type name and N is
a numeric constant.

It also treats certain English words (like "declare", "explain",
"pointer", "ptr", "array", "of", and "to") as keywords.  If I recall
correctly it uses a single grammar for its C-to-English and English-to-C
translations.

If you have a declaration with a named type, replace it with "int" or
"char" before feeding it to cdecl.  If you have a named constant like N,
replace it with an actual constant.

cdecl is quirky but useful.

$ cdecl
Type `help' or `?' for help
cdecl> explain T *ap[N]
syntax error
cdecl> explain int *ap[42]
declare ap as array 42 of pointer to int
cdecl> 

-- 
Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
Working, but not speaking, for Philips
void Void(void) { Void(); } /* The recursive call of the void */

[toc] | [prev] | [next] | [standalone]


#162527

FromKaz Kylheku <563-365-8930@kylheku.com>
Date2021-09-01 05:07 +0000
Message-ID<20210831215224.823@kylheku.com>
In reply to#162520
On 2021-08-31, John Bode <jfbode1029@gmail.com> wrote:
> On 8/31/21 5:35 AM, hongy...@gmail.com wrote:
>> See the following c code snippet located at here [1]:
>> 
>> typedef struct protocol {
>> const int default_port;
>> int(*const parse_packet)(const char *, size_t, char **);
>> } protocol_t;
>> 
>> In the above definition, it seems to me that the `int ...' line is difficult to understand. Any hints will be highly appreciated.
>> 
>> [1] https://github.com/hongyi-zhao/shadowsocksr-libev/blob/1be671bd5fe7cd55d3823d4669786c9ba7913b9e/src/protocol.h#L29
>> 
>> Regards,
>> HY
>> 
>
> When reading complex declarations, start by finding the leftmost
> identifier and work your way out, remembering the following rules:

When reading complex declarators, first consider any precedence
parentheses. Read these inside out.

Within every parenthesized grouping, consider what are the postfix type
constructors on the right, and the unary type constructors on the left.
The postfix constructors all have a higher precedence. All operators
proceed away from the thing being declared: postfix are
left-associative, unary are right-associative.

If there are no such parentheses, there is only one grouping.

E.g.

  (* ( **a[3][4] ) (int) )
  ^  ^           ^       ^
  |   ` inner par        `
  `                      '
   ` outer par ---------'


We start within the inner parens. The postix type constructor operators
are [3][4] and they apply in that order:

   a is an array of 3 elements, which are arrays of 4

Having dealt with postfix, we look at the lower-precedence unaries,
which indicate what a is an array of. There are two stars, so pointer to
pointer:

   a is an array of 3 elements, which are arrays of 4
   ... pointers to pointer

OK, we are done at this parenthesis level; we take the elevator
out one floor. The only postfix operator there is the function parameter
list declarator syntax (int):

   a is an array of 3 elements, which are arrays of 4
   ... pointers to pointer
   ... to a function that takes an int parameter, returning ...

Then we look at the unary: what the function returns:

   a is an array of 3 elements, which are arrays of 4
   ... pointers to pointer
   ... to a function that takes an int parameter, returning
   ... a pointer

We are now done with the declarator. We must look at the declaration
specifiers. For instance, if those are "struct foo".

   a is an array of 4 arrays of 3
   ... pointers to pointer
   ... to a function that takes an int parameter, returning
   ... a pointer
   ... to struct foo

The parentheses in a declarator prevent all of its postfix operators
from applying before all of its unaries; they are necessary precisely
when the type we are constructing is a sequence of constructions that
requires a mixing of unary and postfix type construction operators.

-- 
TXR Programming Language: http://nongnu.org/txr
Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal

[toc] | [prev] | [next] | [standalone]


#162528

From"hongy...@gmail.com" <hongyi.zhao@gmail.com>
Date2021-08-31 23:19 -0700
Message-ID<ed5882da-54e2-4aec-967d-67c89fe9d3c1n@googlegroups.com>
In reply to#162527
On Wednesday, September 1, 2021 at 1:07:14 PM UTC+8, Kaz Kylheku wrote:
> On 2021-08-31, John Bode <jfbod...@gmail.com> wrote: 
> > On 8/31/21 5:35 AM, hongy...@gmail.com wrote: 
> >> See the following c code snippet located at here [1]: 
> >> 
> >> typedef struct protocol { 
> >> const int default_port; 
> >> int(*const parse_packet)(const char *, size_t, char **); 
> >> } protocol_t; 
> >> 
> >> In the above definition, it seems to me that the `int ...' line is difficult to understand. Any hints will be highly appreciated. 
> >> 
> >> [1] https://github.com/hongyi-zhao/shadowsocksr-libev/blob/1be671bd5fe7cd55d3823d4669786c9ba7913b9e/src/protocol.h#L29 
> >> 
> >> Regards, 
> >> HY 
> >> 
> > 
> > When reading complex declarations, start by finding the leftmost 
> > identifier and work your way out, remembering the following rules:
> When reading complex declarators, first consider any precedence 
> parentheses. Read these inside out. 
> 
> Within every parenthesized grouping, consider what are the postfix type 
> constructors on the right, and the unary type constructors on the left. 
> The postfix constructors all have a higher precedence. All operators 
> proceed away from the thing being declared: postfix are 
> left-associative, unary are right-associative. 
> 
> If there are no such parentheses, there is only one grouping. 
> 
> E.g. 
> 
> (* ( **a[3][4] ) (int) ) 
> ^ ^ ^ ^ 
> | ` inner par ` 
> ` ' 
> ` outer par ---------' 
> 
> 
> We start within the inner parens. The postix type constructor operators 
> are [3][4] and they apply in that order: 
> 
> a is an array of 3 elements, which are arrays of 4 
> 
> Having dealt with postfix, we look at the lower-precedence unaries, 
> which indicate what a is an array of. There are two stars, so pointer to 
> pointer: 
> 
> a is an array of 3 elements, which are arrays of 4 
> ... pointers to pointer 
> 
> OK, we are done at this parenthesis level; we take the elevator 
> out one floor. The only postfix operator there is the function parameter 
> list declarator syntax (int): 
> 
> a is an array of 3 elements, which are arrays of 4 
> ... pointers to pointer 
> ... to a function that takes an int parameter, returning ... 
> 
> Then we look at the unary: what the function returns: 
> 
> a is an array of 3 elements, which are arrays of 4 
> ... pointers to pointer 
> ... to a function that takes an int parameter, returning 
> ... a pointer 
> 
> We are now done with the declarator. We must look at the declaration 
> specifiers. For instance, if those are "struct foo". 
> 
> a is an array of 4 arrays of 3 
> ... pointers to pointer 
> ... to a function that takes an int parameter, returning 
> ... a pointer 
> ... to struct foo 

See the explanation given by cdecl:

cdecl> explain struct foo (* ( **a[3][4] ) (int) ) 
declare a as array 3 of array 4 of pointer to pointer to function (int) returning pointer to struct foo

HY
 
> The parentheses in a declarator prevent all of its postfix operators 
> from applying before all of its unaries; they are necessary precisely 
> when the type we are constructing is a sequence of constructions that 
> requires a mixing of unary and postfix type construction operators. 
> 
> -- 
> TXR Programming Language: http://nongnu.org/txr 
> Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal

[toc] | [prev] | [next] | [standalone]


#162534

FromJames Kuyper <jameskuyper@alumni.caltech.edu>
Date2021-09-01 10:34 -0400
Message-ID<sgo32h$eal$2@dont-email.me>
In reply to#162512
On 8/31/21 6:35 AM, hongy...@gmail.com wrote:
> See the following c code snippet located at here [1]:
> 
> typedef struct protocol {
> const int default_port;
> int(*const parse_packet)(const char *, size_t, char **);
> } protocol_t;
> 
> In the above definition, it seems to me that the `int ...' line is difficult to understand. Any hints will be highly appreciated.

The key concept in C declarations is that declaration of a variable
mirrors the usages of that variable. This declaration contains one of
the key exceptions to that rule: "const char *, size_t, char **"
indicates that there's a function taking three arguments, which must be
implicitly convertible to the types specified in that list.

The first "const" is another violation of that principle: it indicates
that parse_packet is const-qualified.

When you ignore those two parts, that's where "declarations mirror
usage" finally comes in: "int (*parse_packet)()" indicates that
(*parse_packet)() is a valid expression with a type of int. If you're
familiar enough with C, that should tell you that *parse_packet must
identify a function, and that parse_packet itself must therefore be a
pointer to a function.

Combining that all together: parse_packet is a pointer to a function
that takes three arguments of types const char*, size_t, and char**
respectively, and returns a value of type int.

This leads to a tricky point. In C, an expression that designates a
function, such as *parse_packet, gets implicitly converted into a
pointer to a function. It used to be the case that function calls
required a function designator as their left operand, but when they
added the implicit conversion to a function pointer, they also changed
the semantics of function calls. The left operand of a function call is
now required to be a pointer to a function, rather than a function
designator, so it all works out. But that also means that the function
can be called directly: due to that implicit conversion,
(*parse_packet)(a, b, c) now has exactly the same meaning as
parse_packet(a, b, c), which is simpler. This change was made for the
sake of convenience, but it can also result in confusion: it means that
parse_packet, *parse_packet, **parse_packet and
***************parse_packet all have the same exact meaning.

[toc] | [prev] | [next] | [standalone]


#162535

FromBart <bc@freeuk.com>
Date2021-09-01 16:22 +0100
Message-ID<sgo5sp$63c$1@dont-email.me>
In reply to#162534
On 01/09/2021 15:34, James Kuyper wrote:
> On 8/31/21 6:35 AM, hongy...@gmail.com wrote:
>> See the following c code snippet located at here [1]:
>>
>> typedef struct protocol {
>> const int default_port;
>> int(*const parse_packet)(const char *, size_t, char **);
>> } protocol_t;
>>
>> In the above definition, it seems to me that the `int ...' line is difficult to understand. Any hints will be highly appreciated.
> 
> The key concept in C declarations is that declaration of a variable
> mirrors the usages of that variable. This declaration contains one of
> the key exceptions to that rule: "const char *, size_t, char **"
> indicates that there's a function taking three arguments, which must be
> implicitly convertible to the types specified in that list.
> 
> The first "const" is another violation of that principle: it indicates
> that parse_packet is const-qualified.
> 
> When you ignore those two parts, that's where "declarations mirror
> usage" finally comes in: "int (*parse_packet)()" indicates that
> (*parse_packet)() is a valid expression with a type of int. If you're
> familiar enough with C, that should tell you that *parse_packet must
> identify a function, and that parse_packet itself must therefore be a
> pointer to a function.
> 
> Combining that all together: parse_packet is a pointer to a function
> that takes three arguments of types const char*, size_t, and char**
> respectively, and returns a value of type int.
> 
> This leads to a tricky point. In C, an expression that designates a
> function, such as *parse_packet, gets implicitly converted into a
> pointer to a function. It used to be the case that function calls
> required a function designator as their left operand, but when they
> added the implicit conversion to a function pointer, they also changed
> the semantics of function calls. The left operand of a function call is
> now required to be a pointer to a function, rather than a function
> designator, so it all works out. But that also means that the function
> can be called directly: due to that implicit conversion,
> (*parse_packet)(a, b, c) now has exactly the same meaning as
> parse_packet(a, b, c), which is simpler. This change was made for the
> sake of convenience, but it can also result in confusion: it means that
> parse_packet, *parse_packet, **parse_packet and
> ***************parse_packet all have the same exact meaning.
> 

I made changes to my own systems language yesterday to relax the need 
for explicit derefs for things like function pointers.

I was worried that, as well as resulting in some loss of transparency in 
code (F in F() could be a function, or a pointer to a function), it 
would inherit C's problems where you can add arbitrary number of derefs 
and it would still work.

But apparently not. The example here would be declared as:

    ref function(ref char, int, ref ref char)=>int parse_packet

and can be called as either of:

    parse_packet(x,y,z)
    parse_packet^(x,y,z)      # ^ is post-fix deref op

but not as:

    parse_packet^^(x,y,z)     # or ^^^ etc

It uses a different approach: if the F in F() (or A[i] or P.m) is not 
the right type, but is a pointer type, it will try dereferencing until 
it is. Then it will insert those deref ops into the AST, so that the 
first call above is, internally, always:

    parse_packet^(x,y,z)

So fewer derefs are OK (it will match my dynamic code), but not more.

[toc] | [prev] | [next] | [standalone]


#162567

From"hongy...@gmail.com" <hongyi.zhao@gmail.com>
Date2021-09-01 20:02 -0700
Message-ID<18381f9e-e544-40cc-b87b-7349a8fdc925n@googlegroups.com>
In reply to#162535
On Wednesday, September 1, 2021 at 11:23:19 PM UTC+8, Bart wrote:
> On 01/09/2021 15:34, James Kuyper wrote: 
> [...]
> I made changes to my own systems language yesterday to relax the need 
> for explicit derefs for things like function pointers. 
> 
> I was worried that, as well as resulting in some loss of transparency in 
> code (F in F() could be a function, or a pointer to a function), it 
> would inherit C's problems where you can add arbitrary number of derefs 
> and it would still work. 
> 
> But apparently not. The example here would be declared as: 
> 
> ref function(ref char, int, ref ref char)=>int parse_packet 
> 
> and can be called as either of: 
> 
> parse_packet(x,y,z) 
> parse_packet^(x,y,z) # ^ is post-fix deref op 
> 
> but not as: 
> 
> parse_packet^^(x,y,z) # or ^^^ etc 
> 
> It uses a different approach: if the F in F() (or A[i] or P.m) is not 
> the right type, but is a pointer type, it will try dereferencing until 
> it is. Then it will insert those deref ops into the AST, so that the 
> first call above is, internally, always: 

What's the meaning of AST?
 
> parse_packet^(x,y,z) 
> 
> So fewer derefs are OK (it will match my dynamic code), but not more.

[toc] | [prev] | [next] | [standalone]


#162570

FromKeith Thompson <Keith.S.Thompson+u@gmail.com>
Date2021-09-01 21:01 -0700
Message-ID<87eea7hbhz.fsf@nosuchdomain.example.com>
In reply to#162567
"hongy...@gmail.com" <hongyi.zhao@gmail.com> writes:
> On Wednesday, September 1, 2021 at 11:23:19 PM UTC+8, Bart wrote:
>> On 01/09/2021 15:34, James Kuyper wrote: 
>> [...]
>> I made changes to my own systems language yesterday to relax the need 
>> for explicit derefs for things like function pointers. 
>> 
>> I was worried that, as well as resulting in some loss of transparency in 
>> code (F in F() could be a function, or a pointer to a function), it 
>> would inherit C's problems where you can add arbitrary number of derefs 
>> and it would still work. 
>> 
>> But apparently not. The example here would be declared as: 
>> 
>> ref function(ref char, int, ref ref char)=>int parse_packet 
>> 
>> and can be called as either of: 
>> 
>> parse_packet(x,y,z) 
>> parse_packet^(x,y,z) # ^ is post-fix deref op 
>> 
>> but not as: 
>> 
>> parse_packet^^(x,y,z) # or ^^^ etc 
>> 
>> It uses a different approach: if the F in F() (or A[i] or P.m) is not 
>> the right type, but is a pointer type, it will try dereferencing until 
>> it is. Then it will insert those deref ops into the AST, so that the 
>> first call above is, internally, always: 
>
> What's the meaning of AST?

https://www.google.com/search?q=parse+AST

>> parse_packet^(x,y,z) 
>> 
>> So fewer derefs are OK (it will match my dynamic code), but not more.

-- 
Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
Working, but not speaking, for Philips
void Void(void) { Void(); } /* The recursive call of the void */

[toc] | [prev] | [next] | [standalone]


#162574

From"hongy...@gmail.com" <hongyi.zhao@gmail.com>
Date2021-09-01 23:18 -0700
Message-ID<3e5d6a8b-3b40-4106-ac96-bbbd2fe62357n@googlegroups.com>
In reply to#162570
On Thursday, September 2, 2021 at 12:01:24 PM UTC+8, Keith Thompson wrote:
> [...]
> > What's the meaning of AST?
> https://www.google.com/search?q=parse+AST

It led me here:

https://en.wikipedia.org/wiki/Abstract_syntax_tree

HY

[toc] | [prev] | [next] | [standalone]


#162585

Fromscott@slp53.sl.home (Scott Lurndal)
Date2021-09-02 15:02 +0000
Message-ID<rI5YI.3385$d82.2643@fx21.iad>
In reply to#162570
Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:
>"hongy...@gmail.com" <hongyi.zhao@gmail.com> writes:

>> What's the meaning of AST?
>
>https://www.google.com/search?q=parse+AST
>

As an old VAX programmer, AST was 'Asynchronous System Trap' :-).

[toc] | [prev] | [next] | [standalone]


#162586

FromLew Pitcher <lew.pitcher@digitalfreehold.ca>
Date2021-09-02 15:24 +0000
Message-ID<sgqqas$gun$1@dont-email.me>
In reply to#162585
On Thu, 02 Sep 2021 15:02:47 +0000, Scott Lurndal wrote:

> Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:
>>"hongy...@gmail.com" <hongyi.zhao@gmail.com> writes:
> 
>>> What's the meaning of AST?
>>
>>https://www.google.com/search?q=parse+AST
>>
> 
> As an old VAX programmer, AST was 'Asynchronous System Trap' :-).

My IBM mainframe education says "APAR Status Tracking".
My Minix education says "Andrew S. Tanenbaum"
;-)

-- 
Lew Pitcher
"In Skills, We Trust"

[toc] | [prev] | [next] | [standalone]


Page 1 of 2  [1] 2  Next page →

Back to top | Article view | comp.lang.c


csiph-web