Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.c > #93767 > unrolled thread
| Started by | gazelle@shell.xmission.com (Kenny McCormack) |
|---|---|
| First post | 2016-09-18 23:06 +0000 |
| Last post | 2016-09-19 11:46 -0700 |
| Articles | 8 — 7 participants |
Back to article view | Back to comp.lang.c
Question about extern declaration gazelle@shell.xmission.com (Kenny McCormack) - 2016-09-18 23:06 +0000
Re: Question about extern declaration supercat@casperkitty.com - 2016-09-18 16:33 -0700
Re: Question about extern declaration BartC <bc@freeuk.com> - 2016-09-19 01:02 +0100
Re: Question about extern declaration Ben Bacarisse <ben.usenet@bsb.me.uk> - 2016-09-19 01:23 +0100
Re: Question about extern declaration BartC <bc@freeuk.com> - 2016-09-19 10:40 +0100
Re: Question about extern declaration m.labanowicz@gmail.com - 2016-09-19 03:27 -0700
Re: Question about extern declaration Nobody <nobody@nowhere.invalid> - 2016-09-19 13:38 +0100
Re: Question about extern declaration Keith Thompson <kst-u@mib.org> - 2016-09-19 11:46 -0700
| From | gazelle@shell.xmission.com (Kenny McCormack) |
|---|---|
| Date | 2016-09-18 23:06 +0000 |
| Subject | Question about extern declaration |
| Message-ID | <nrn6m7$mpr$1@news.xmission.com> |
So, I've got something in one source file like:
struct foo *bar[] = { &s1, &s2, 0 };
and I want to access bar from another source file.
So, I do:
extern struct foo **bar;
but it doesn't work, until, after much hair pulling, I change it to:
extern struct foo *bar[];
which is, of course, sensible, as it matches the original declaration.
But all these years, I always assumed that, most of the time, **x and *x[]
pretty much meant the same thing. I've always used "char **argv" in
main(), even though the book-approved syntax is char *argv[]. It has
always worked the same.
So, what, really, is the difference between the two forms (specifically, in
an extern statement)?
--
He continues to assert that 2 plus 2 equals 4, despite being repeatedly
told otherwise.
[toc] | [next] | [standalone]
| From | supercat@casperkitty.com |
|---|---|
| Date | 2016-09-18 16:33 -0700 |
| Message-ID | <472df6bb-0505-49e3-b51a-82bcb9d77298@googlegroups.com> |
| In reply to | #93767 |
On Sunday, September 18, 2016 at 6:06:53 PM UTC-5, Kenny McCormack wrote:
> struct foo *bar[] = { &s1, &s2, 0 };
> extern struct foo **bar;
> extern struct foo *bar[];
>
> So, what, really, is the difference between the two forms (specifically, in
> an extern statement)?
An "extern" declaration effectively asks the compiler to interpret in some
fashion an external symbol the linker is going to supply. On many systems,
the linker will have no clue what an address represents, so it's necessary
for the declaration to tell the compiler how to interpret it.
The former declaration says that the address from the linker identifies a
storage location called "bar", which *holds* a pointer to an object of type
"struct foo *". The latter declaration, by contrast, says that the address
from the linker *directly identifies* the first item in an array of "struct
foo*" (as opposed to identifying an item hold the address of the first
object of that type).
[toc] | [prev] | [next] | [standalone]
| From | BartC <bc@freeuk.com> |
|---|---|
| Date | 2016-09-19 01:02 +0100 |
| Message-ID | <nrn9ts$v7t$1@dont-email.me> |
| In reply to | #93767 |
On 19/09/2016 00:06, Kenny McCormack wrote:
> So, I've got something in one source file like:
>
> struct foo *bar[] = { &s1, &s2, 0 };
>
> and I want to access bar from another source file.
>
> So, I do:
>
> extern struct foo **bar;
>
> but it doesn't work, until, after much hair pulling, I change it to:
>
> extern struct foo *bar[];
>
> which is, of course, sensible, as it matches the original declaration.
>
> But all these years, I always assumed that, most of the time, **x and *x[]
> pretty much meant the same thing. I've always used "char **argv" in
> main(), even though the book-approved syntax is char *argv[]. It has
> always worked the same.
>
> So, what, really, is the difference between the two forms (specifically, in
> an extern statement)?
Outside of a parameter list:
T **bar; // pointer to pointer to T
T *bar[5]; // 'value' array 5 of pointer to T
T (*bar)[5]; // (pointer to array 5 of T)
The first two forms, which is what you have, are not the same thing.
I've put in the 5 to make it clearer: the first form, declared in static
memory, will reserve space for one pointer. The second will reserve
space for 5 pointers.
Outside of a parameter list:
T **bar; // pointer to pointer to T
T *bar[5]; // pointer to pointer to T
Here they /are/ the same thing (with the 5 being discarded), as a value
array doesn't make sense for a parameter.
To make it simpler, the difference between your two declarations is that
same as between these two:
int *bar;
int foo[];
C unhelpfully allows such diverse declarations to be accessed using the
same code (bar[i] or foo[i]; or *bar or *foo).
--
Bartc
[toc] | [prev] | [next] | [standalone]
| From | Ben Bacarisse <ben.usenet@bsb.me.uk> |
|---|---|
| Date | 2016-09-19 01:23 +0100 |
| Message-ID | <8737kwka90.fsf@bsb.me.uk> |
| In reply to | #93771 |
BartC <bc@freeuk.com> writes:
> On 19/09/2016 00:06, Kenny McCormack wrote:
>> So, I've got something in one source file like:
>>
>> struct foo *bar[] = { &s1, &s2, 0 };
>>
>> and I want to access bar from another source file.
>>
>> So, I do:
>>
>> extern struct foo **bar;
>>
>> but it doesn't work, until, after much hair pulling, I change it to:
>>
>> extern struct foo *bar[];
>>
>> which is, of course, sensible, as it matches the original declaration.
>>
>> But all these years, I always assumed that, most of the time, **x and *x[]
>> pretty much meant the same thing. I've always used "char **argv" in
>> main(), even though the book-approved syntax is char *argv[]. It has
>> always worked the same.
>>
>> So, what, really, is the difference between the two forms (specifically, in
>> an extern statement)?
>
> Outside of a parameter list:
>
> T **bar; // pointer to pointer to T
> T *bar[5]; // 'value' array 5 of pointer to T
> T (*bar)[5]; // (pointer to array 5 of T)
>
> The first two forms, which is what you have, are not the same thing.
>
> I've put in the 5 to make it clearer: the first form, declared in
> static memory, will reserve space for one pointer. The second will
> reserve space for 5 pointers.
>
> Outside of a parameter list:
^^^^^^^
>
> T **bar; // pointer to pointer to T
> T *bar[5]; // pointer to pointer to T
>
> Here they /are/ the same thing (with the 5 being discarded), as a
> value array doesn't make sense for a parameter.
I think you meant "inside a parameter list".
<snip>
--
Ben.
[toc] | [prev] | [next] | [standalone]
| From | BartC <bc@freeuk.com> |
|---|---|
| Date | 2016-09-19 10:40 +0100 |
| Message-ID | <nrobq9$82t$2@dont-email.me> |
| In reply to | #93773 |
On 19/09/2016 01:23, Ben Bacarisse wrote: > BartC <bc@freeuk.com> writes: >> Outside of a parameter list: > ^^^^^^^ > I think you meant "inside a parameter list". > Yes. I even remember wondering while writing it whether "In" might be better than "Inside". Then proceeded to write "Outside"! -- Bartc
[toc] | [prev] | [next] | [standalone]
| From | m.labanowicz@gmail.com |
|---|---|
| Date | 2016-09-19 03:27 -0700 |
| Message-ID | <d6961688-2ebb-4939-8c3a-6999e15f25e9@googlegroups.com> |
| In reply to | #93767 |
> extern struct foo **bar; bar++; /* ok */ > extern struct foo *bar[]; bar++; /* error: cannot increment value of type 'struct foo *[]' */
[toc] | [prev] | [next] | [standalone]
| From | Nobody <nobody@nowhere.invalid> |
|---|---|
| Date | 2016-09-19 13:38 +0100 |
| Message-ID | <pan.2016.09.19.12.38.38.849000@nowhere.invalid> |
| In reply to | #93767 |
On Sun, 18 Sep 2016 23:06:47 +0000, Kenny McCormack wrote: > So, what, really, is the difference between the two forms (specifically, > in an extern statement)? One is a pointer to a pointer, the other is an array of pointers. Arrays and pointers are equivalent in some contexts, but not all. If you use an array as a "value", the value is a pointer to the first element. This covers enough cases that it's not that hard to mislead yourself that there's no difference between them. It also doesn't help that C allows you to declare a function parameter as an array even though what's actually being passed is a pointer. Presumably this feature exists for "documentation", i.e. to distinguish a pointer to a single value from a pointer to the first of many values. The equivalence doesn't apply to any other variable declaration (extern, "static" global, global with external linkage, "static" local, automatic local), because in those cases you can declare variables which are actually arrays, whereas function parameters can't be arrays.
[toc] | [prev] | [next] | [standalone]
| From | Keith Thompson <kst-u@mib.org> |
|---|---|
| Date | 2016-09-19 11:46 -0700 |
| Message-ID | <lnh99bwwva.fsf@kst-u.example.com> |
| In reply to | #93796 |
Nobody <nobody@nowhere.invalid> writes:
> On Sun, 18 Sep 2016 23:06:47 +0000, Kenny McCormack wrote:
>
>> So, what, really, is the difference between the two forms (specifically,
>> in an extern statement)?
>
> One is a pointer to a pointer, the other is an array of pointers.
>
> Arrays and pointers are equivalent in some contexts, but not all.
Arrays and pointers are not equivalent in any context. An array
expression is, in most contexts, converted to a pointer expression
whose value is the address of the initial element of the array
object.
We can, for example, apply the unary "*" operator to the name of a
pointer object or to the name of an array object. In both cases,
the operand is an expression of pointer type; the only difference
is that one happens to be a converted array expression.
> If you
> use an array as a "value", the value is a pointer to the first element.
> This covers enough cases that it's not that hard to mislead yourself that
> there's no difference between them.
That's not the correct distinction. For example, if an identifier
appears on the left side of an assignment, it doesn't refer to the
value of the object -- but the array-to-pointer conversion still
occurs (making the assignment invalid because the resulting pointer
expression is not an lvalue).
Understand that array expressions are usually "converted" to pointer
expressions, and understand the three cases where they aren't.
> It also doesn't help that C allows you to declare a function parameter as
> an array even though what's actually being passed is a pointer. Presumably
> this feature exists for "documentation", i.e. to distinguish a pointer to
> a single value from a pointer to the first of many values.
Yes, that's a separate special-case rule, and yes, it causes a fair
amount of confusion.
> The equivalence doesn't apply to any other variable declaration (extern,
> "static" global, global with external linkage, "static" local, automatic
> local), because in those cases you can declare variables which are
> actually arrays, whereas function parameters can't be arrays.
--
Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
[toc] | [prev] | [standalone]
Back to top | Article view | comp.lang.c
csiph-web