473,740 Members | 8,442 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

multi dimensional arrays as one dimension array

The subject might be misleading.
Regardless, is this code valid:

#include <stdio.h>

void f(double *p, size_t size) { while(size--) printf("%f\n", *p++); }
int main(void) {
double array[2][1] = { { 3.14 }, { 42.6 } };
f((double *)array, sizeof array / sizeof **array);
return 0;
}

Assuming casting double [2][1] to double * is implementation defined
or undefined behavior, replace the cast with (void *).

Since arrays are not allowed to have padding bytes in between of
elements, it seems valid to me.
Aug 29 '08 #1
152 9860
vi******@gmail. com wrote:
The subject might be misleading.
Regardless, is this code valid:

#include <stdio.h>

void f(double *p, size_t size) { while(size--) printf("%f\n", *p++); }
int main(void) {
double array[2][1] = { { 3.14 }, { 42.6 } };
f((double *)array, sizeof array / sizeof **array);
return 0;
}

Assuming casting double [2][1] to double * is implementation defined
or undefined behavior, replace the cast with (void *).

Since arrays are not allowed to have padding bytes in between of
elements, it seems valid to me.
Stepping through a one dimensional array
and on through a consecutive one dimensional array
is only defined for elements of character type
and only because
any object can be treated as an array of character type.

--
pete
Aug 29 '08 #2
On Aug 29, 6:39 am, pete <pfil...@mindsp ring.comwrote:
vipps...@gmail. com wrote:
The subject might be misleading.
Regardless, is this code valid:
#include <stdio.h>
void f(double *p, size_t size) { while(size--) printf("%f\n", *p++); }
int main(void) {
double array[2][1] = { { 3.14 }, { 42.6 } };
f((double *)array, sizeof array / sizeof **array);
return 0;
}
Assuming casting double [2][1] to double * is implementation defined
or undefined behavior, replace the cast with (void *).
Since arrays are not allowed to have padding bytes in between of
elements, it seems valid to me.

Stepping through a one dimensional array
and on through a consecutive one dimensional array
is only defined for elements of character type
and only because
any object can be treated as an array of character type.
So as I understand it you are saying my code invokes undefined
behavior.
In which hypothetical (or real, if such implementation does exist)
implementation my code won't work, and why?
Aug 29 '08 #3
vi******@gmail. com wrote:
On Aug 29, 6:39 am, pete <pfil...@mindsp ring.comwrote:
>vipps...@gmail .com wrote:
>>The subject might be misleading.
Regardless, is this code valid:
#include <stdio.h>
void f(double *p, size_t size) { while(size--) printf("%f\n", *p++); }
int main(void) {
double array[2][1] = { { 3.14 }, { 42.6 } };
f((double *)array, sizeof array / sizeof **array);
return 0;
}
Assuming casting double [2][1] to double * is implementation defined
or undefined behavior, replace the cast with (void *).
Since arrays are not allowed to have padding bytes in between of
elements, it seems valid to me.
Stepping through a one dimensional array
and on through a consecutive one dimensional array
is only defined for elements of character type
and only because
any object can be treated as an array of character type.

So as I understand it you are saying my code invokes undefined
behavior.
In which hypothetical (or real, if such implementation does exist)
implementation my code won't work, and why?
I don't know.
I think it would be more difficult to design a system
where it wouldn't work, than to design one where it would.

Think of it as being allowed not to work.

--
pete
Aug 29 '08 #4
On Aug 28, 8:15 pm, vipps...@gmail. com wrote:
The subject might be misleading.
Regardless, is this code valid:

#include <stdio.h>

void f(double *p, size_t size) { while(size--) printf("%f\n", *p++); }
int main(void) {
double array[2][1] = { { 3.14 }, { 42.6 } };
f((double *)array, sizeof array / sizeof **array);
return 0;

}

Assuming casting double [2][1] to double * is implementation defined
or undefined behavior, replace the cast with (void *).
Changing the cast to void* only creates more work for the compiler.
Unless it is smart enough to optimize away the first step, it must
first convert array (which in this context is identical to &array[0]
and has type "double (*)[1]") to void* to satisfy the cast and then
convert that to double* to satisfy the prototype.

The only issue about pointer conversions is if the value is properly
aligned for the resulting type and the value of the expression array
is guaranteed to be properly aligned for a double* since the value
(disregarding type) is exactly the same as &array[0][0]..
>
Since arrays are not allowed to have padding bytes in between of
elements, it seems valid to me.
If your system has built in hardware assist for bounds checking, it
would be reasonable for the "bounds registers" to contain the start
and end addresses of array[0]. Eventually your p++ would be outside
this range (even though it is still within array as a whole). While
this is a perfectly valid value attempts to dereference it should be
trapped by the bounds checking logic in the hardware.

