Strange function declaration

M

Massimo Neri

I was analyzing some GNU code when I saw something like this:

int
getopt (argc, argv, optstring)
int argc;
char *const *argv;
const char *optstring;
{
return _getopt_internal (argc, argv, optstring,
(const struct option *) 0,
(int *) 0,
0);
}

There are 2 strange things.

First I don't understand the head of the function:
int getopt(argc,argv,optstring) [<---
Where are the types?]
int argc; char *const *argv; const char *optstring; [<--- Here they
are, or not?]
I never see something like this. It looks so strange.

The second thing that I don't understand is
char *const *argv;
What is this? I know that argv is meant to be const char **. Is this
the same thing?

Thank for your attention,
Massimo
 
K

Keith Thompson

Massimo Neri said:
I was analyzing some GNU code when I saw something like this:

int
getopt (argc, argv, optstring)
int argc;
char *const *argv;
const char *optstring;
{
return _getopt_internal (argc, argv, optstring,
(const struct option *) 0,
(int *) 0,
0);
}

There are 2 strange things.

First I don't understand the head of the function:
int getopt(argc,argv,optstring) [<---
Where are the types?]
int argc; char *const *argv; const char *optstring; [<--- Here they
are, or not?]
I never see something like this. It looks so strange.

That's an old-style function definition. ANSI C introduced prototypes
in 1989, but the language still supports old-style (K&R) definitions.
The only reason to use them is backward compatibility to very old
compilers, or just plain inertia. Note that prototypes allow for
better compile-time error checking.
The second thing that I don't understand is
char *const *argv;
What is this? I know that argv is meant to be const char **. Is this
the same thing?

It's not the same thing. "char *const *argv" declares argv as a
const pointer to const char. "const char **argv" declares argv
as a pointer to pointer to const char.
 
M

Massimo Neri

So I have to read declarations from right to the left.
"char *const *argv" declares argv as a
const pointer to const char.

I think I have to read this "argv is a const pointer to char" and not
"const pointer to CONST char".
"const char **argv" declares argv
as a pointer to pointer to const char.

Now I have another question. What is the best way to declare argv?

Thank for your attention,
Massimo
 
B

Ben Bacarisse

Richard Heathfield said:
In
<f57d7c4a-cec3-4898-86da-e256f1decbf4@g23g2000vbr.googlegroups.com>,
Massimo Neri wrote:
The differences between char *const *X and const char **Y are that (1)
you can't assign a new value to X, but you can assign a new value to
Y, and (2) you *can* assign a new value to *X, but not to *Y.

I think you are out by one star. Both X and Y can be assigned to. *X
can't be but *Y can (also, **X can be assigned but **Y can't).

Your statement would be correct for char **const X and char *const *Y
(with or without a further const at front of either).
 
B

BGB / cr88192

Richard Heathfield said:
In


<K&R function declarator snipped>

It's ancient C. Backinadawnatime, when men were real men and women
were real women, Dennis Ritchie designed function declarators to be
int by default. Thus: foo(a, b, c) { return a + b + c; } was (and,
under C90, remains) perfectly legal.

It was only necessary to clarify the type for the compiler's benefit
for parameters that were not int. Such clarifiers went between the )
that closed the parameter list and the { that opened the function
body.

yep, and this is one of those features I didn't personally bother
implementing for my compiler...

hence, my compiler will likely never be completely standards conformant, as
I have left out a few features, most of which I don't personally use, and
have not felt that much pressing need to implement them...


actually, this is partly due to an oddity in my parser/compiler:
it doesn't actually differentiate between the toplevel and function bodies
(within the parser).
although, this is partly because my parser is somewhat older than my C
compiler, but a few years back was just sort of "beaten" into parsing C.

hence, using actual statements or expressions at the toplevel will parse,
although the actual compiler portion will not know what to do with this
(since this portion does distinguish between the toplevel and function
bodies).

to support K&R declaration syntax would then require using different parsing
code for the toplevel and for function bodies.

The modern equivalent of

int
getopt (argc, argv, optstring)
int argc;
char *const *argv;
const char *optstring;

is

int getopt(int argc, char *const *argv, const char *optstring)

kept for context...
 
S

Seebs

int
getopt (argc, argv, optstring)
int argc;
char *const *argv;
const char *optstring;
{
return _getopt_internal (argc, argv, optstring,
(const struct option *) 0,
(int *) 0,
0);
}

There are 2 strange things.

First I don't understand the head of the function:
int getopt(argc,argv,optstring) [<---
Where are the types?]
int argc; char *const *argv; const char *optstring; [<--- Here they
are, or not?]
I never see something like this. It looks so strange.

This is how very early (pre-ANSI) C handled function arguments; you declared
the arguments if they had a type other than int. Good style was to declare
them all, but it was optional.

You rarely see this outside of code intending compatibility with a broad
range of systems.
The second thing that I don't understand is
char *const *argv;
What is this? I know that argv is meant to be const char **. Is this
the same thing?

No, it isn't. This indicates that argv is an array of constant pointers to
non-constant characters. (I think. I always get tangled on this.) This
correctly describes the state of C as I understand it, which is that arguments
to a function are never themselves meaningfully const (C is pass-by-value),
but may point to things which may not be modified. The C standard asserts
that you can modify the characters pointed to by the pointers in argv, but
never asserts that the pointers themselves may be safely modified, so this
function declares itself with types compatible with those semantics.

-s
 
K

Keith Thompson

Massimo Neri said:
So I have to read declarations from right to the left.


I think I have to read this "argv is a const pointer to char" and not
"const pointer to CONST char".
[...]

See if you can find a tool called "cdecl".

% cdecl
Type `help' or `?' for help
cdecl> explain const char **argv
declare argv as pointer to pointer to const char
cdecl> declare argv as const pointer to const char
const char * const argv
cdecl>
 
K

Keith Thompson

Seebs said:
No, it isn't. This indicates that argv is an array of constant pointers to
non-constant characters. (I think. I always get tangled on this.)
[...]

Quibble: "constant" and "const" are very different things in C.

A constant is a literal, like 42. A "constant expression" is,
roughly, an expression that can be evaluated at compile time,
and that can therefore be used where a constant can be used, like
(2 + 2).

"const", on the other hand, is a qualifier that would probably have
been better called "readonly"; it indicates an object or type that
you're not allowed to modify.

An example:

const int r = rand(); /* definitely const, definitely not constant */
 
S

Seebs

Quibble: "constant" and "const" are very different things in C.

Yup. Right you are. (And in this case, while I was thinking the right
thing, I definitely did pick the wrong word.)
"const", on the other hand, is a qualifier that would probably have
been better called "readonly"; it indicates an object or type that
you're not allowed to modify.

Yes.

Good point about the name.

-s
 
D

Default User

Richard said:
In


<K&R function declarator snipped>

It's ancient C. Backinadawnatime, when men were real men and women
were real women . . .

And small furry creatures from Alpha Centauri were real small furry
creatures from Alpha Centauri?




Brian
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,065
Latest member
OrderGreenAcreCBD

Latest Threads

Top