473,416 Members | 1,974 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,416 software developers and data experts.

array padding

Hello,
Is the behaviour of indexing an array with a negative number (like a[-1])
defined by the standard?
Nov 14 '05 #1
19 7731
buda <ku*****@hotmail.com> wrote:
Hello,
Is the behaviour of indexing an array with a negative number (like a[-1])
defined by the standard?


Not 101% certain, but a[n] should point to *(a+(sizeof(*a)*n)), so it should
be *(a+(sizeof(a)*-1)), that is 1 memory-spot before a starts.
Nov 14 '05 #2
"buda" <ku*****@hotmail.com> writes:
Is the behaviour of indexing an array with a negative number (like
a[-1]) defined by the standard?


If the expression refers to an existing array element, then yes.
Otherwise, the behavior is undefined.

For example, given the code

int b [3];
int *a = b + 1;

the expression `a [-1]' is valid and refers to the same object as
`b [0]'.

Martin
--
,--. Martin Dickopp, Dresden, Germany ,= ,-_-. =.
/ ,- ) http://www.zero-based.org/ ((_/)o o(\_))
\ `-' `-'(. .)`-'
`-. Debian, a variant of the GNU operating system. \_/
Nov 14 '05 #3
buda wrote:
Hello,
Is the behaviour of indexing an array with a negative number (like a[-1])
defined by the standard?


It's undefined behaviour. See section 6.5.6 of the 1999 C standard.

Allin Cottrell
Nov 14 '05 #4
Viktor Lofgren <ro**@eudial.nos--pam.mine.nu> writes:
buda <ku*****@hotmail.com> wrote:
Hello,
Is the behaviour of indexing an array with a negative number (like
a[-1]) defined by the standard?


Not 101% certain, but a[n] should point to *(a+(sizeof(*a)*n)),


Your statement is misleading. First of all, `a [n]' is not necessarily
a pointer, so it's not necessarily pointing to anything. You probably
mean "the address of `a [n]' is the same as ...".

More importantly, the address of `a [n]' is the same as the address of
`*(a + n)', which is different from `*(a + (sizeof (*a) * n))' unless
`sizeof *a' happens to be 1. However the address of `a [n]' is the same
as the address of `*((char *)a + (sizeof (*a) * n))', i.e. the addresses
of `a' and `a [n]' differ by `sizeof (*a) * n' bytes.

Martin
--
,--. Martin Dickopp, Dresden, Germany ,= ,-_-. =.
/ ,- ) http://www.zero-based.org/ ((_/)o o(\_))
\ `-' `-'(. .)`-'
`-. Debian, a variant of the GNU operating system. \_/
Nov 14 '05 #5
Martin Dickopp <ex****************@zero-based.org> wrote:
More importantly, the address of `a [n]' is the same as the address of
`*(a + n)', which is different from `*(a + (sizeof (*a) * n))' unless
`sizeof *a' happens to be 1. However the address of `a [n]' is the same
as the address of `*((char *)a + (sizeof (*a) * n))', i.e. the addresses
of `a' and `a [n]' differ by `sizeof (*a) * n' bytes.


No, if a is int_32*, a[n] = *(a + 4 * n).
For an example:

int* b = NULL;
printf("%d %d", &b[0], &b[1]);

prints "0 4" when executed, if a[n] would be *(a+n), it would print "0 1".
Nov 14 '05 #6
In article <2w***************@newsb.telia.net>,
Viktor Lofgren <ro**@eudial.nos--pam.mine.nu> wrote:
Martin Dickopp <ex****************@zero-based.org> wrote:
More importantly, the address of `a [n]' is the same as the address of
`*(a + n)', which is different from `*(a + (sizeof (*a) * n))' unless
`sizeof *a' happens to be 1. However the address of `a [n]' is the same
as the address of `*((char *)a + (sizeof (*a) * n))', i.e. the addresses
of `a' and `a [n]' differ by `sizeof (*a) * n' bytes.


No, if a is int_32*, a[n] = *(a + 4 * n).
For an example:

int* b = NULL;
printf("%d %d", &b[0], &b[1]);

prints "0 4" when executed, if a[n] would be *(a+n), it would print "0 1".


I suggest you try

int a [10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
int n = 1;

printf ("%d %d\n", a [n], * (a + 4 * n));

and tell us what happens.
Nov 14 '05 #7
Viktor Lofgren <ro**@eudial.nos--pam.mine.nu> writes:
Martin Dickopp <ex****************@zero-based.org> wrote:
More importantly, the address of `a [n]' is the same as the address of
`*(a + n)', which is different from `*(a + (sizeof (*a) * n))' unless
`sizeof *a' happens to be 1. However the address of `a [n]' is the same
as the address of `*((char *)a + (sizeof (*a) * n))', i.e. the addresses
of `a' and `a [n]' differ by `sizeof (*a) * n' bytes.
No, if a is int_32*, a[n] = *(a + 4 * n).


No. Please look up in your C book what the effect of the `+' operator
is if one operand is a pointer and the other is an integer.
For an example:

