From: Charles Richmond on 8 Mar 2010 18:26 Joe Pfeiffer wrote: > Charles Richmond <frizzle(a)tx.rr.com> writes: >> ... but do *not* forget that when an integer is added to a pointer, >> that integer is "scaled" by the length associated with that >> pointer. So if "a" is a pointer to a four byte integer, then "a+1" >> actually adds *four* to the pointer. The integer "1" is scaled by the >> length of the object pointed to by "a". > > That fact took me several painful days to learn. I had (in a project I > don't remember, for reasons I don't remember) used the + syntax > dereferencing a buffer of integers, and had scaled it myself. Which > meant, of course, that everything seemed fine for a ways into the > buffer, then mysteriously segfaulted. > > Hmmm... I've got quite a few like that, with vividly remembered bugs in > totally forgotten projects. This scaling of an integer when added to a pointer... is fundamental to the way C arrays and the array operator works. -- +----------------------------------------+ | Charles and Francis Richmond | | | | plano dot net at aquaporin4 dot com | +----------------------------------------+
From: Charles Richmond on 8 Mar 2010 18:36 Ahem A Rivet's Shot wrote: > On Sun, 7 Mar 2010 18:59:43 +0000 (UTC) > johnf(a)panix.com (John Francis) wrote: > >> In article <20100307143020.fcc7e3df.steveo(a)eircom.net>, >> Ahem A Rivet's Shot <steveo(a)eircom.net> wrote: >>> On Sun, 07 Mar 2010 07:48:01 -0500 >>> Greg Menke <gusenet(a)comcast.net> wrote: >>> >>>> Ahem A Rivet's Shot <steveo(a)eircom.net> writes: >>>>> The C subscript operator does do nothing other than adding >>>>> two numbers and dereferencing the result, that last action is rather >>>>> important. The validity of constructs like 2[a] and *(2+a) make this >>>>> clear - as does the equivalence of a and &(a[0]) or of *a and a[0] >>>>> where a is a pointer. >>>> Yet when dereferencing arrays of rank >= 2, dimensions are >>>> automatically incorporated into the effective address, so its not >>>> quite equivalent to a simple addition of pointer and offset. >>> There is a way to regard it as such - consider a[x][y] as being >>> equivalent to *(a[x] + y) where we regard a[x] as devolving into a >>> pointer to a row of the array. But yes multidimensional array support is >>> a little more involved than single dimensional array support. It's still >>> not a proper type though. >> That's all very well, but in fact no C implementation of which I am >> aware uses dope vectors when allocating multidimensional arrays. (I > > Indeed they don't - it is simply a matter of how you interpret the > partial construct a[x] when a is declared as a two dimensional array - one > way of interpreting it is as a pointer to an array row even though it is > not a valid construct on it's own. > > There is a clear extension of the one dimentsional case a declaration > int a[5] leaves future references to a as being equivalent to &(a[0]) so > it is reasonable to regard a declaration int a[4][5] as leaving future > references like a[i] as equivalent to &(a[i][0]). > One important point is: a two-dimensional array is a double indirection. The construct "x[5][8]" is equivalent to "*(*(x+5)+8)". Each of those two "*" does a dereference. >> have come across the practice in other languages). In fact C has to >> perform different calculations to evaluate the address of an element >> a[i][j], depending on how a was defined (int a[4][5], or int** a). >> The sizeof operator also knows something about array types. > > If a is defined as int **a then a[i][j] is not valid at all. > *Not* completely true. If a is a pointer to a pointer, it can be dereference with **a: x = **a; equivalently, this can be written: x = a[0][0]; since it is equivalent to: x = *(*(a+0)+0); -- +----------------------------------------+ | Charles and Francis Richmond | | | | plano dot net at aquaporin4 dot com | +----------------------------------------+
From: Anssi Saari on 9 Mar 2010 09:56 Charles Richmond <frizzle(a)tx.rr.com> writes: > Yes, "2[c]" does work in C as well as "c[2]", and yields the same > results. The definition of "c[x]" is "*(c+x)", where the array "c" > becomes a pointer to the first element, and the integer value "x" is > scaled by the length associated with the pointer "c". "*(c+x)" will > give the same result as "*(x+c)", so it's logical. Just curious, but why is it that "2[c]" doesn't seem to work as an argument to printf? This simple example gives an error at compile, for example: #include <stdio.h> int main() { char c[] = "12345678"; printf("%c\n", [2]c); } gcc says: array_fun_mini_example.c: In function 'main': array_fun_mini_example.c:6: error: expected expression before '[' token I'm using gcc 4.3.2. Assignment like 2[c] = '1' and reading a value like tmp = 2[c] seem to work fine, though.
From: Joe Pfeiffer on 9 Mar 2010 10:20 Anssi Saari <as(a)sci.fi> writes: > Charles Richmond <frizzle(a)tx.rr.com> writes: > >> Yes, "2[c]" does work in C as well as "c[2]", and yields the same >> results. The definition of "c[x]" is "*(c+x)", where the array "c" >> becomes a pointer to the first element, and the integer value "x" is >> scaled by the length associated with the pointer "c". "*(c+x)" will >> give the same result as "*(x+c)", so it's logical. > > Just curious, but why is it that "2[c]" doesn't seem to work as an > argument to printf? This simple example gives an error at compile, for > example: > > #include <stdio.h> > > int main() > { > char c[] = "12345678"; > printf("%c\n", [2]c); > } > > gcc says: > > array_fun_mini_example.c: In function 'main': > array_fun_mini_example.c:6: error: expected expression before '[' token > > I'm using gcc 4.3.2. Assignment like 2[c] = '1' and reading a value > like tmp = 2[c] seem to work fine, though. Possibly because your program uses [2]c, not 2[c]. -- As we enjoy great advantages from the inventions of others, we should be glad of an opportunity to serve others by any invention of ours; and this we should do freely and generously. (Benjamin Franklin)
From: Michael Wojcik on 9 Mar 2010 13:40
Peter Flass wrote: > Michael Wojcik wrote: >> Peter Flass wrote: >>> Hey! C's finally caught up to PL/I. Only took them 50 years, and then >>> of course all the features are just tacked-on in true C fashion, instead >>> of thought-through. >> >> Well, that's rather insulting to the members of WG14, who spent a >> decade designing those features. Fortunately, they published the >> Rationale showing that, in fact, they were thought through.[1] And a >> great deal of documentation describing the process is available in the >> archives.[2] >> >> If you'd care to show why you think otherwise, perhaps there would be >> some grounds for debate. > > "The flexible array must be last"? Doing otherwise would break existing code. WG14's remit is to maintain upward compatibility. > "sizeof applied to the structure ignores the array but counts any > padding before it"? I have no idea what you're quoting there. That phrase doesn't seem to be present in my copy of the standard. > C is a collection of ad-hoc ideas. WG14 may have put a great deal of > thought into how to extend it without breaking the existing mosh, but > that's my point, it's still a mosh. If that was your point, then I have to say it was rather ill-expressed. -- Michael Wojcik Micro Focus Rhetoric & Writing, Michigan State University |