Can I tab[-1] ?

B

Ben Bacarisse

fir said:
W dniu czwartek, 20 grudnia 2012 14:38:45 UTC+1 użytkownik Ben Bacarisse napisał:
I think the OP wants an 'dead' edge all the way round. I.e. I think
they want:

int wider_tab[(N+2)*(N+2)];
int (*tab)[N+2] = (int (*)[N+2])&wider_tab[N+2+1];

(for N=500). You could also (probably) get away with using plain 2D
arrays for a little more clarity:

int wider_tab[N+2][N+2];
int (*tab)[N+2] = (void *)&wider_tab[1][1];

that is exactly what i want, but here above is it vector of pointers
or lite/solid block of addresable ram (with no other area pointers?),
(somewhat sad to say but i forgot of was atways somewhat out to array
pointer subtlities :/ like this)

Sorry, but I can't understand enough of the that to answer what seems to
be a question in it. I hazard a guess: What I wrote uses a pointer
into a single 2D array. There are no other pointers involved (it's not
an array of pointers.
what way "int (*tab)[N+2]" should be read?

tab is a pointer to an array of N+2 ints. http://www.bsb.me.uk/c-types
 
K

Keith Thompson

Shao Miller said:
There is a caveat: It's possible that the standard allows (int [500]) to
have a stricter alignment requirement than (int [502*502]), which would
mean that the cast isn't guaranteed to behave. I'm not convinced that
it's allowed, and even if it is, I am confident that no implementation
actually has such a requirement.

Confidence: Agreed.

C11's 6.2.8p4 seems to suggest that possible alignments are really
derived from fundamental types.

It would be helpful if you'd quote the text you're citing; not everyone
has a copy of the standard easily available (though I do).

Quoting N1570:

Alignments are represented as values of the type size_t. Valid
alignments include only those values returned by an
_Alignof expression for fundamental types, plus an additional
implementation-defined set of values, which may be empty. Every
valid alignment value shall be a nonnegative integral power
of two.

There is a change bar on that paragraph. Are you perhaps referring
to an earlier draft?

I don't think that implies what you say it does. It seems to allow,
for example, a structure to have a stricter alignment than any of
its members, or than any fundamental type.

[...]
 
P

Philip Lantz

Tim said:
What I think you mean is that all implementations do in fact
produce (at the present time) the desired behavior. Even if
that's true, I expect no implementation actually guarantees it,
and certainly not all of them do.

I think they do--not explicitly in their documentation, but implicitly
by their definitions of how they handle alignment and pointer
conversions.
 
P

Phil Carmody

Philip Lantz said:
I think they do--not explicitly in their documentation, but implicitly
by their definitions of how they handle alignment and pointer
conversions.

You've read those definitions for *every* compiler?
"All" means "all", do not underestimate what that implies.

Phil
 
K

Keith Thompson

Tim Rentsch said:
Dear Professor:

Please change your settings, or edit your postings, or both, to
get rid of extraneous blank lines.

That's the fault of Google Groups. The best solution is to post
through an actual Usenet server; eternal-september.org is good
and free. The second-best solution is probably to copy-and-paste
your article into a text editor, repair the damage done by GG,
then copy-and-paste it back into your web browser before posting

[...]
as to -1 as far as i remember ritche wrote (in c development
historical note) that this square bracket syntax is only a
sugar/alias to pointers *(a+5) becomes a[5] here (or even 5[a]
points the same as denoted in wiki - so it is maybe just
mechanical trick), so by analogy if *(a-1) works a[-1] should be
working also

C is now defined by the ISO document on it. Any writing by
Ritchie, however much we might enjoy or appreciate it, is no
longer authoritative.

And that ISO document defines array indexing in terms of pointer
arithmetic.

N1370 6.5.2.1p2:

The definition of the subscript operator [] is that E1[E2] is
identical to (*((E1)+(E2))).

`*(a-1)` has defined behavior if and only if `a[-1]` has defined
behavior. `a` is always an expression of pointer type (possibly
the result of an implicit conversion of an expression of array type).

Which means that using pointer notation is not a way to avoid the UB
implied by array semantics.
 
S

Shao Miller

fir said:
[citation for Tim Rentsch]



Can I use c arrays in such way tab[-1] or tab[-1][-1] (I mean when index is below zero)?



Also - I think if try to use some way of optimization

where instead of checking some edge values like



if(x>=0 && x<500 && y>=0 && y<500)

tab[y][x] = 1;



alloc some edge ram and do not bother about x=-1 or x=tab_max_x+1



but here it would be convenient to cast some pointer ot type tab[500][500] 'into' wider_tab[502][502]

in such way that tab[0][0] wolul correspond to wider_tab[1][1] (and tab[-1][-1] to wider_tab[0][0])



Can I get something like that? (If not I am sad)



The short answer is no. If E is any expression of array type,

any use of (E)[-1] or even just ((E)-1) is undefined behavior.



To get something like what you want, you would have to use

an array of pointers, those pointers being of type (int *),

and the type of 'tab' being (int **), with tab pointing at

the second element of the array (ie, at index [1]). The

pointers in the pointer array should point into a large

one-dimensional array, eg, 'int tab_space[ 502 * 502 ];'.

Dear Professor:

Please change your settings, or edit your postings, or both, to
get rid of extraneous blank lines.
what with

int (*tab)[N+2] = (void *)&wider_tab[1][1];

isnt tab here a pointer to "int somechunk[502]" ?

and if so, tab+1 (or tab[1]) woluld be next one "int some[502}" laying
after previous -

so if it is working -> (tab[j]) (or tab[j]), it should be
working the way I would exactly like- so it would be grrt (great I
mean)


Indexing in C is not defined just in terms of address
calculation. Address calculation is one aspect, but there
are additional constraints, and those constraints must be
observed; otherwise ALL BETS ARE OFF. The approach
described above violates those constraints. ANY approach
using pointer to array types, that attempts to index an
expression of array type with an index value of -1, will
violate the constraints. There is NO WAY to do what you
want to do using regular arrays or pointers to arrays; use
an array of pointers, and use type (int **) for the
accessing identifer ('tab' in the above) instead.



I suspect that might be true, but I haven't been able to find where
the standard prohibits using an index of -1 (as in a[-1]), so long as
the underlying object exists at *(a-1). If you've found it, please
share.


I'd say that it's due to ambiguity in the Standard, especially regarding
"object" and "array object".

It would seems that an implementation has license to perform bounds
checking based on a notion of "type defines the bounds." (If you can't
find where an implementation _doesn't_ have such a license, then it
does, right? ;) )

