Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.c > #24852 > unrolled thread
| Started by | gdotone@gmail.com |
|---|---|
| First post | 2012-08-24 08:28 -0700 |
| Last post | 2012-09-07 06:28 -0700 |
| Articles | 13 on this page of 33 — 17 participants |
Back to article view | Back to comp.lang.c
2D arrays, pointers, and pointer arithmetic: question gdotone@gmail.com - 2012-08-24 08:28 -0700
Re: 2D arrays, pointers, and pointer arithmetic: question Adrian Ratnapala <adrian.ratnapala@gmail.com> - 2012-08-24 08:41 -0700
Re: 2D arrays, pointers, and pointer arithmetic: question James Kuyper <jameskuyper@verizon.net> - 2012-08-24 12:01 -0400
Re: 2D arrays, pointers, and pointer arithmetic: question 88888 Dihedral <dihedral88888@googlemail.com> - 2012-08-24 11:10 -0700
Re: 2D arrays, pointers, and pointer arithmetic: question gdotone@gmail.com - 2012-08-27 13:35 -0700
Re: 2D arrays, pointers, and pointer arithmetic: question James Kuyper <jameskuyper@verizon.net> - 2012-08-27 16:46 -0400
Re: 2D arrays, pointers, and pointer arithmetic: question Adrian Ratnapala <raka@scooter.fritz.box> - 2012-08-28 19:06 +0000
Re: 2D arrays, pointers, and pointer arithmetic: question Eric Sosman <esosman@ieee-dot-org.invalid> - 2012-08-28 15:22 -0400
Re: 2D arrays, pointers, and pointer arithmetic: question James Kuyper <jameskuyper@verizon.net> - 2012-08-28 15:34 -0400
Re: 2D arrays, pointers, and pointer arithmetic: question Keith Thompson <kst-u@mib.org> - 2012-08-28 14:11 -0700
Re: 2D arrays, pointers, and pointer arithmetic: question James Kuyper <jameskuyper@verizon.net> - 2012-08-28 17:26 -0400
Re: 2D arrays, pointers, and pointer arithmetic: question "io_x" <a@b.c.invalid> - 2012-08-29 09:25 +0200
Re: 2D arrays, pointers, and pointer arithmetic: question Adrian Ratnapala <raka@scooter.fritz.box> - 2012-08-29 07:20 +0000
Re: 2D arrays, pointers, and pointer arithmetic: question James Kuyper <jameskuyper@verizon.net> - 2012-08-29 07:17 -0400
Re: 2D arrays, pointers, and pointer arithmetic: question Adrian Ratnapala <raka@scooter.fritz.box> - 2012-08-29 11:41 +0000
Re: 2D arrays, pointers, and pointer arithmetic: question Eric Sosman <esosman@ieee-dot-org.invalid> - 2012-08-29 08:21 -0400
Re: 2D arrays, pointers, and pointer arithmetic: question Keith Thompson <kst-u@mib.org> - 2012-08-29 11:37 -0700
Re: 2D arrays, pointers, and pointer arithmetic: question Edward Rutherford <edward.p.rutherford79@REMOVETHIS.gmail.com> - 2012-08-29 20:05 +0000
Re: 2D arrays, pointers, and pointer arithmetic: question James Kuyper <jameskuyper@verizon.net> - 2012-08-29 17:27 -0400
Re: 2D arrays, pointers, and pointer arithmetic: question Keith Thompson <kst-u@mib.org> - 2012-08-29 18:05 -0700
Re: 2D arrays, pointers, and pointer arithmetic: question Les Cargill <lcargill99@comcast.com> - 2012-08-29 20:14 -0500
Re: 2D arrays, pointers, and pointer arithmetic: question Malcolm McLean <malcolm.mclean5@btinternet.com> - 2012-08-30 04:47 -0700
Re: 2D arrays, pointers, and pointer arithmetic: question Richard Damon <news.x.richarddamon@xoxy.net> - 2012-09-01 23:47 -0400
Re: 2D arrays, pointers, and pointer arithmetic: question 88888 Dihedral <dihedral88888@googlemail.com> - 2012-09-02 04:43 -0700
Re: 2D arrays, pointers, and pointer arithmetic: question Richard Damon <news.x.richarddamon@xoxy.net> - 2012-09-02 23:12 -0400
Re: 2D arrays, pointers, and pointer arithmetic: question ais523 <ais523@nethack4.org> - 2012-08-30 11:35 +0000
Re: 2D arrays, pointers, and pointer arithmetic: question ralph <nt_consulting64@yahoo.com> - 2012-08-30 11:17 -0500
Re: 2D arrays, pointers, and pointer arithmetic: question Keith Thompson <kst-u@mib.org> - 2012-08-30 13:52 -0700
Re: 2D arrays, pointers, and pointer arithmetic: question Anders Wegge Keller <wegge@wegge.dk> - 2012-08-30 23:13 +0200
Re: 2D arrays, pointers, and pointer arithmetic: question ralph <nt_consulting64@yahoo.com> - 2012-08-31 16:37 -0500
Re: 2D arrays, pointers, and pointer arithmetic: question Barry Schwarz <schwarzb@dqel.com> - 2012-08-27 19:45 -0700
Re: 2D arrays, pointers, and pointer arithmetic: question Keith Thompson <kst-u@mib.org> - 2012-08-27 20:40 -0700
Re: 2D arrays, pointers, and pointer arithmetic: question Tim Rentsch <txr@alumni.caltech.edu> - 2012-09-07 06:28 -0700
Page 2 of 2 — ← Prev page 1 [2]
| From | Les Cargill <lcargill99@comcast.com> |
|---|---|
| Date | 2012-08-29 20:14 -0500 |
| Message-ID | <k1mefd$e60$3@dont-email.me> |
| In reply to | #25471 |
Keith Thompson wrote: > Edward Rutherford <edward.p.rutherford79@REMOVETHIS.gmail.com> writes: >> Keith Thompson wrote: >>> `near` and `far`, which are of course non-standard, can result in >>> different pointer types having different sizes. Passing a `near` or >>> `far` pointer to printf with a "%p" format is likely to give bad results >>> in practice. >> >> Using near or far pointers in any way at all will invoke an undefined >> behavior, so I think it's safe to say bad results are likely with or >> without attempts to printf() such pointers! > > For a C implementation that supports `near`, `far`, `void*`, and > printf's "%p" format, I would expect that casting a `near` or `far` > pointer value to `void*` before passing it to printf would work > "correctly". Of course the standard doesn't guarantee that, but I'd > expect it of any decent C or C-like implementation. > > (I've never used `near` or `far` myself. It's plausible that an > implementation old enough to support them would be too old to support > `void*`.) > The C89 flavors of MSC supported both "void*" and "near"/"far". TINY MODEL FTW! -- Les Cargill
[toc] | [prev] | [next] | [standalone]
| From | Malcolm McLean <malcolm.mclean5@btinternet.com> |
|---|---|
| Date | 2012-08-30 04:47 -0700 |
| Message-ID | <01b58c31-8d92-4ebe-80aa-cb6f8d7c52db@googlegroups.com> |
| In reply to | #25474 |
בתאריך יום חמישי, 30 באוגוסט 2012 02:09:02 UTC+1, מאת Les Cargill: > Keith Thompson wrote: > > The C89 flavors of MSC supported both "void*" and "near"/"far". TINY > MODEL FTW! > The idea of the "models" was that you could write program without the near/far non-standard extensions. Under "huge", if I remember rightly, all pointers were 32 bit and it did some inefficient magic to hide the segments and give you what looked like flat memory. Under "large", pointers were 32 bits but you couldn't allocate a block of more than 64 K. Under "tiny" all code and data had to fit within the same 64K segment, which led to the most efficient machine code. But you could use far pointers to allocate data in other segments. So you ended up rewriting fucntions like "farmemcpy", because the standard library only worked with the standard pointers.
[toc] | [prev] | [next] | [standalone]
| From | Richard Damon <news.x.richarddamon@xoxy.net> |
|---|---|
| Date | 2012-09-01 23:47 -0400 |
| Message-ID | <k1uksa$b2g$1@dont-email.me> |
| In reply to | #25524 |
On 8/30/12 7:47 AM, Malcolm McLean wrote: > בתאריך יום חמישי, 30 באוגוסט 2012 02:09:02 UTC+1, מאת Les Cargill: >> Keith Thompson wrote: >> >> The C89 flavors of MSC supported both "void*" and "near"/"far". TINY >> MODEL FTW! >> > The idea of the "models" was that you could write program without the > near/far non-standard extensions. Under "huge", if I remember rightly, > all pointers were 32 bit and it did some inefficient magic to hide the > segments and give you what looked like flat memory. Under "large", > pointers were 32 bits but you couldn't allocate a block of more than > 64 K. > Under "tiny" all code and data had to fit within the same 64K segment, > which led to the most efficient machine code. But you could use far > pointers to allocate data in other segments. So you ended up rewriting > fucntions like "farmemcpy", because the standard library only worked > with the standard pointers. > > > > The models came about due to the memory structure of the 16 bit x86 architecture. Addresses were in general greater than 16 bits in length, while address registers were only 16 bits long, and were combined with a "segment register" to convert the value to a full address. (depending on what mode the processor was in would change how the conversion was done). Near pointers only stored the value of the address register, and the segment register was assumed by the type of pointer (the Data Segment Register for "data" pointers, and the Program Segment Register for function pointers). In addition, data pointers had a huge type, which was like a far pointer, but could point to an object that might be bigger than a single segment, and the compiler would need to do additional work on address arithmetic to handle this. It mostly was used in "Real" mode, where the Segment register was just added to the address register after shifting up the Segment register 4 bits (giving a 20 bit final memory address). The program model determined what were the default sizes for each type of pointer. Model Data Code Tiny near near Small near near Medium near far Compact far near Large far far Huge huge far The difference between Tiny and Small was that in Tiny, the code and data were in the same segment, while in Small they were in distinct segments. It was by far more common to have near/far pointers in code that had a default near size of pointers, to handle a limited number of objects/functions that would be placed outside the default near block to make room for them, sometimes to access things outside the current program. Note also that the 32 bit x86 family of processors still have these memory models (and 48 bit "far" pointers), they are just mostly ignored and most programs are just done in the Tiny or Small model, after all who should need more than 4GB of address space ;) The resurgence of memory models for programs was headed off (for now at least) with the introduction of 64 bit processors.
[toc] | [prev] | [next] | [standalone]
| From | 88888 Dihedral <dihedral88888@googlemail.com> |
|---|---|
| Date | 2012-09-02 04:43 -0700 |
| Message-ID | <b7724e03-0f38-4d3e-94b7-ca549a1961ac@googlegroups.com> |
| In reply to | #25718 |
On Sunday, September 2, 2012 11:47:23 AM UTC+8, Richard Damon wrote: > On 8/30/12 7:47 AM, Malcolm McLean wrote: > > > בתאריך יום חמישי, 30 באוגוסט 2012 02:09:02 UTC+1, מאת Les Cargill: > > >> Keith Thompson wrote: > > >> > > >> The C89 flavors of MSC supported both "void*" and "near"/"far". TINY > > >> MODEL FTW! > > >> > > > The idea of the "models" was that you could write program without the > > > near/far non-standard extensions. Under "huge", if I remember rightly, > > > all pointers were 32 bit and it did some inefficient magic to hide the > > > segments and give you what looked like flat memory. Under "large", > > > pointers were 32 bits but you couldn't allocate a block of more than > > > 64 K. > > > Under "tiny" all code and data had to fit within the same 64K segment, > > > which led to the most efficient machine code. But you could use far > > > pointers to allocate data in other segments. So you ended up rewriting > > > fucntions like "farmemcpy", because the standard library only worked > > > with the standard pointers. > > > > > > > > > > > > > > > > The models came about due to the memory structure of the 16 bit x86 > > architecture. Addresses were in general greater than 16 bits in length, > > while address registers were only 16 bits long, and were combined with a > > "segment register" to convert the value to a full address. (depending on > > what mode the processor was in would change how the conversion was done). > > > > Near pointers only stored the value of the address register, and the > > segment register was assumed by the type of pointer (the Data Segment > > Register for "data" pointers, and the Program Segment Register for > > function pointers). In addition, data pointers had a huge type, which > > was like a far pointer, but could point to an object that might be > > bigger than a single segment, and the compiler would need to do > > additional work on address arithmetic to handle this. It mostly was used > > in "Real" mode, where the Segment register was just added to the address > > register after shifting up the Segment register 4 bits (giving a 20 bit > > final memory address). > > > > The program model determined what were the default sizes for each type > > of pointer. > > > > Model Data Code > > Tiny near near > > Small near near > > Medium near far > > Compact far near > > Large far far > > Huge huge far > > > > The difference between Tiny and Small was that in Tiny, the code and > > data were in the same segment, while in Small they were in distinct > > segments. > > > > It was by far more common to have near/far pointers in code that had a > > default near size of pointers, to handle a limited number of > > objects/functions that would be placed outside the default near block to > > make room for them, sometimes to access things outside the current program. > > > > Note also that the 32 bit x86 family of processors still have these > > memory models (and 48 bit "far" pointers), they are just mostly ignored > > and most programs are just done in the Tiny or Small model, after all > > who should need more than 4GB of address space ;) The resurgence of > > memory models for programs was headed off (for now at least) with the > > introduction of 64 bit processors. These are old tricks. Now there are 4 to 8 core cpus in the tablet computers, or note book computers running Androids( LINUX+JAVA by a new name for marketing). How to support the multi-core part in C is still not addressed very well?
[toc] | [prev] | [next] | [standalone]
| From | Richard Damon <news.x.richarddamon@xoxy.net> |
|---|---|
| Date | 2012-09-02 23:12 -0400 |
| Message-ID | <k2177i$e3h$1@dont-email.me> |
| In reply to | #25750 |
On 9/2/12 7:43 AM, 88888 Dihedral wrote: > > How to support the multi-core part in C is still not addressed very well? > > > Until the latest standard came out, "ISO Standard C" had no concept of "threads", and without threads, the issues of a multi-core CPU are irreverent. Any program that wanted to use threads had to rely on some other standard of some sort to implement the threads and that standard needed to define how to handle the various issues with multiple cores. There is no inherent problem with this, most real programs actually are going to depend on some standard beyond "ISO Standard C", if only the documentation of the compiler, many times on something like POSIX or the like. With the new standardization of some basic thread supporting primitives in ISO C, the capability to write more stuff in strictly conforming ISO Standard C is available (once support becomes common), so perhaps some programs that used to have a requirement on say POSIX, can now just require C11 compliance, but most are still going to be dependent on things beyond the ISO C standard. I would suspect that in reality, most code for a program should be fairly agnostic to the multi-core nature of the machine, as it should be dealing with data that it currently "owns" and the interfaces that pass data from one thread to another should deal with all the needed memory barriers to make sure this "just works". It is only the sections that need to deal with actually sending information between threads that needs to worry about these aspects, and in most cases the threading library will provide a "good enough" interface (if a bit heavy). It is only the case where trying to improve efficiency that the applications programmer is going to need to deal with these details, and in most cases when dealing with improving efficiency, there is a tendency to move into implementation defined/specific characteristics anyway (how expensive things are tends to be a function of the implementation).
[toc] | [prev] | [next] | [standalone]
| From | ais523 <ais523@nethack4.org> |
|---|---|
| Date | 2012-08-30 11:35 +0000 |
| Message-ID | <k1nj65$t03$1@dont-email.me> |
| In reply to | #25471 |
Keith Thompson wrote: > (I've never used `near` or `far` myself. It's plausible that an > implementation old enough to support them would be too old to support > `void*`.) 16-bit versions of Borland C for Windows supported void* just fine (we're talking well after 1989; they ran under Windows 95 to be able to compile programs that would run under the still-then-in-use Windows 3.1), but also supported near and far because they existed on that platform. The fix used for standards compliance was to have compiler options to specify whether function pointers were near/far if not specified, and whether non-function pointers were near/far if not specified. (This means, among other things, that it was not necessarily possible to convert a void(*)() to a void* and back again, which makes for a nice counterexample to give to people who think it is possible.) The system headers marked every pointer with near or far in order to make them conform to the library ABI, and implicit casts were added to the language avoid this causing trouble. There was actually a third option, huge, which could cope with objects larger than one segment (by performing extra arithmetic upon segment overflow), and was otherwise like far. (And was rarely used, because objects that large were not so useful back then due to limited memory.) I also remember the system-specific library function farmalloc(), which was like malloc but which gave you a far pointer; very useful for storing large amounts of data long-term in a program which otherwise could do with near pointers for data. -- ais523
[toc] | [prev] | [next] | [standalone]
| From | ralph <nt_consulting64@yahoo.com> |
|---|---|
| Date | 2012-08-30 11:17 -0500 |
| Message-ID | <8g2v38tk3bvtgmctvq9mtd4j13u0cu2ugs@4ax.com> |
| In reply to | #25414 |
On Wed, 29 Aug 2012 11:37:02 -0700, Keith Thompson <kst-u@mib.org> wrote: >Eric Sosman <esosman@ieee-dot-org.invalid> writes: >> On 8/29/2012 3:20 AM, Adrian Ratnapala wrote: >>> [... about converting int* to void* for "%p" conversion ...] >>> BTW: I don't know if my misconception is "frequent" enough to warrant an >>> FAQ change, but it doesn't look like the FAQ covers this. Contra Eric, >>> 5.17 is about something else; 4.17 / 19.40 are closer but not quite >>> relevant. >> >> 5.17 is mostly about representations of null pointers, but >> not entirely. If you'll read the entire thing, you'll find two >> specific mentions of different pointer formats, plus a link to >> further examples. >> >> 14.17 and 19.40(d) are about `near' and `far', whose >> connection to the matter at hand eludes me. > >`near` and `far`, which are of course non-standard, can result in >different pointer types having different sizes. Passing a `near` >or `far` pointer to printf with a "%p" format is likely to give >bad results in practice. Actually in practice it was never an issue. Because of how the different models were implemented a different CRT or "standard C Library" was always employed, thus each encountered a "printf()" fully able to managed whatever "%p" formatted argument it received. -ralph
[toc] | [prev] | [next] | [standalone]
| From | Keith Thompson <kst-u@mib.org> |
|---|---|
| Date | 2012-08-30 13:52 -0700 |
| Message-ID | <lnipc0umq1.fsf@nuthaus.mib.org> |
| In reply to | #25546 |
ralph <nt_consulting64@yahoo.com> writes:
> On Wed, 29 Aug 2012 11:37:02 -0700, Keith Thompson <kst-u@mib.org>
> wrote:
[...]
>>`near` and `far`, which are of course non-standard, can result in
>>different pointer types having different sizes. Passing a `near`
>>or `far` pointer to printf with a "%p" format is likely to give
>>bad results in practice.
>
> Actually in practice it was never an issue.
>
> Because of how the different models were implemented a different CRT
> or "standard C Library" was always employed, thus each encountered a
> "printf()" fully able to managed whatever "%p" formatted argument it
> received.
Wasn't it possible to have both near and far pointers, with different
sizes, in the same program?
For example:
char near *nearp = ...;
char far *farp = ...;
printf("nearp = %p, farp = %p\n", nearp, farp);
Maybe that wasn't a common thing to do, but wouldn't it cause problems?
--
Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst>
Will write code for food.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
[toc] | [prev] | [next] | [standalone]
| From | Anders Wegge Keller <wegge@wegge.dk> |
|---|---|
| Date | 2012-08-30 23:13 +0200 |
| Message-ID | <87pq68hymr.fsf@huddi.jernurt.dk> |
| In reply to | #25572 |
Keith Thompson <kst-u@mib.org> writes:
> Wasn't it possible to have both near and far pointers, with
> different sizes, in the same program?
It is. The 80186 compiler I use at work calls this "Mixed mode".
> For example:
>
> char near *nearp = ...;
> char far *farp = ...;
> printf("nearp = %p, farp = %p\n", nearp, farp);
>
> Maybe that wasn't a common thing to do, but wouldn't it cause problems?
One should think that this would give a funny-looking result for the
near pointer. But I've never had to log pointer values on that
platform, so I cannot say for sure what would happen.
--
/Wegge
Leder efter redundant peering af dk.*,linux.debian.*
[toc] | [prev] | [next] | [standalone]
| From | ralph <nt_consulting64@yahoo.com> |
|---|---|
| Date | 2012-08-31 16:37 -0500 |
| Message-ID | <7m42485p88d735n2rt05jet2qjej1rbkb1@4ax.com> |
| In reply to | #25572 |
On Thu, 30 Aug 2012 13:52:06 -0700, Keith Thompson <kst-u@mib.org>
wrote:
>ralph <nt_consulting64@yahoo.com> writes:
>> On Wed, 29 Aug 2012 11:37:02 -0700, Keith Thompson <kst-u@mib.org>
>> wrote:
>[...]
>>>`near` and `far`, which are of course non-standard, can result in
>>>different pointer types having different sizes. Passing a `near`
>>>or `far` pointer to printf with a "%p" format is likely to give
>>>bad results in practice.
>>
>> Actually in practice it was never an issue.
>>
>> Because of how the different models were implemented a different CRT
>> or "standard C Library" was always employed, thus each encountered a
>> "printf()" fully able to managed whatever "%p" formatted argument it
>> received.
>
>Wasn't it possible to have both near and far pointers, with different
>sizes, in the same program?
>
>For example:
>
> char near *nearp = ...;
> char far *farp = ...;
> printf("nearp = %p, farp = %p\n", nearp, farp);
>
>Maybe that wasn't a common thing to do, but wouldn't it cause problems?
Not in "common practice" since the keywords "far" and "near" were
themselves implementaton and conditionally defined. ie, "far" was
actually a defined macro "__far"*.
It was essentially difficult to create 'near' and 'far' pointers in
the same translation unit without going out of your way to contrive
something.
char near *nearp = ...;
char far *farp = ...;
I would expect the above to silent or deliver a strong Warning or even
Error, depending on model being compiled.
Of course we are talking about more than a vendor extension to the
language. Microsoft besides simply providing two different sized
pointer declarations also did thunking and other redefinitions behind
the scenes. (Both the preprocessor and linker were very busy little
beavers. <g>) For example, 'near' pointers magically became 'far'
pointers when calling something in a 'WinAPI' shared library. Well not
too much magic. They basically just prefixed the current defaut
segment to the near address. Hard to say what else might have been
going on. Can't remember all of it.
Do remember that it 'just worked'. <g>
-ralph
[__far* Originally it was "_far", one under-score. Later it become
"__far" to be ANSI compliant for vendor implementation defines. The
final definition was often buried in a stack of #defines. <g>]
[toc] | [prev] | [next] | [standalone]
| From | Barry Schwarz <schwarzb@dqel.com> |
|---|---|
| Date | 2012-08-27 19:45 -0700 |
| Message-ID | <d8ao38l6qg6gsnrvhfecom6bc4cs6er9n9@4ax.com> |
| In reply to | #25134 |
On Mon, 27 Aug 2012 13:35:35 -0700 (PDT), gdotone@gmail.com wrote:
snip
>I created a simple program, creating a 2X3 array and explored the address of the expressions, in piece and whole.
>
>#include <stdio.h>
>#include <stdlib.h>
>
>#define SPACE_BETWEEN_LINES "\n\n"
>
>int main(void)
>{
> int a[2][3];
> int i,j;
>
> printf ( SPACE_BETWEEN_LINES );
>
> for ( i = 0; i < 2; i++ )
> for ( j = 0; j < 3; j++ )
> a[i][j] = 0;
10*i+j might have been a better value so when you print any element of
the array you can tell it is the correct one.
snip
> printf ( "The value at *(a+0) is %d\n", **(a+0) ); /* *(*(a+0)) */
*(a+0) is by definition the same as a[0]. a[0] is an array of 3 int.
It doesn't make sense to talk about a single value for such an array.
**(a+0) is same as a[0][0] (from recursive application of the above
definition). a[0][0] is the single int you print. But it is not the
value of a[0].
>
> printf ( "\n" );
>
> return 1;
This is a non-portable return value from main. Usually successful
completion returns 0. If you really wanted a non-zero value,
EXIT_FAILURE is portable and always non-zero.
>}
>
>Output:
>
>
>The address for a[0][0] is 0x7fff67ca8bf0
>The address for a[0][1] is 0x7fff67ca8bf4
>The address for a[0][2] is 0x7fff67ca8bf8
>The address for a[1][0] is 0x7fff67ca8bfc
>The address for a[1][1] is 0x7fff67ca8c00
>The address for a[1][2] is 0x7fff67ca8c04
>
>
>The address for ((*(a + 0)) + 0) is 0x7fff67ca8bf0
>The address for ((*(a + 0)) + 1) is 0x7fff67ca8bf4
>The address for ((*(a + 0)) + 2) is 0x7fff67ca8bf8
>The address for ((*(a + 1)) + 0) is 0x7fff67ca8bfc
>The address for ((*(a + 1)) + 1) is 0x7fff67ca8c00
>The address for ((*(a + 1)) + 2) is 0x7fff67ca8c04
>
>
>The starting address of a is: 0x7fff67ca8bf0
>
>The second row starting address: 0x7fff67ca8bfc
>
>The a[1][0] address is : 0x7fff67ca8bfc
>
>
>
>*(a+0) address is: 0x7fff67ca8bf0
>
>*(a+0) + 1 address is: 0x7fff67ca8bf4
>The value at *(a+0) is 0
>
>Ok, *(a+0) returns and address, *(a+0) + 1 returns an address.
>
>So, given a[][], a two dimensional array, *(a+i) will return the address of the starting row, *(a+i) + j, returns the address of row,column, &a[i][j].
* is not a function so return is not the best term to use. The
expression *(a+i) and its identical twin a[i] will, with a few
exceptions that don't apply here, both EVALUATE to the address of the
i-th row, not the starting row. If you meant the start of row i, that
would be correct.
>The i term added to a is being added to the base address of the array and itself, i, representing the size of a row. j then adds to that address giving the column position.
When a pointer and an integer are added, the value of the integer is
scaled by the size of the object pointed to, or if you prefer, the
size of the object type pointed to.
Given a pointer p to type T and an integer k, the C expression
p + k
is mathematically equivalent to
p + k * sizeof(T)
or the synonymous
p + k * sizeof *p
Furthermore, discounting the exceptions alluded to above, an
expression with array type is converted to the address of the first
array element with type pointer to element type.
So, the expression
a
is converted to &a[0] with type pointer to array of 3 int,
syntactically written as int(*)[3]. Since sizeof(int) is 4 on
your system, an array of 3 int has size 12.
Combining these two facts tells us that the expression a+i will
evaluate to the address i*12 bytes beyond the start of the array and
still have type pointer to array of 3 int. The net effect is that a+i
evaluates to the address of the i-th row
The expression *(a+i) dereferences this pointer and the result is an
array of 3 int. Consequently, this expression is also converted as
described above. The result is the address of the first element of
the i-th row &a[i][0] with type pointer to int. In other words,
&a[i][0].
Adding j to this expression will evaluate to the address j*4 bytes
beyond the start of the row and still have type pointer to int. In
other words, &a[i][j].
--
Remove del for email
[toc] | [prev] | [next] | [standalone]
| From | Keith Thompson <kst-u@mib.org> |
|---|---|
| Date | 2012-08-27 20:40 -0700 |
| Message-ID | <ln62831y7d.fsf@nuthaus.mib.org> |
| In reply to | #25171 |
Barry Schwarz <schwarzb@dqel.com> writes:
> On Mon, 27 Aug 2012 13:35:35 -0700 (PDT), gdotone@gmail.com wrote:
[...]
> * is not a function so return is not the best term to use. The
> expression *(a+i) and its identical twin a[i] will, with a few
> exceptions that don't apply here, both EVALUATE to the address of the
> i-th row, not the starting row. If you meant the start of row i, that
> would be correct.
The usual term is "yield": functions return values, and expressions
yield values.
[...]
>>The i term added to a is being added to the base address of the array
>>and itself, i, representing the size of a row. j then adds to that
>>address giving the column position.
>
> When a pointer and an integer are added, the value of the integer is
> scaled by the size of the object pointed to, or if you prefer, the
> size of the object type pointed to.
Another way to look at it is that the value is *not* "scaled" by the
size of the object pointed to; rather, the addition yields a pointer
that points N *objects* past the object that the original pointer
points to. (There has to be an array for this to make sense, possibly
the 1-element array that's equivalent to a single object.)
The standard's description doesn't talk about scaling (N1570 6.5.6p8):
When an expression that has integer type is added to or
subtracted from a pointer, the result has the type of the
pointer operand. If the pointer operand points to an element
of an array object, and the array is large enough, the result
points to an element offset from the original element such that
the difference of the subscripts of the resulting and original
array elements equals the integer expression. In other words, if
the expression P points to the i -th element of an array object,
the expressions (P)+N(equivalently, N+(P)) and (P)-N(where N
has the valuen ) point to, respectively, the i+n-th and i−n-th
elements of the array object, provided they exist.
Referring to addition being "scaled" implies that pointers are
*really* pointers to bytes. That's likely true on the machine code
level, but it's not true in the C abstract machine; rather pointers
*really* point to whatever type they're defined to point to.
> Given a pointer p to type T and an integer k, the C expression
> p + k
> is mathematically equivalent to
> p + k * sizeof(T)
> or the synonymous
> p + k * sizeof *p
I understand what you mean, but the fact that you're using "+"
with two very different meaning could be confusing.
[...]
--
Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst>
Will write code for food.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
[toc] | [prev] | [next] | [standalone]
| From | Tim Rentsch <txr@alumni.caltech.edu> |
|---|---|
| Date | 2012-09-07 06:28 -0700 |
| Message-ID | <kfnipbqklmk.fsf@x-alumni2.alumni.caltech.edu> |
| In reply to | #25176 |
Keith Thompson <kst-u@mib.org> writes:
> Barry Schwarz <schwarzb@dqel.com> writes:
>> On Mon, 27 Aug 2012 13:35:35 -0700 (PDT), gdotone@gmail.com wrote:
> [snip]
>
>>>The i term added to a is being added to the base address of the array
>>>and itself, i, representing the size of a row. j then adds to that
>>>address giving the column position.
>>
>> When a pointer and an integer are added, the value of the integer is
>> scaled by the size of the object pointed to, or if you prefer, the
>> size of the object type pointed to.
>
> Another way to look at it is that the value is *not* "scaled" by the
> size of the object pointed to; rather, the addition yields a pointer
> that points N *objects* past the object that the original pointer
> points to. (There has to be an array for this to make sense, possibly
> the 1-element array that's equivalent to a single object.)
>
> The standard's description doesn't talk about scaling (N1570 6.5.6p8):
> [snip quoted paragraph]
But, talking about the [] array indexing operator, the Standard
does say in a footnote
Then i is adjusted according to the type of x, which
conceptually entails multiplying i by the size of the
object to which the pointer points
I'm not arguing for or against either explanation; I think both
have some support (as an explanation) in the Standard.
[toc] | [prev] | [standalone]
Page 2 of 2 — ← Prev page 1 [2]
Back to top | Article view | comp.lang.c
csiph-web