int* b = NULL;
printf("%d %d", &b[0], &b[1]);

prints "0 4" when executed, if a[n] would be *(a+n), it would print "0 1".


This code fragment invokes undefined behavior for two reasons: First of
all, the "%d" specifier expects an `int' argument, but `&b[0]' and
`&b[1]' have type `int *'. Secondly, it is undefined behavior to add
something to a null pointer, as is done in the expression `&b[1]'.

Since the code invokes undefined behavior, anything could have happened,
including printing "0 4", printing "0 1", or printing a Shakespearean
sonnet.

If you really want a program that demonstrates that you're wrong, try
this one:
#include <stdio.h>

int main (void)
{
int a [4];
printf ("address of a [1] is %p\n", (void *)&a [1]);
printf ("address of *(a + 1) is %p\n", (void *)&*(a + 1));
printf ("address of *(a + 4 * 1) is %p\n", (void *)&*(a + 4 * 1));
return 0;
}
Martin
--
,--. Martin Dickopp, Dresden, Germany ,= ,-_-. =.
/ ,- ) http://www.zero-based.org/ ((_/)o o(\_))
\ `-' `-'(. .)`-'
`-. Debian, a variant of the GNU operating system. \_/
Nov 14 '05 #8
>> More importantly, the address of `a [n]' is the same as the address of
`*(a + n)', which is different from `*(a + (sizeof (*a) * n))' unless
`sizeof *a' happens to be 1. However the address of `a [n]' is the same
as the address of `*((char *)a + (sizeof (*a) * n))', i.e. the addresses
of `a' and `a [n]' differ by `sizeof (*a) * n' bytes.
No, if a is int_32*, a[n] = *(a + 4 * n).


No. I think you mean a[n] = *(a addl (4 mull n))
where addl and mull are assembly-language arithmetic operators.
For an example:

int* b = NULL;
printf("%d %d", &b[0], &b[1]);

prints "0 4" when executed, if a[n] would be *(a+n), it would print "0 1".


C operators are different from assembly-language ones, especially
when pointers are involved.

Also, there is no guarantee that sizeof(a 32-bit integer type) does not
equal 1.

Gordon L. Burditt
Nov 14 '05 #9
Allin Cottrell wrote:

buda wrote:
Hello,
Is the behaviour of indexing an array with a negative number (like a[-1])
defined by the standard?


It's undefined behaviour. See section 6.5.6 of the 1999 C standard.

Allin Cottrell


Maybe you could give us a wee bit more to go on...
Since we might be looking at two different documents,
are you refering to the section titled -

"6.5.6 Additive operators"?

I'm not sure how the following is "undefined behaviour"...

/********************************************/

#include <stdio.h>
int
main()
{
char str[] = "1234567890";
char *p = &str[ sizeof (str) - 1 ]; /* `p' points to string's
NULL */
printf("Character should be '0', '%c'.\n", p[ -1 ]);
printf("Character should be '9', '%c'.\n", p[ -2 ]);

