Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.c > #162512 > unrolled thread
| Started by | "hongy...@gmail.com" <hongyi.zhao@gmail.com> |
|---|---|
| First post | 2021-08-31 03:35 -0700 |
| Last post | 2021-09-01 08:32 -0700 |
| Articles | 20 on this page of 22 — 12 participants |
Back to article view | Back to comp.lang.c
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 →
| From | "hongy...@gmail.com" <hongyi.zhao@gmail.com> |
|---|---|
| Date | 2021-08-31 03:35 -0700 |
| Subject | int(*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]
| From | Bonita Montero <Bonita.Montero@gmail.com> |
|---|---|
| Date | 2021-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]
| From | "hongy...@gmail.com" <hongyi.zhao@gmail.com> |
|---|---|
| Date | 2021-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]
| From | Keith Thompson <Keith.S.Thompson+u@gmail.com> |
|---|---|
| Date | 2021-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]
| From | Manfred <noname@add.invalid> |
|---|---|
| Date | 2021-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]
| From | John Bode <jfbode1029@gmail.com> |
|---|---|
| Date | 2021-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]
| From | "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> |
|---|---|
| Date | 2021-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]
| From | Bart <bc@freeuk.com> |
|---|---|
| Date | 2021-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]
| From | "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> |
|---|---|
| Date | 2021-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]
| From | "hongy...@gmail.com" <hongyi.zhao@gmail.com> |
|---|---|
| Date | 2021-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]
| From | Keith Thompson <Keith.S.Thompson+u@gmail.com> |
|---|---|
| Date | 2021-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]
| From | Kaz Kylheku <563-365-8930@kylheku.com> |
|---|---|
| Date | 2021-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]
| From | "hongy...@gmail.com" <hongyi.zhao@gmail.com> |
|---|---|
| Date | 2021-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]
| From | James Kuyper <jameskuyper@alumni.caltech.edu> |
|---|---|
| Date | 2021-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]
| From | Bart <bc@freeuk.com> |
|---|---|
| Date | 2021-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]
| From | "hongy...@gmail.com" <hongyi.zhao@gmail.com> |
|---|---|
| Date | 2021-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]
| From | Keith Thompson <Keith.S.Thompson+u@gmail.com> |
|---|---|
| Date | 2021-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]
| From | "hongy...@gmail.com" <hongyi.zhao@gmail.com> |
|---|---|
| Date | 2021-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]
| From | scott@slp53.sl.home (Scott Lurndal) |
|---|---|
| Date | 2021-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]
| From | Lew Pitcher <lew.pitcher@digitalfreehold.ca> |
|---|---|
| Date | 2021-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