Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.c > #90259 > unrolled thread
| Started by | sinbad <sinbad.sinbad@gmail.com> |
|---|---|
| First post | 2016-07-12 03:06 -0700 |
| Last post | 2016-07-12 12:33 -0400 |
| Articles | 14 — 9 participants |
Back to article view | Back to comp.lang.c
extern array as a pointer sinbad <sinbad.sinbad@gmail.com> - 2016-07-12 03:06 -0700
Re: extern array as a pointer BartC <bc@freeuk.com> - 2016-07-12 11:45 +0100
Re: extern array as a pointer Frank Tetzel <s1445051@mail.zih.tu-dresden.de> - 2016-07-12 13:58 +0200
Re: extern array as a pointer Ben Bacarisse <ben.usenet@bsb.me.uk> - 2016-07-12 13:33 +0100
Re: extern array as a pointer Keith Thompson <kst-u@mib.org> - 2016-07-12 09:30 -0700
Re: extern array as a pointer James Kuyper <jameskuyper@verizon.net> - 2016-07-12 12:52 -0400
Re: extern array as a pointer Keith Thompson <kst-u@mib.org> - 2016-07-12 11:30 -0700
Re: extern array as a pointer supercat@casperkitty.com - 2016-07-12 11:51 -0700
Re: extern array as a pointer supercat@casperkitty.com - 2016-07-12 10:55 -0700
Re: extern array as a pointer Keith Thompson <kst-u@mib.org> - 2016-07-12 09:28 -0700
Re: extern array as a pointer Nobody <nobody@nowhere.invalid> - 2016-07-12 13:26 +0100
Re: extern array as a pointer Keith Thompson <kst-u@mib.org> - 2016-07-12 09:26 -0700
Re: extern array as a pointer Richard Heathfield <rjh@cpax.org.uk> - 2016-07-12 13:46 +0100
Re: extern array as a pointer James Kuyper <jameskuyper@verizon.net> - 2016-07-12 12:33 -0400
| From | sinbad <sinbad.sinbad@gmail.com> |
|---|---|
| Date | 2016-07-12 03:06 -0700 |
| Subject | extern array as a pointer |
| Message-ID | <27db6ff2-216f-41c6-a9e0-c06d206f5262@googlegroups.com> |
Hi,
why does the following program crash at line# 20.
Is it even legal to define array as an integer
pointer while infact it's original definition is
single dimensional array or five elements.
1 #include "stdio.h"
2
3 int foo();
4
5 int array[5];
6
7 int main()
8 {
9 foo();
10 printf("array[0] is %u", array[0]);
11 return(0);
12 }
13
14 foo.c:
15
16 extern int *array;
17
18 int foo()
19 {
20 arr[0]= 10;
21 return(0);
22 }
[toc] | [next] | [standalone]
| From | BartC <bc@freeuk.com> |
|---|---|
| Date | 2016-07-12 11:45 +0100 |
| Message-ID | <nm2ho6$455$1@dont-email.me> |
| In reply to | #90259 |
On 12/07/2016 11:06, sinbad wrote:
>
> Hi,
>
> why does the following program crash at line# 20.
> Is it even legal to define array as an integer
> pointer while infact it's original definition is
> single dimensional array or five elements.
>
> 1 #include "stdio.h"
> 2
> 3 int foo();
> 4
> 5 int array[5];
> 6
> 7 int main()
> 8 {
> 9 foo();
> 10 printf("array[0] is %u", array[0]);
> 11 return(0);
> 12 }
> 13
> 14 foo.c:
> 15
> 16 extern int *array;
> 17
> 18 int foo()
> 19 {
> 20 arr[0]= 10;
Did you mean array[0] here?
> 21 return(0);
> 22 }
>
>
You have a normal array in one module which is defined as a pointer to
array in another, assuming arr was meant to be array. Try writing:
extern int array[];
in foo.c
--
Bartc
[toc] | [prev] | [next] | [standalone]
| From | Frank Tetzel <s1445051@mail.zih.tu-dresden.de> |
|---|---|
| Date | 2016-07-12 13:58 +0200 |
| Message-ID | <20160712135839.349cd1a4@archvm> |
| In reply to | #90261 |
> > why does the following program crash at line# 20.
> > Is it even legal to define array as an integer
> > pointer while infact it's original definition is
> > single dimensional array or five elements.
> >
> > 1 #include "stdio.h"
> > 2
> > 3 int foo();
> > 4
> > 5 int array[5];
> > 6
> > 7 int main()
> > 8 {
> > 9 foo();
> > 10 printf("array[0] is %u", array[0]);
> > 11 return(0);
> > 12 }
> > 13
> > 14 foo.c:
> > 15
> > 16 extern int *array;
> > 17
> > 18 int foo()
> > 19 {
> > 20 arr[0]= 10;
>
> Did you mean array[0] here?
>
> > 21 return(0);
> > 22 }
> >
> >
>
> You have a normal array in one module which is defined as a pointer
> to array in another, assuming arr was meant to be array. Try writing:
>
> extern int array[];
>
> in foo.c
But why? Why is "extern int *array" containing the first element which
is 0? Why doesn't the compiler or rather the linker warn about this? Is
the type information lost for the linker?
In the past i used *array and array[] interchangeable. I might have to
reconsider that.
[toc] | [prev] | [next] | [standalone]
| From | Ben Bacarisse <ben.usenet@bsb.me.uk> |
|---|---|
| Date | 2016-07-12 13:33 +0100 |
| Message-ID | <87mvlnyr13.fsf@bsb.me.uk> |
| In reply to | #90265 |
Frank Tetzel <s1445051@mail.zih.tu-dresden.de> writes:
>> > why does the following program crash at line# 20.
>> > Is it even legal to define array as an integer
>> > pointer while infact it's original definition is
>> > single dimensional array or five elements.
>> >
>> > 1 #include "stdio.h"
>> > 2
>> > 3 int foo();
>> > 4
>> > 5 int array[5];
>> > 6
>> > 7 int main()
>> > 8 {
>> > 9 foo();
>> > 10 printf("array[0] is %u", array[0]);
>> > 11 return(0);
>> > 12 }
>> > 13
>> > 14 foo.c:
>> > 15
>> > 16 extern int *array;
>> > 17
>> > 18 int foo()
>> > 19 {
>> > 20 arr[0]= 10;
>>
>> Did you mean array[0] here?
>>
>> > 21 return(0);
>> > 22 }
>> >
>> >
>>
>> You have a normal array in one module which is defined as a pointer
>> to array in another, assuming arr was meant to be array. Try writing:
>>
>> extern int array[];
>>
>> in foo.c
>
> But why? Why is "extern int *array" containing the first element which
> is 0? Why doesn't the compiler or rather the linker warn about this? Is
> the type information lost for the linker?
Yes, it's sadly not common for this sort of thing to be checked at link
time.
> In the past i used *array and array[] interchangeable. I might have to
> reconsider that.
They are interchangeable only when they appear as formal parameters in a
function declaration or definition and that's only because C can't pass
"naked" array values so the [] form is redundant. It was (probably
unfortunately) appropriated to mean the same thing in this context.
In other contexts, a pointer declaration and an array declaration are
very different. Think of what code the compiler must generate for
extern int *a;
...
a[0] // a names a pointer-sized object whose content must loaded
// and used in a indirect memory access.
and
extern int a[10];
...
a[0] // a names a 10-int sized object. It is the address of that
// object that must be used.
But there are all sorts of other ways to see why this distinction
matters. For example, consider what &a means in each case.
--
Ben.
[toc] | [prev] | [next] | [standalone]
| From | Keith Thompson <kst-u@mib.org> |
|---|---|
| Date | 2016-07-12 09:30 -0700 |
| Message-ID | <lnbn22izsv.fsf@kst-u.example.com> |
| In reply to | #90265 |
Frank Tetzel <s1445051@mail.zih.tu-dresden.de> writes:
[...]
> But why? Why is "extern int *array" containing the first element which
> is 0? Why doesn't the compiler or rather the linker warn about this? Is
> the type information lost for the linker?
Yes, that's exactly the problem: the linker is required to pay attention
to type information.
Careful use of header files, so you don't have multiple unchecked
declarations of the same thing, can avoid problems like this.
> In the past i used *array and array[] interchangeable. I might have to
> reconsider that.
Please do. And read section 6 of the comp.lang.c FAQ:
http://www.c-faq.com/
--
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] | [next] | [standalone]
| From | James Kuyper <jameskuyper@verizon.net> |
|---|---|
| Date | 2016-07-12 12:52 -0400 |
| Message-ID | <nm377p$k9q$1@dont-email.me> |
| In reply to | #90283 |
On 07/12/2016 12:30 PM, Keith Thompson wrote: > Frank Tetzel <s1445051@mail.zih.tu-dresden.de> writes: > [...] >> But why? Why is "extern int *array" containing the first element which >> is 0? Why doesn't the compiler or rather the linker warn about this? Is >> the type information lost for the linker? > > Yes, that's exactly the problem: the linker is required to pay attention > to type information. Is there a "not" missing from that sentence?
[toc] | [prev] | [next] | [standalone]
| From | Keith Thompson <kst-u@mib.org> |
|---|---|
| Date | 2016-07-12 11:30 -0700 |
| Message-ID | <lntwfuhfow.fsf@kst-u.example.com> |
| In reply to | #90290 |
James Kuyper <jameskuyper@verizon.net> writes:
> On 07/12/2016 12:30 PM, Keith Thompson wrote:
>> Frank Tetzel <s1445051@mail.zih.tu-dresden.de> writes:
>> [...]
>>> But why? Why is "extern int *array" containing the first element which
>>> is 0? Why doesn't the compiler or rather the linker warn about this? Is
>>> the type information lost for the linker?
>>
>> Yes, that's exactly the problem: the linker is required to pay attention
>> to type information.
>
> Is there a "not" missing from that sentence?
OOPS!
Yes, what I meant was:
Yes, that's exactly the problem: the linker is not required to pay
attention to type information.
--
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] | [next] | [standalone]
| From | supercat@casperkitty.com |
|---|---|
| Date | 2016-07-12 11:51 -0700 |
| Message-ID | <0aeccb04-6e57-4109-9105-01a3497b89a2@googlegroups.com> |
| In reply to | #90297 |
On Tuesday, July 12, 2016 at 1:30:55 PM UTC-5, Keith Thompson wrote: > Yes, that's exactly the problem: the linker is not required to pay > attention to type information. A more fundamental problem is that nothing is required to relay type information from the source text to the linker. Even if the linker were required to validate any type information it receives, there would be no way it could ensure that an identifier is used consistently in two translation units unless something were to tell it how each unit used the identifier in question.
[toc] | [prev] | [next] | [standalone]
| From | supercat@casperkitty.com |
|---|---|
| Date | 2016-07-12 10:55 -0700 |
| Message-ID | <c22b9a02-73df-4add-a3cc-20bffe69edfe@googlegroups.com> |
| In reply to | #90283 |
On Tuesday, July 12, 2016 at 11:31:05 AM UTC-5, Keith Thompson wrote: > Frank Tetzel <s1445051@mail.zih.tu-dresden.de> writes: > [...] > > But why? Why is "extern int *array" containing the first element which > > is 0? Why doesn't the compiler or rather the linker warn about this? Is > > the type information lost for the linker? > > Yes, that's exactly the problem: the linker is required to pay attention > to type information. To supply warnings the linker would need to examine type information; since the Standard doesn't require warnings the language can be and often is implemented on systems whose linker simply associates every symbol with a base selector and an offset, and each byte an executable file that isn't specified directly within an object file must represent an eight-bit chunk of a computed value of the form (symbol + offset). Many of the limits on constant address expressions exist to support that design.
[toc] | [prev] | [next] | [standalone]
| From | Keith Thompson <kst-u@mib.org> |
|---|---|
| Date | 2016-07-12 09:28 -0700 |
| Message-ID | <lnfureizw5.fsf@kst-u.example.com> |
| In reply to | #90261 |
BartC <bc@freeuk.com> writes:
> On 12/07/2016 11:06, sinbad wrote:
>> why does the following program crash at line# 20.
>> Is it even legal to define array as an integer
>> pointer while infact it's original definition is
>> single dimensional array or five elements.
[...]
>> 5 int array[5];
[...]
>> 16 extern int *array;
[...]
>
> You have a normal array in one module which is defined as a pointer to
> array in another, assuming arr was meant to be array.
No, it's declared (not defined) as a pointer to int, not a pointer to an
array. A pointer to an array would be something like
extern int (*a)[];
or
extern int (*a)[5];
> Try writing:
>
> extern int array[];
Yup.
--
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] | [next] | [standalone]
| From | Nobody <nobody@nowhere.invalid> |
|---|---|
| Date | 2016-07-12 13:26 +0100 |
| Message-ID | <pan.2016.07.12.12.26.36.123000@nowhere.invalid> |
| In reply to | #90259 |
On Tue, 12 Jul 2016 03:06:29 -0700, sinbad wrote: > why does the following program crash at line# 20. The program shouldn't even compile cleanly, given that you reference a variable "arr" which is declared nowhere. Assuming that you meant to write "array", it will typically crash because the declaration doesn't match the definition. > Is it even legal to define array as an integer pointer while infact it's > original definition is single dimensional array or five elements. You didn't *define* "array" as an integer pointer, you *declared* it as such. And, no, it won't work. Arrays aren't pointers. They *decay* to pointers when used as expressions (as opposed to lvalues), but they aren't pointers. If you do: > int array[5]; the object file will contain a reservation of 5*sizeof(int) bytes and the symbol table entry for array will reference the start of that reservation. If you do: > int *array; the object file will contain a reservation of sizeof(int*) bytes and the symbol table entry for array will reference the start of that reservation. With an extern declaration: > extern int array[]; an expression such as array[i] will result in code along the lines of > *(int*)(array + i*sizeof(int)) With an extern declaration like: > extern int *array; an expression such as array[i] will result in code along the lines of > *(*(int*)array + i * sizeof(int)) I.e. there will be an extra level of indirection based upon the fact that the symbol refers to the address of a pointer to the first element rather than to the address of the first element itself. If you kept the existing definition but declared array as "extern int array[];", everything should work. If you kept the existing declaration but defined "array" as "int *array;", then you'd generate correct code, but unless you added some more code somewhere to initialise the pointer to point to valid memory before you used it, you'd still get a segfault.
[toc] | [prev] | [next] | [standalone]
| From | Keith Thompson <kst-u@mib.org> |
|---|---|
| Date | 2016-07-12 09:26 -0700 |
| Message-ID | <lnk2gqj00b.fsf@kst-u.example.com> |
| In reply to | #90267 |
Nobody <nobody@nowhere.invalid> writes:
[...]
> And, no, it won't work. Arrays aren't pointers.
Right.
> They *decay* to pointers
> when used as expressions (as opposed to lvalues), but they aren't pointers.
lvalues are expressions -- and that's not the right distinction anyway.
(An lvalue is, somewhat loosely, an expression that designates an
object.)
An expression of array type is implicitly converted to a pointer to the
array's initial element *unless* it is one of:
- The operand of a unary "&" operator; or
- The operand of a unary "sizeof" operator; or
- A string literal in an initializer used to initialize an array object.
[...]
--
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] | [next] | [standalone]
| From | Richard Heathfield <rjh@cpax.org.uk> |
|---|---|
| Date | 2016-07-12 13:46 +0100 |
| Message-ID | <nm2orr$sic$1@dont-email.me> |
| In reply to | #90259 |
On 12/07/16 11:06, sinbad wrote: > > Hi, > > why does the following program crash at line# 20. Because arrays are not pointers, and pointers are not arrays. > Is it even legal to define array as an integer > pointer while infact it's original definition is > single dimensional array or five elements. It invokes undefined behaviour. int array[5] defines an array of 5 int, with file scope and external linkage. If you wish to refer to this array from another source file, you can, by declaring it as follows: extern int array[]; > 13 > 14 foo.c: > 15 > 16 extern int *array; Here, the name is right but the type is wrong. array is int[5], not int *. C allows us to compile source files individually, linking them in a later step. So the compiler has to be able to compile foo.c without even seeing main()'s source file. It has /no idea/ that array (bad choice for an identifier name, by the way!) is an array. When you tell it array is a pointer, it believes you, and array[0] is a legal access to an object pointed to by an int * (you actually wrote arr[0], but I'm overlooking that). So there's no reason for the compiler to complain. But it's still wrong, and it may bite you. And, apparently, it did. -- Richard Heathfield Email: rjh at cpax dot org dot uk "Usenet is a strange place" - dmr 29 July 1999 Sig line 4 vacant - apply within
[toc] | [prev] | [next] | [standalone]
| From | James Kuyper <jameskuyper@verizon.net> |
|---|---|
| Date | 2016-07-12 12:33 -0400 |
| Message-ID | <nm3650$g16$1@dont-email.me> |
| In reply to | #90259 |
On 07/12/2016 06:06 AM, sinbad wrote:
>
> Hi,
>
> why does the following program crash at line# 20.
> Is it even legal to define array as an integer
> pointer while infact it's original definition is
> single dimensional array or five elements.
>
> 1 #include "stdio.h"
> 2
> 3 int foo();
> 4
> 5 int array[5];
> 6
> 7 int main()
> 8 {
> 9 foo();
> 10 printf("array[0] is %u", array[0]);
> 11 return(0);
> 12 }
> 13
> 14 foo.c:
> 15
> 16 extern int *array;
> 17
> 18 int foo()
> 19 {
> 20 arr[0]= 10;
> 21 return(0);
> 22 }
Other people have already given you accurate explanations, so I guess
I'll do what I do best, and give you the corresponding citations from
the standard:
"In the set of translation units and libraries that constitutes an
entire program, each declaration of a particular identifier with
external linkage denotes the same object or function." (6.2.2p2)
"All declarations that refer to the same object or function shall have
compatible type; otherwise, the behavior is undefined." (6.2.7p2)
int[5] and int* are not compatible types. One requires storage space for
5 'int' objects; the other requires storage space for a single pointer
to an 'int'.
C contains a couple of features that can cause newbies to confuse arrays
with pointers. First of all, in most contexts, an lvalue of array type
is automatically converted into a pointer to the first element of that
array. The only three exceptions are
1. "sizeof array"
This expression gives you the size of the actual array, and NOT the size
of a pointer to the first element of the array.
2. &array
This expression returns a pointer of type T(*)[N], where T is the
element type of the array, and N is the length of the array. If array
had been converted to a pointer to the first element, then &array would
have had the type T**.
3. char array[] = "string";
The string literal causes the creation of an anonymous array of char
containing {'s', 't', 'r', 'i', 'n', 'g', '\0'}. When used as an
initializer for a character array, the contents of the anonymous array
are copied into that character array. In contrast, for initialization of
all other data types, the normal conversion occurs:
char *ptr = "string";
the string literal is an lvalue of array type, and therefore gets
converted to a pointer to the first element of the array ('s'), and that
pointer is stored in ptr.
The second feature that causes this confusion has already been mentioned
by Ben Bacarisse: a declaration of a parameter of a function that looks
like it declared that parameter as an array actually declares that
parameter to be a pointer to the element type of the array. The length
specified for the array is completely ignored - it is functionally no
more significant than a comment.
These features were designed into the language because the authors of
the language thought they'd be convenient, and once you get used to
them, they are convenient. But until you get used to them, they're a
great cause of confusion.
[toc] | [prev] | [standalone]
Back to top | Article view | comp.lang.c
csiph-web