Whether such a system exists is a practical issue
Aug 29 '08 #5
vi******@gmail. com wrote:
On Aug 29, 6:39 am, pete <pfil...@mindsp ring.comwrote:
>vipps...@gmail .com wrote:
>>The subject might be misleading.
Regardless, is this code valid:
#include <stdio.h>
void f(double *p, size_t size) { while(size--) printf("%f\n", *p++); }
int main(void) {
double array[2][1] = { { 3.14 }, { 42.6 } };
f((double *)array, sizeof array / sizeof **array);
return 0;
}
Assuming casting double [2][1] to double * is implementation defined
or undefined behavior, replace the cast with (void *).
Since arrays are not allowed to have padding bytes in between of
elements, it seems valid to me.
Stepping through a one dimensional array
and on through a consecutive one dimensional array
is only defined for elements of character type
and only because
any object can be treated as an array of character type.

So as I understand it you are saying my code invokes undefined
behavior.
In which hypothetical (or real, if such implementation does exist)
implementation my code won't work, and why?
The key point is the pointer conversion. At the point where that
conversion occurs, the compiler knows that (double*)array == array[0].
It's undefined if any number greater than 1 is added to that pointer
value, and also if that pointer is dereferenced after adding 1 to it.

Because the behavior is undefined, it's possible for a conforming
implementation to provide a run-time bounds check. This would require
the use of some mechanism such as a "fat" pointer, which contains not
only the information about where it points, but also information about
the upper and lower limits on where it can point. The implementation can
set the limits on the pointer value created by that conversion, based
upon the limits for array[0].

Implementations with support for run-time bounds checking are rare; the
performance cost is significant, it's almost always optional, and
usually not the default option, so you're unlikely to run into this
issue by accident.

The more tricky possibility is also something you're far more likely to
run into. Because the behavior is undefined in those cases, a compiler
is allowed to generate code which is optimized in a way that assumes
that those cases don't actually come up; because it makes that
assumption, such code can fail catastrophicall y if that assumption is
violated.

This is most likely to occur as the result of anti-aliasing assumptions.
The compiler is allowed to generate code which assumes that array[0][i]
is never an alias for array[1][j], regardless of the values of i and j.
As a result, it can drop anti-aliasing checks from code that would need
such checks if that assumption could be violated without making the
behavior undefined.

I don't see any way for that to come up in this particular example, but
in more complicated cases it can come up. If 'p' and 'array' were both
in scope at the same place somewhere in the code, the compiler would not
be required to prevent the problems that might occur if p[j] and
array[1][i] happened to refer to the same location in memory. It is
required to cover the possibility that p[j] and array[0][i] refer to the
same object, but only if 'i' and 'j' are both 0. It's also required to
handle the possibility that p+j refers to the same location as
array[0][i], but only if 'i' and 'j' are both in the range [0,1].
Aug 29 '08 #6
On Aug 29, 6:15 am, vipps...@gmail. com wrote:
Message-ID: <38b37f10-252e-48f8-bffa-
cc**********@j2 2g2000hsf.googl egroups.com>

Thanks everyone.
Aug 29 '08 #7
On Thu, 28 Aug 2008 23:39:54 -0400, pete <pf*****@mindsp ring.com>
wrote:
>
Stepping through a one dimensional array
and on through a consecutive one dimensional array
is only defined for elements of character type
and only because
any object can be treated as an array of character type.
I am trying to understand your answer. Are you saying that the
original code will not necessarily work in a conforming compiler
because there is no guarantee in the standard that the row slices will
be exactly next to each other in memory (i.e., there may be padding
added to each row that may not be a multiple of sizeof(double)) ? But
at the same time if double was replaced with char, i.e.,

#include <stdio.h>
void f(char *p, size_t size) { while(size--) printf("%c\n", *p++); }
int main(void) {
char array[2][1] = { { 'a' }, { 'b' } };
f((char *)array, sizeof array / sizeof **array);
return 0;
}

then for this particular case the row slices are required by the
standard to be next to each other in memory so the individual stepping
will work in the called function? Or are you saying that for the char
case there may still be padding between the row slices but the
individual stepping will work because the padding will always be a
multiple of sizeof(char) (i.e., 1), and that the stepping in the
called function will just include the padded characters if they are
present?

i.e., in either case the called function may not be doing what you
intended if there is padded memory present between the rows, but in
the case of double or other non-character type it may even bomb.

Do I understand your answer correctly?

James Tursa
Aug 31 '08 #8
On Fri, 29 Aug 2008 11:08:00 GMT, James Kuyper
<ja*********@ve rizon.netwrote:
>
The key point is the pointer conversion. At the point where that
conversion occurs, the compiler knows that (double*)array == array[0].
It's undefined if any number greater than 1 is added to that pointer
value, and also if that pointer is dereferenced after adding 1 to it.
Trying to understand your answer as it relates to the original post. I
don't see how the original function gets an address 2 beyond the end,
or 1 beyond the end and attempts to dereference it, as you seem to be
saying. Can you point this out? Did I misunderstand you?