If you have:

int foo[10];

then when you point into that array, the bounds are pretty obvious,
because the type is known.

With 'malloc' and family, there're no types involved until an effective
type is established, but at least we know the bounds based on the size.

If you have:

int foo[10];
int (* bar)[2] = (void *) (foo + 1);

and if you believe that alignment is satisfied (a separate discussion),
then '*bar' (an array expression yielding a pointer in many contexts)
has bounds which would seem to be established by its type; discarding
the bounds of the original "substrate" being a distinct possibility.

But for something more concrete than my rambling, please see the
informative annex for "Portability Issues" -> "Undefined behavior" and
the following:

"An array subscript is out of range, even if an object is apparently
accessible with the given subscript (as in the lvalue expression a[1][7]
given the declaration int a[4][5]) (6.5.6)."

- Shao Miller
 
F

fir

W dniu piątek, 21 grudnia 2012 03:19:35 UTC+1 użytkownik Keith Thompson napisał:
That's the fault of Google Groups. The best solution is to post
through an actual Usenet server; eternal-september.org is good
and free. The second-best solution is probably to copy-and-paste
your article into a text editor, repair the damage done by GG,
then copy-and-paste it back into your web browser before posting
:-( It does not working - when i command 'answer' in gougle groups i ve gotspoiled
content in it - and it is very troublesome
to delete 100 blank lines every time. Maybe easier would be to live it as it is? (sorry for that)
 
S

Shao Miller

Shao Miller said:
There is a caveat: It's possible that the standard allows (int [500]) to
have a stricter alignment requirement than (int [502*502]), which would
mean that the cast isn't guaranteed to behave. I'm not convinced that
it's allowed, and even if it is, I am confident that no implementation
actually has such a requirement.

Confidence: Agreed.

C11's 6.2.8p4 seems to suggest that possible alignments are really
derived from fundamental types.

It would be helpful if you'd quote the text you're citing; not everyone
has a copy of the standard easily available (though I do).

A useful habit to get into; sorry about that.
Quoting N1570:

Alignments are represented as values of the type size_t. Valid
alignments include only those values returned by an
_Alignof expression for fundamental types, plus an additional
implementation-defined set of values, which may be empty. Every
valid alignment value shall be a nonnegative integral power
of two.

There is a change bar on that paragraph. Are you perhaps referring
to an earlier draft?

That's the one.
I don't think that implies what you say it does. It seems to allow,
for example, a structure to have a stricter alignment than any of
its members, or than any fundamental type.

I do not argue of any guarantee, but by "suggest," I do mean to take
notice of what's actually included in the text. It says "fundamental
types," so we can be sure of those alignments. It says "which may be
empty," which causes me to think that the former alignments are the
important ones, while not restricting implementations. It says "power
of two" which restricts the implementation in such a way that if the
implementation is going to have alignments we might not expect, at least
it can't get too carried away... So it seems simpler to not worry about
it getting too carried away.

Why an implementation might have an alignment requirement for an array
that's any more strict than its element type, I could only guess.
Fortunately, we can check directly in C11 ('_Alignof') and with a
reasonable method for C < C11 (such as Mr. Chris M. Thomasson's).

Another consideration is that alignment must be a factor of the size of
a complete object type, else arrays of that type are impossible.
However, not just any factor will do, due to powers of 2.

Consider 'char[514]'. It can only have an alignment requirement of 1 or
2, as both are factors as well as powers of two. 'char[512]' is much
"luckier." Given such complications (factoring sizes and looking for
powers of two), the simplest strategy for deciding alignments for arrays
seems to be... Using the alignment of the element type.

- Shao Miller
 
T

Tim Rentsch

Shao Miller said:
There is a caveat: It's possible that the standard allows (int [500]) to
have a stricter alignment requirement than (int [502*502]), which would
mean that the cast isn't guaranteed to behave. [snip]

C11's 6.2.8p4 seems to suggest that possible alignments are really
derived from fundamental types.

It may to you, but it doesn't to me, and I don't think it should
to anyone else.
 
T

Tim Rentsch

Philip Lantz said:
I think they do--not explicitly in their documentation, but implicitly
by their definitions of how they handle alignment and pointer
conversions.

Unless or until you're prepared to offer evidence that /all/
parts of a compiler take this into account, including the
optimizer, and take pains to do "the expected thing" in all
cases, I don't see any reason to accept this as true. Just
giving examples of how some sample programs behave is evidence of
/likely/ behavior, but is not evidence for /guaranteed/ behavior.

The problem here is not the pointer arithmetic involved (which is
likely to be done right) but access. As optimizers become more
aggressive, especially in the presence of pointer access, they
try to get more done in parallel, and to get greater latitude
for instruction reordering. One important factor for doing this
is aliasing relationships. If, for example, we have a struct
definition like

struct {
int a;
int b[3];
} x;

then any access done by indexing x.b cannot change the value
of x.a. This might help, for example, if the optimizer wanted
to cache x.a temporarily in a register. Compare that to a
case with a two-dimensional array:

int two_d[4][4];

Any access done by indexing two_d[1] cannot change any of the
values in two_d[0], two_d[2], or two_d[3]. Obviously this
deduction might help an optimizer generate better code in
some circumstances. It is for these sorts of reasons that
the C Standard limits what kinds of accesses can be done
through array types, and why optimizers try to take advantage
of the more restrictive rules. And that's why relying on
out-of-bounds array access is dangerous -- and not just now,
but moreso as time goes on.
 
T

Tim Rentsch

Robert Wessel said:
On Thu, 20 Dec 2012 12:40:48 -0800, Tim Rentsch
[snip]
Indexing in C is not defined just in terms of address
calculation. Address calculation is one aspect, but there
are additional constraints, and those constraints must be
observed; otherwise ALL BETS ARE OFF. The approach
described above violates those constraints. ANY approach
using pointer to array types, that attempts to index an
expression of array type with an index value of -1, will
violate the constraints. There is NO WAY to do what you
want to do using regular arrays or pointers to arrays; use
an array of pointers, and use type (int **) for the
accessing identifer ('tab' in the above) instead.

I suspect that might be true, but I haven't been able to find where
the standard prohibits using an index of -1 (as in a[-1]), so long as
the underlying object exists at *(a-1). If you've found it, please
share.

Unfortunately the Standard doesn't do a good job of stating
this rule clearly in normative text, so the best reference
I can give you is Annex J.2 (listing undefined behaviors).
However I think the statement there is clearly on point:

An array subscript is out of range, even if an object is
apparently accessible with the given subscript (as in the
lvalue expression a[1][7] given the declaration int a[4][5])
(6.5.6).

(This text appears on page 560 of N1570.)

================

P.S. In my news reader, the quoted text in your posting had no
spaces between the > and the line being quoted. Can you set
your news reader to put a space in there? I find it much
harder to read without any intervening white space.
 
F

fir

W dniu czwartek, 20 grudnia 2012 22:38:07 UTC+1 użytkownik Ben Bacarisse napisał:
fir said:
W dniu czwartek, 20 grudnia 2012 14:38:45 UTC+1 użytkownik Ben Bacarisse napisał:
I think the OP wants an 'dead' edge all the way round. I.e. I think
they want:

int wider_tab[(N+2)*(N+2)];
int (*tab)[N+2] = (int (*)[N+2])&wider_tab[N+2+1];

(for N=500). You could also (probably) get away with using plain 2D
arrays for a little more clarity:

int wider_tab[N+2][N+2];
int (*tab)[N+2] = (void *)&wider_tab[1][1];

that is exactly what i want, but here above is it vector of pointers
or lite/solid block of addresable ram (with no other area pointers?),
(somewhat sad to say but i forgot of was atways somewhat out to array
pointer subtlities :/ like this)



Sorry, but I can't understand enough of the that to answer what seems to
be a question in it. I hazard a guess: What I wrote uses a pointer
into a single 2D array. There are no other pointers involved (it's not
an array of pointers.

what way "int (*tab)[N+2]" should be read?


tab is a pointer to an array of N+2 ints. http://www.bsb.me.uk/c-types
Allright. Tnx for the answers, that (I mean "int (*tab)[N+2] = (void *)&wider_tab[1][1];" ) was I was searching for - if it works, (i will check it when I will need it l8r) But Probably it will work, so it is good news, seeya all (till next time;)
 
S

Shao Miller

Shao Miller said:
There is a caveat: It's possible that the standard allows (int [500]) to
have a stricter alignment requirement than (int [502*502]), which would
mean that the cast isn't guaranteed to behave. [snip]

C11's 6.2.8p4 seems to suggest that possible alignments are really
derived from fundamental types.

It may to you, but it doesn't to me, and I don't think it should
to anyone else.

Well in that case, I'd suggest that N1570's 6.5.3.4p3 is more suggestive:

"The _Alignof operator yields the alignment requirement of its
operand type. The operand is not evaluated and the result is an integer
constant. When applied to an array type, the result is the alignment
requirement of the element type."

- Shao Miller
 
K

Keith Thompson

Shao Miller said:
Shao Miller said:
On 12/20/2012 03:28, Philip Lantz wrote:

There is a caveat: It's possible that the standard allows (int [500]) to
have a stricter alignment requirement than (int [502*502]), which would
mean that the cast isn't guaranteed to behave. [snip]

C11's 6.2.8p4 seems to suggest that possible alignments are really
derived from fundamental types.

It may to you, but it doesn't to me, and I don't think it should
to anyone else.

Well in that case, I'd suggest that N1570's 6.5.3.4p3 is more suggestive:

"The _Alignof operator yields the alignment requirement of its
operand type. The operand is not evaluated and the result is an integer
constant. When applied to an array type, the result is the alignment
requirement of the element type."

So *some* alignments are derived from fundamental types: those of the
fundamental types themselves, and those of arrays of fundamental types
(and, by induction, arrays of arrays of fundamental types, and so
forth).

But a struct or union may legally have an alignment that exceeds the
alignment of any of its members, or of any fundamental type.
 
S

Shao Miller

Shao Miller said:
On 12/20/2012 03:28, Philip Lantz wrote:

There is a caveat: It's possible that the standard allows (int [500]) to
have a stricter alignment requirement than (int [502*502]), which would
mean that the cast isn't guaranteed to behave. [snip]

C11's 6.2.8p4 seems to suggest that possible alignments are really
derived from fundamental types.

It may to you, but it doesn't to me, and I don't think it should
to anyone else.

Well in that case, I'd suggest that N1570's 6.5.3.4p3 is more suggestive:

"The _Alignof operator yields the alignment requirement of its
operand type. The operand is not evaluated and the result is an integer
constant. When applied to an array type, the result is the alignment
requirement of the element type."

So *some* alignments are derived from fundamental types: those of the
fundamental types themselves, and those of arrays of fundamental types
(and, by induction, arrays of arrays of fundamental types, and so
forth).

But a struct or union may legally have an alignment that exceeds the
alignment of any of its members, or of any fundamental type.

Agreed. Perhaps the "factors of the size that are powers of 2" argument
elsethread can provide additional confidence. I never meant to suggest
that extended alignments[N1570:6.2.8p3] were not allowed, but perhaps my
wording was off... Please allow me to retract and substitute:

"C11's 6.2.8p4 seems to suggest that possible alignments are more
expected to derive from fundamental types than to be extended
alignments, since there may be none of the latter."

I guess it's a Bayesian argument?

- Shao Miller
 
S

Shao Miller

Shao Miller said:
On 12/21/2012 12:37, Tim Rentsch wrote:

On 12/20/2012 03:28, Philip Lantz wrote:

There is a caveat: It's possible that the standard allows (int
[500]) to
have a stricter alignment requirement than (int [502*502]), which
would
mean that the cast isn't guaranteed to behave. [snip]

C11's 6.2.8p4 seems to suggest that possible alignments are really
derived from fundamental types.

It may to you, but it doesn't to me, and I don't think it should
to anyone else.


Well in that case, I'd suggest that N1570's 6.5.3.4p3 is more
suggestive:

"The _Alignof operator yields the alignment requirement of its
operand type. The operand is not evaluated and the result is an integer
constant. When applied to an array type, the result is the alignment
requirement of the element type."

So *some* alignments are derived from fundamental types: those of the
fundamental types themselves, and those of arrays of fundamental types
(and, by induction, arrays of arrays of fundamental types, and so
forth).

But a struct or union may legally have an alignment that exceeds the
alignment of any of its members, or of any fundamental type.

Agreed. Perhaps the "factors of the size that are powers of 2" argument
elsethread can provide additional confidence. I never meant to suggest
that extended alignments[N1570:6.2.8p3] were not allowed, but perhaps my
wording was off... Please allow me to retract and substitute:

"C11's 6.2.8p4 seems to suggest that possible alignments are more
expected to derive from fundamental types than to be extended
alignments, since there may be none of the latter."

I guess it's a Bayesian argument?

If the context and other bits hadn't've been snipped, perhaps it
might've been clearer that I was talking about "confidence" and not
impossibly making a claim about something which is discussed one
paragraph above my reference. Please make the effort to consider
context, all. (Not directed at anyone in particular.) Thanks! :)
 
T

Tim Rentsch

Shao Miller said:
Shao Miller said:
On 12/20/2012 03:28, Philip Lantz wrote:

There is a caveat: It's possible that the standard allows (int [500]) to
have a stricter alignment requirement than (int [502*502]), which would
mean that the cast isn't guaranteed to behave. [snip]

C11's 6.2.8p4 seems to suggest that possible alignments are really
derived from fundamental types.

It may to you, but it doesn't to me, and I don't think it should
to anyone else.

Well in that case, I'd suggest that N1570's 6.5.3.4p3 is more
suggestive: [snip]

And the writing in 6.2.5 p13 suggests that the alignment of array
types may be different than the alignment of their element types,
but neither of those observations is relevant to the point I was
making.
 
K

Keith Thompson

Shao Miller said:
So *some* alignments are derived from fundamental types: those of the
fundamental types themselves, and those of arrays of fundamental types
(and, by induction, arrays of arrays of fundamental types, and so
forth).

But a struct or union may legally have an alignment that exceeds the
alignment of any of its members, or of any fundamental type.

Agreed. Perhaps the "factors of the size that are powers of 2" argument
elsethread can provide additional confidence. I never meant to suggest
that extended alignments[N1570:6.2.8p3] were not allowed, but perhaps my
wording was off... Please allow me to retract and substitute:

"C11's 6.2.8p4 seems to suggest that possible alignments are more
expected to derive from fundamental types than to be extended
alignments, since there may be none of the latter."

It suggests no such thing. There may or may not be extended
alignments. The standard says nothing about which possibility is
"more expected".

I just noticed something interesting. N1570 uses the phrase
"fundamental types" only twice, both times in the context
of alignment (the second occurrence is in Annex J, which is
non-normative). But it never defines the term. I suppose I've
been assuming that it refers to types other than array, structure,
and union types, but we already have a term for those: scalar types.

There's a distinction between "fundamental alignment" and "extended
alignment". As I understand it, the fundamental alignments are the
default alignments of any type (yielded by _Alignof in the absence
of any alignment specifier); the _Alignas keyword can specify either
a fundamental alignment or an extended alignment.

The maximum fundamental alignment is _Alignof (max_align_t).
Note that max_align_t is merely specified to be an object type;
it needn't be scalar.
I guess it's a Bayesian argument?

Not sure what you mean by that.
 
K

Keith Thompson

Tim Rentsch said:
And the writing in 6.2.5 p13 suggests that the alignment of array
types may be different than the alignment of their element types,
but neither of those observations is relevant to the point I was
making.

It's a weak suggestion at best:

Each complex type has the same representation and alignment
requirements as an array type containing exactly two elements
of the corresponding real type; the first element is equal to
the real part, and the second element to the imaginary part,
of the complex number.

The fact that it refers to the alignment requirements of the array
type, rather than of the element type, *might* suggest that they
could differ, but I think it was just easier to word it that way.
6.5.3.4p3 (already quoted in this thread) explicitly says they're
the same.

Which I suspect is what you meant, but I wasn't sure.
 
K

Keith Thompson

Shao Miller said:
On 12/22/2012 00:48, Shao Miller wrote: [...]
Agreed. Perhaps the "factors of the size that are powers of 2" argument
elsethread can provide additional confidence. I never meant to suggest
that extended alignments[N1570:6.2.8p3] were not allowed, but perhaps my
wording was off... Please allow me to retract and substitute:

"C11's 6.2.8p4 seems to suggest that possible alignments are more
expected to derive from fundamental types than to be extended
alignments, since there may be none of the latter."

I guess it's a Bayesian argument?

If the context and other bits hadn't've been snipped, perhaps it
might've been clearer that I was talking about "confidence" and not
impossibly making a claim about something which is discussed one
paragraph above my reference. Please make the effort to consider
context, all. (Not directed at anyone in particular.) Thanks! :)

Having read most or all of the context in this thread, I'm afraid
I have no idea what it is that you're confident about.
 

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

Forum statistics

Threads
474,077
Messages
2,570,567
Members
47,204
Latest member
abhinav72673

Latest Threads

Top