printf("Character should be '0', '%c'\n", *(p - 1));
printf("Character should be '9', '%c'\n", *(p - 2));

printf("Same as above, '0', '%c'.\n", *--p); /* Is _this_ undefined
too? */
printf("Same as above, '9', '%c'.\n", *--p);

return (0);
}
--
Stephen
Nov 14 '05 #10

On Sat, 22 May 2004, Stephen L. wrote:

Allin Cottrell wrote:
buda wrote:
Is the behaviour of indexing an array with a negative number (like a[-1])
defined by the standard?
It's undefined behaviour. See section 6.5.6 of the 1999 C standard.


I'm not sure how the following is "undefined behaviour"...


It's not. However, if 'a' is, as the OP said, an array name, then
indeed indexing 'a' with a negative subscript will dereference a pointer
that's not pointing to an object. E.g.,

foo a[bar]; a[-1];

is *always*, without exception, undefined behavior.

Doing the same thing with a pointer, e.g.

baz *p = quux; p[-1];

may or may not invoke UB, depending on the value of 'quux'. In your
example, there is no undefined behavior.

-Arthur

#include <stdio.h>

int
main()
{
char str[] = "1234567890";
char *p = &str[ sizeof (str) - 1 ]; /* `p' points to string's
NULL */
printf("Character should be '0', '%c'.\n", p[ -1 ]);
printf("Character should be '9', '%c'.\n", p[ -2 ]);

printf("Character should be '0', '%c'\n", *(p - 1));
printf("Character should be '9', '%c'\n", *(p - 2));

printf("Same as above, '0', '%c'.\n", *--p); /* Is _this_ undefined
too? */
printf("Same as above, '9', '%c'.\n", *--p);

return (0);
}

Nov 14 '05 #11
"Stephen L." <sd*********@cast-com.net> writes:
char str[] = "1234567890";
char *p = &str[ sizeof (str) - 1 ]; /* `p' points to string's
NULL */


ITYM null character instead of NULL. (NULL is a macro which expands to
a null /pointer/ constant.)