James Tursa
Aug 31 '08 #9
On Aug 31, 8:02 pm, James Tursa <aclassyguywith akno...@hotmail .com>
wrote:
On Thu, 28 Aug 2008 23:39:54 -0400, pete <pfil...@mindsp ring.com>
wrote:
Stepping through a one dimensional array
and on through a consecutive one dimensional array
is only defined for elements of character type
and only because
any object can be treated as an array of character type.

I am trying to understand your answer. Are you saying that the
original code will not necessarily work in a conforming compiler
because there is no guarantee in the standard that the row slices will
be exactly next to each other in memory (i.e., there may be padding
added to each row that may not be a multiple of sizeof(double)) ? But
at the same time if double was replaced with char, i.e.,

#include <stdio.h>
void f(char *p, size_t size) { while(size--) printf("%c\n", *p++); }
int main(void) {
char array[2][1] = { { 'a' }, { 'b' } };
f((char *)array, sizeof array / sizeof **array);
return 0;

}

then for this particular case the row slices are required by the
standard to be next to each other in memory so the individual stepping
will work in the called function? Or are you saying that for the char
case there may still be padding between the row slices but the
individual stepping will work because the padding will always be a
multiple of sizeof(char) (i.e., 1), and that the stepping in the
called function will just include the padded characters if they are
present?

i.e., in either case the called function may not be doing what you
intended if there is padded memory present between the rows, but in
the case of double or other non-character type it may even bomb.

Do I understand your answer correctly?
That code of yours invokes undefined behavior, if char is signed.
You have to change the type of p to unsigned char.
Also, it would only be meaningful if you did not divide by sizeof
**array.

'pete' did not really answer my question. Instead he spoke for object
representations .
What pete really meant is that you can treat any pointer to object as
an array of unsigned char, to observe its representation.
Aug 31 '08 #10

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

Similar topics

0
1684
by: James | last post by:
I see that variations on this question have appeared before but I'm still completely stumped. I'm developing an application with a fairly robust graphics component for 3D rendering. I've written all the 3D rendering scripts, but what's really hanging me up is how to I pass information from an one-dimensional arraylist to a two-dimensional array. Here's what I'm trying to do: 1) My program generates an arraylist called "mpoints" of 2D...
6
9523
by: Gregory L. Hansen | last post by:
I'm sure I saw this mentioned somewhere, but I can't find it. How can I dynamically allocate a multi-dimensional array in C++? My next question, if this gets figured out, is if I should use the delete command to remove it, or would that be delete ? -- "What are the possibilities of small but movable machines? They may or may not be useful, but they surely would be fun to make."
4
2250
by: Richard Hayden | last post by:
Hi, Why does gcc (3.3.2) give me a 'initialization from incompatible pointer type' warning when compiling: int main(int argc, char** argv) { int testa; int** testp = testa; }
8
2249
by: masood.iqbal | last post by:
All this time I was under the illusion that I understand the concept of multi-dimensional arrays well ---- however the following code snippet belies my understanding. I had assumed all along that a declaration like: int intArray means that there is an array of pointers to int with a size of 5, each of whose elements is an array of int with a size of 3. This definition seemed intuitive to me since a declaration like
11
4465
by: truckaxle | last post by:
I am trying to pass a slice from a larger 2-dimensional array to a function that will work on a smaller region of the array space. The code below is a distillation of what I am trying to accomplish. // - - - - - - - - begin code - - - - - - - typedef int sm_t; typedef int bg_t; sm_t sm; bg_t bg;
1
6299
by: Fayez Al-Naddaf | last post by:
I got this message when I tried to browse my web service "Multi-dimensional arrays are not supported. Use a jagged array instead" Can someone told me why?
0
1363
by: volx | last post by:
Hello all: What is the proper way to implement in MC++ a web service which accepts a multi dimensional array as a parameter to one of its methods? This does compile: double pass2DArray(Double array __gc);
5
1633
by: David T. Ashley | last post by:
Hi, Aside from the obvious recursive syntax for initialization, $x = array( ... array( ...)), what is the best way to deal with multi-dimensional arrays in PHP? It seems there is no syntax like $x???
3
2126
by: ben.r.wood | last post by:
I am not entirely sure, but after scanning the web believe I need to use multi-dimensional arrays for my problem - although I have not seen any examples of what I am trying to achieve. I have a form with one field, for which a user will submit a lump of delimited data. The data will always be in the same format, ie. 5 fields per record, each field has a delimeter and a new row starts a new record. for example:
0
8969
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, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
9484
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, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
1
9272
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 Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
9211
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 protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
0
8218
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, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
0
4572
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
0
4826
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
2
2748
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
3
2195
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

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.