Martin
--
,--. Martin Dickopp, Dresden, Germany ,= ,-_-. =.
/ ,- ) http://www.zero-based.org/ ((_/)o o(\_))
\ `-' `-'(. .)`-'
`-. Debian, a variant of the GNU operating system. \_/
Nov 14 '05 #12
In article <news:2w***************@newsb.telia.net>
Viktor Lofgren <ro**@eudial.nos--pam.mine.nu> writes:
For an example:

int* b = NULL;
printf("%d %d", &b[0], &b[1]);

prints "0 4" when executed, if a[n] would be *(a+n), it would print "0 1".


I ran this on a Data General Eclipse[%] and it printed:

1879048192 1879048194

Can you explain this?

(Convert the above to hex for a big hint. The numbers are 0x70000000
and 0x70000002 respectively. The facts that sizeof(int) is 4 and
that "int *" uses "word pointers", with 16-bit words, are both
important.)

[% Actually I do not have access to one, but this is what it might
print, if I remember right. I made up a segment-and-ring number
of 0x7 and am not sure that this is correct for user-mode code, or
even the right number of bits.]
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W) +1 801 277 2603
email: forget about it http://web.torek.net/torek/index.html
Reading email is like searching for food in the garbage, thanks to spammers.
Nov 14 '05 #13
"buda" <ku*****@hotmail.com> writes:
Hello,
Is the behaviour of indexing an array with a negative number (like a[-1])
defined by the standard?


If a is an array object, then evaluating a[-1] invokes undefined
behavior.

Array indexing is really a binary operation ("binary" meaning it takes
two operands); the left operand is a pointer to some object type, and
the right operand is an integer (or vice versa; see below). x[y] is
equivalent to *(x+y). Since x is a pointer and y is an integer, the
"+" performs pointer arithmetic.

If "a" points into the middle of an array object, "a[-1]" yields the
value of the array element just before the one that "a" points to.

It may seem odd that the left operand is expected to be a pointer, not
an array. It works for arrays because, in most expression contexts,
an array name is converted to a pointer to its first element.

(x[y] is equivalent to *(x+y). Since addition is commutative, *(x+y)
is equivalent to *(y+x), which is equivalent to y[x]. Thus
5["abcdef"] is a legal expression, equal to 'f'. This is interesting,
but not particularly useful.)

See section 6 of the C FAQ <http://www.eskimo.com/~scs/C-faq/top.html>
for more information. While you're there, read the whole thing.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Nov 14 '05 #14
buda wrote:

Hello,
Is the behaviour of indexing an array with a negative number (like a[-1])
defined by the standard?

You can do something like the following;

#include <stdio.h>
#include <stdlib.h>

int main()
{
int *a, *b;

b = malloc(21 * sizeof int);

a = b + 11;

a[5] = 42;

a[-5] = 24;

printf("The values are %d and %d\n",a[5],a[-5]);
}

This technique can be useful when converting a Pascal program
that is using negative subscripts.


--
+----------------------------------------------------------------+
| Charles and Francis Richmond richmond at plano dot net |
+----------------------------------------------------------------+
Nov 14 '05 #15
In <c8********@news3.newsguy.com> Chris Torek <no****@torek.net> writes:
I ran this on a Data General Eclipse[%] and it printed:
<snip>
[% Actually I do not have access to one, but this is what it might
print, if I remember right.


Did anyone implement standard C on it? How about K&R C?

Dan
--
Dan Pop
DESY Zeuthen, RZ group
Email: Da*****@ifh.de
Nov 14 '05 #16
>In <c8********@news3.newsguy.com> Chris Torek <no****@torek.net> writes:
I ran this on a Data General Eclipse[%] ...
[% Actually I do not have access to one, but this is what it might
print, if I remember right.

In article <news:c8***********@sunnews.cern.ch>
Dan Pop <Da*****@cern.ch> asked:Did anyone implement standard C on it? How about K&R C?


I am not at all sure about Standard C. The machine I used ran
a (somewhat bizarre and twisted variation on) 4.2BSD Unix. The
C compiler implemented everything required to compile typical
Unix programs. I think that covers "K&R C" and then some -- the
compiler had enumerations and "unsigned char", for instance.

Quite a lot of our C code had to be fixed up not to make assumptions
about pointer formats.

Besides the pointer trickiness, the main thing I remember about
the Eclipse is that the output from perror() was broken. It printed
a two digit error number, followed by no whitespace, followed by
the string, so that one would get things like:

prog: cannot open foo.dat: 02No such file or directory

(I also remember something about bogus newlines, perhaps before the
"02".)

(This machine and the Pyramid were responsible for our group at
the University of Maryland making numerous fixes to varous programs.
The Pyramid found non-pointer bugs. For instance, MH used the
interesting calling sequence "parameter passing by register
assumption"[%], which was impossible on the Pyramid due to its
register windows. The Pyramid also exposed all the programs that
failed to "return 0" or "exit(0)" from main. Return values from
functions had to be stored in register "pr0" in the register-window
assigned to that function, and calling some other function did not
affect one's own pr0, only one's tr0. Hence, programs that on the
VAX returned whatever was left in r0 -- which was the return value
from the most-recently-called function -- instead returned their
first argument. For main(), this was the parameter argc.)

[% An illustration, not necessarily the actual MH code and using
ANSI C syntax rather than Classic C:

void f1(struct S *param) {
register int a, b;
register FILE *some_file;
...
some_file = fopen("some_path", "w");
f2(param, a);
...
}

void f2(register struct S *param, register int a) {
register FILE *fp; /* NOTE: NOT INITIALIZED! */
...
fprintf(fp, "%s: %d\n", param->zig, a);
...
}

This worked on the VAX, and even the PDP-11, because the machine's
registers were handed out in a fixed, known order. On the VAX,
"some_file" wound up in r9; on the PDP-11 it was in r3. In each
case, declaring "fp" third in f2() caused the C compiler to reserve
the same register -- which still held the opened FILE *! The VAX
C compiler gave you six registers, while the PDP-11 gave you only
three, so the actual "parameter passing by register assumption" in
MH was definitely in the first six "register" variables, and almost
certainly in the first three.]
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W) +1 801 277 2603
email: forget about it http://web.torek.net/torek/index.html
Reading email is like searching for food in the garbage, thanks to spammers.
Nov 14 '05 #17
C will allow you to use a negative index. The index into an array is
signed integer. I guess you can use negative indices if you make sure
that the memory before the start of the array is allocated for this.

I remember seeing use of negative in Tanenbaum's MINIX book. The
positive indices were used as user task pids and negative indices
were used for MINIX tasks.

Sandeep
--
http://www.EventHelix.com/EventStudio
EventStudio 2.0 - Generate Sequence Diagrams and Use Case Diagrams in PDF
Nov 14 '05 #18


EventHelix.com wrote:
... The index into an array is
signed integer. I guess you can use negative indices if you make sure
that the memory before the start of the array is allocated for this.


Doing this little trick is not C. A resource other than the
the ISO/IEC Internation Standard may suggest this and your compiler may
accept it in a way you expect. But that does not make it C. The C
Language describes this as undefined behavior.

The Standard specifically describes many circumstances of
undefined behavor. The following circumstance seems to make operation
clearly UB.

— Addition or subtraction of a pointer into, or just beyond,
an array object and an integer type produces a result that
does not point into, or just beyond, the same array object (6.5.6).
--
Al Bowers
Tampa, Fl USA
mailto: xa******@myrapidsys.com (remove the x to send email)
http://www.geocities.com/abowers822/

Nov 14 '05 #19
ev********@hotmail.com (EventHelix.com) writes:
C will allow you to use a negative index. The index into an array is
signed integer. I guess you can use negative indices if you make sure
that the memory before the start of the array is allocated for this.

I remember seeing use of negative in Tanenbaum's MINIX book. The
positive indices were used as user task pids and negative indices
were used for MINIX tasks.


I'll bet that the "array" being indexed with a negative integer was
actually a pointer into the middle of an array object.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Nov 14 '05 #20

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

35
by: Scott Kelley | last post by:
Is there a way to reset all elements of an array with a single instruction? I want to set all elements to zero. Currently looping to do so. thx, Scott Kelley
6
by: Eric Smith | last post by:
Is a structure containing an incomplete array as its last element (per paragraph 2 of section 6.7.2.1 of ISO/IEC 9899:1999 (E)) itself an incomplete type? That appears to be indicated by paragraph...
13
by: Amarendra | last post by:
Folks, This structure padding issue is bothering me now, could not locate a satisfactory answer on clc, so here it goes... I have a structure, given below: typedef struct { int flag; char...
9
by: buda | last post by:
Hi, I've been wondering for a while now (and always forgot to ask :) what is the exact quote from the Standard that forbids the use of (&array) (when x >= number_of_columns) as stated in the FAQ...
3
by: Eric Laberge | last post by:
Aloha! I've been reading the standard (May '05 draft, actually) and stumbled across this: 6.7.1 Initialization §20 "If the aggregate or union contains elements or members that are aggregates...
20
by: Lalatendu Das | last post by:
hi let's say i have a structure struct test { int A; char B; int C; }; this above structure defination always going to take 16 byte in memeory in whatever manner we align the member variables...
24
by: Kavya | last post by:
int main (){ int a={{1,2,3},{4,5,6}}; int (*ptr)=a; /* This should be fine and give 3 as output*/ printf("%d\n",(*ptr)); ++ptr;
6
by: Francois Grieu | last post by:
Hello, I'm asking myself all kind of questions on allocating an array of struct with proper alignment. Is the following code oorrect ? I'm most interested by the statement t =...
13
by: aarklon | last post by:
Hi all, arrays are guaranteed to be contiguous with no padding before or after any array member , but what about enums ..???
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.