473,722 Members | 2,484 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Validity of pointer conversions

Are the following codes guaranteed to work always?
1.

#include <iostream>
inline void some_func(int *p, const std::size_t SIZE)
{
using namespace std;

for(size_t i=0; i<SIZE; ++i)
cout<< p[i]<< " ";
}
int main()
{
int array[10][5]= {0};

some_func(array[0], sizeof(array)/sizeof(**array) );

std::cout<< std::endl;
}
The above prints 50 zeros. I think it is guaranteed to work, since all
arrays are sequences of their elements.

2.

#include <iostream>
int main()
{
using namespace std;

int array[50]= {0};

int (*p)[5]= reinterpret_cas t<int (*)[5](&array[0]);

for (size_t i= 0; i< 10; ++i)
for(size_t j=0; j<5; ++j)
cout<< p[i][j]<<" ";

cout<< endl;

}
Here p behaves as a 2-dimensional matrix, that is a 10x5 matrix. I think
it is guaranteed to work for the same reason as the first one, that is
we can treat an array (sequence) of integers as various types of integer
arrays.
Jan 5 '08
25 2012
On Jan 5, 10:02 pm, Ioannis Vranos <j...@no.spamwr ote:
James Kanze wrote:
On Jan 5, 4:02 pm, Ioannis Vranos <j...@no.spamwr ote:
Are the following codes guaranteed to work always?
1.
#include <iostream>
inline void some_func(int *p, const std::size_t SIZE)
{
using namespace std;
for(size_t i=0; i<SIZE; ++i)
cout<< p[i]<< " ";
}
int main()
{
int array[10][5]= {0};
some_func(array[0], sizeof(array)/sizeof(**array) );
std::cout<< std::endl;
}
The above prints 50 zeros. I think it is guaranteed to work,
since all arrays are sequences of their elements.
And? I don't see any relationship between what you just said
and any guarantee of working. You have an array bounds
violation, which is undeefined behavior. And there have been
(and maybe still are) implementations which detect it, and
treat it as an error condition.
What exact array bounds violation is there in the code above?
"int array[10][5];" is a sequence of 50 integers.
No. "int array[10][5]" is an array[10] of array[5] of int. The
standard may require that it be physically laid out as a
sequence of 50 integers, but that has nothing to do with the
type. The type is "int [10][5]". When it decays to a
pointer, the type is "int (*)[5]", a pointer to the first of
ten elements, and when you dereference said pointer, the result
is an int*, pointer to the first of five elements.

The authors of the C standard went out of there way to ensure
that an implementation which tracked bounds would be legal.
2.
#include <iostream>
int main()
{
using namespace std;
int array[50]= {0};
int (*p)[5]= reinterpret_cas t<int (*)[5](&array[0]);
for (size_t i= 0; i< 10; ++i)
for(size_t j=0; j<5; ++j)
cout<< p[i][j]<<" ";
cout<< endl;
}
Here p behaves as a 2-dimensional matrix, that is a 10x5
matrix.
Almost nothing involving reinterpret_cas t is guaranteed to work.
OK, consider int (*p)[5]= static_cast<int (*)[5](static_cast<vo id
*>(&array[0])); instead.
If by that you mean that you can play games with the dimensions,
as long as the total number of elements is unchanged, that is
simply false.
Why?
The short answer is because the standard says so. The rationale
behind this is to allow bounds checking implementations . Such
implementations have existed, and may still exist. (Centerline
offered one, and I believe that the Centerline compiler is still
on the market.)
In all cases we have the same sequence of ints,
So? What does physical layout have to do with type?
that is int array[50], int array[10][5], int array[5][10] are
all implemented as the same sequence of 50 ints. If they are
not implemented in the same way, where do they differ?
The underlying physical layout may be the same, but that doesn't
mean that they have the same type.

--
James Kanze (GABI Software) email:ja******* **@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientier ter Datenverarbeitu ng
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Jan 6 '08 #11
James Kanze wrote:
>
>that is int array[50], int array[10][5], int array[5][10] are
all implemented as the same sequence of 50 ints. If they are
not implemented in the same way, where do they differ?

The underlying physical layout may be the same, but that doesn't
mean that they have the same type.

I didn't say that they are of the same type, I was just wondering if we
can "adjust" arrays to behave the way we want, one dimensional array,
two dimensional array and so for.

I got the idea from valarray & slice combinations to "create" matrices
as we like (2x4, 3x5 and so on) while the whole thing is really based on
a 1-dimensional valarray.

Thought perhaps we could do the same with built in arrays by using
pointers since as you said, the physical implementation is the same.

I think it would be great if this was guaranteed to work, the same way
there is a special guarantee that we can treat POD objects as sequences
of chars/unsigned chars.
Jan 6 '08 #12
On 2008-01-06 16:09, Ioannis Vranos wrote:
James Kanze wrote:
>>
>>that is int array[50], int array[10][5], int array[5][10] are
all implemented as the same sequence of 50 ints. If they are
not implemented in the same way, where do they differ?

The underlying physical layout may be the same, but that doesn't
mean that they have the same type.


I didn't say that they are of the same type, I was just wondering if we
can "adjust" arrays to behave the way we want, one dimensional array,
two dimensional array and so for.

I got the idea from valarray & slice combinations to "create" matrices
as we like (2x4, 3x5 and so on) while the whole thing is really based on
a 1-dimensional valarray.

Thought perhaps we could do the same with built in arrays by using
pointers since as you said, the physical implementation is the same.

I think it would be great if this was guaranteed to work, the same way
there is a special guarantee that we can treat POD objects as sequences
of chars/unsigned chars.
Why not just use a one-dimensional array of sufficient size and wrap it
in a class and use some simple calculations to get the correct element,
it is guaranteed to work and in the end it will probably generate the
same code. Using proxy classes you can even get the same syntax (but I
would prefer to simply overload operator() ).

--
Erik Wikström
Jan 6 '08 #13
On 5 Jan, 15:02, Ioannis Vranos <j...@no.spamwr ote:
Are the following codes guaranteed to work always?
<snip>

Ioannis,

They aren't guaranteed to work, and I can think of at least one
architecture in which they probably won't.

On the 8086 memory model, an int is usually 16 bits, and a "segment"
of memory is 64Kb - allowing 32k ints. Segments are 16 bytes apart -
a "paragraph" - and can overlap. You can tell the compiler to work in
several ways to get around this limit.

If the compiler is working in such a mode as to give a different
segment address for each of your 10 arrays, each one will be padded up
to the next paragraph boundary, so you'll have 10 bytes for the 5
integers - and then 6 bytes free (almost the same as padding). The
next array will be on the next paragraph boundary. There's no bounds
checking, so the first 5 integers will be the ones you expect, the
next 3 will be the padding, and only then will you get the 2nd 5.

Ciao
Jan 6 '08 #14
James Kanze wrote:
>
int array[10][5]= {99};

What does that change? *You have different initial values
(array[0][0] == 99, all other elements == 0). *
I think it is not a best idea to trust that all other elements will be
zero. Default constructor for int will be called, and i have some
compilers, which do nothing in the case (a trash from previous memory
users will be found in the array). The same thing does for pointers
(int* for example).
C++ has reinterpret_cas t for a reason. *I use it, for example,
when implementing things like malloc or garbage collection. *In
such cases, it's a necessary evil.

In anything but such low level (architecture dependent)
programming, of course, it's a guaranteed problem, if only for
reasons of readability.
One can make separated namespaces to locate code specific for each
architecture and later to write using for correct one. A general
(suitable for all platforms, but with bad performance) form of the
code often can exist also in own namespace.

Maksim A. Polyanin
old page about some C++ improvements:
http://grizlyk1.narod.ru/cpp_new
Jan 6 '08 #15
Grizlyk wrote:
James Kanze wrote:
int array[10][5]= {99};
What does that change? *You have different initial values
(array[0][0] == 99, all other elements == 0). *

I think it is not a best idea to trust that all other elements will be
zero. Default constructor for int will be called, and i have some
compilers, which do nothing in the case (a trash from previous memory
users will be found in the array). The same thing does for pointers
(int* for example).

That's not correct. If an incomplete initializer is used, all other
elements will be initialized as if it were set to 0. I don't know if
the C++ standard covers it specifically (my copy is at work), as it's
inherited from C. Here's the C99 draft standard on the issue:

[#21] If there are fewer initializers in a brace-enclosed
list than there are elements or members of an aggregate, or
fewer characters in a string literal used to initialize an
array of known size than there are elements in the array,
the remainder of the aggregate shall be initialized
implicitly the same as objects that have static storage
duration.


Brian
Jan 6 '08 #16
Imagine having a vector<intv(100 ); and want to pass it to a function
expecting a built-in array of int[2][50]

If it was guaranteed to work, we could just do:
vector<intvi(10 0);

int (*p)[50]= reinterpret_cas t<int(*)[50](&vi[0]);

somefunc(p);
Jan 7 '08 #17
Default User wrote:
>
The clause "the same as objects that have static storage
duration" is not the same as "filled by zero".

From the C++ standard:

1 Objects with static storage duration (3.7.1) shall be
zero-initialized (8.5) before any other initialization takes place.
This is quite clear now:

1. Default constructor for static POD type makes zero-initialized
value.

2. Default constructor for not static POD type can do nothing.

There are fewer initializers of an aggregate or an array of known
size, remainder of the aggregate or the array shall be initialized
implicitly the same as objects that have static storage duration.

3. So default constructor for not static POD type for remainder of the
aggregate or the array makes zero-initialized value.

4. For non-POD values default ctor will be called always, even for
automaic aggregates or arrays.
Let's look like compilers make static arrays:

I have no idea what you are going on about.
It is easy to understand
char * * * b[100]={1,2};
is C++ source code with static array b.
_b:
* *.byte * 1
* *.byte * 2
* *.space 98
or
_b label * byte
* *db * * *1
* *db * * *2
* *db * * *98 * * *dup(?)
is oputput compiled from C++ into assembler for a concrete CPU.
all depends from asm conventions for ".space" and
"dup(?)" directives.
It is means, that if assembler can emit for directive "dup(?)"
executable with any random values excluding 0 (there are the
assemblers in the world), the C++ compiler became non-standard (will
have a non-conforming implementation) .

I think, that C++ programmer must not take in account the low-level
details of C++ compiler implementation and trust, that considered
arrays will be zero initialized for "conforming implementation" .

Maksim A. Polyanin
old page about some C++ improvements:
http://grizlyk1.narod.ru/cpp_new
Jan 7 '08 #18
On Jan 6, 9:22 pm, Grizlyk <grizl...@yande x.ruwrote:
James Kanze wrote:
int array[10][5]= {99};
What does that change? You have different initial values
(array[0][0] == 99, all other elements == 0).
I think it is not a best idea to trust that all other elements
will be zero.
The standard says that all other elements will be zero. Are you
claiming that you've had problems with compiler errors in this
regard?
Default constructor for int will be called, and i have some
compilers, which do nothing in the case (a trash from previous
memory users will be found in the array). The same thing does
for pointers (int* for example).
Which compilers? The standard is very explicit: "if there are
fewer initializers in the list than there are members in the
aggregate, then each member not explicitly initialized shall be
default-initialized." (That's from C++98. The exact wording
has changed some, but in no way which affects PODs.)

--
James Kanze (GABI Software) email:ja******* **@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientier ter Datenverarbeitu ng
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Jan 8 '08 #19
On Jan 7, 8:52 pm, Grizlyk <grizl...@yande x.ruwrote:
Default User wrote:
The clause "the same as objects that have static storage
duration" is not the same as "filled by zero".
From the C++ standard:
1 Objects with static storage duration (3.7.1) shall be
zero-initialized (8.5) before any other initialization takes place.
This is quite clear now:
1. Default constructor for static POD type makes zero-initialized
value.
2. Default constructor for not static POD type can do nothing.
Only class types have constructors, and the default constructor
of a POD class does nothing. Ever.

Default initialization of a non-POD class type calls the default
constructor. Default initialization of an array
default-initializes each element. Default initialization of any
other type is zero initialization.

If a definition of an aggregate has an initializer list,
elements for which no initializer is given are default
initialized---for a POD type, that means zero initialized.

If a definition of POD has no initializer, then it is not
initialized. All objects (even those with user defined
constructors) with static lifetime are zero initialized before
program start-up, however.

--
James Kanze (GABI Software) email:ja******* **@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientier ter Datenverarbeitu ng
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Jan 8 '08 #20

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

Similar topics

22
12734
by: Alex Fraser | last post by:
From searching Google Groups, I understand that void pointer arithmetic is a constraint violation, which is understandable. However, generic functions like qsort() and bsearch() must in essence do exactly this, and similarly generic functions seem to have useful applications. In a few posts I read, it was suggested to avoid void pointer arithmetic by casting to a char pointer, and performing arithmetic on that (in multiples of...
16
3376
by: jacob navia | last post by:
Valid pointers have two states. Either empty (NULL), or filled with an address that must be at a valid address. Valid addresses are: 1) The current global context. The first byte of the data of the program till the last byte. Here we find static tables, global context pointers, etc. This are the global variables of the program.
204
13041
by: Alexei A. Frounze | last post by:
Hi all, I have a question regarding the gcc behavior (gcc version 3.3.4). On the following test program it emits a warning: #include <stdio.h> int aInt2 = {0,1,2,4,9,16}; int aInt3 = {0,1,2,4,9};
10
2222
by: vb | last post by:
Hi all, I am a newbie in C and i want to know what all pointer conversions are "legal" according to ANSI C standard. For Example, int* to char*, some_struct* to char* and so on .. According to me, since any pointer can be cast to void* and void * can be cast to any other pointer so this implies that any pointer can be cast to any other pointer. Is that so?
12
1237
by: Vladimir_petter | last post by:
Dear All, There is the problem in nutshells (see the program bellow): It is ok to convert pointer to F<T> to the pointer to I. Now if I have pointer to member "F<T> entity::*" can I convert it to the "I entity::*"? Compiler does not let me to do that (I've tried on VC 7.1 and Comeau 4.3.3). If I do reinterpret_cast then the program will be compiled and runs as expected all though I would like to know possible implications of this
8
2234
by: Martin Jørgensen | last post by:
Hi, "C primer plus" p.382: Suppose we have this declaration: int (*pa); int ar1; int ar2; int **p2;
33
4545
by: a | last post by:
Hi, I have a pointer that points to an unknown heap memory block, is it possible to check the pointer + 3 is valid or not? If it is impossible, how can I do the check? Thanks
5
3911
by: jason.cipriani | last post by:
There have been some recent threads about casting pointers to and from void* that have me rethinking some of my usual practices. I have a couple of questions. 1. What is the purpose of C++'s static_cast<>? In other words, is there any real difference between statements like (with non-pointer types): double a = 3.4; int b = (int)a; // <--- this
8
1862
by: tfelb | last post by:
Hey group! I have 2 questions. I saw functions with char *dst = (char *)src. In that case if I remember what I've learned I assign (an) (the) address of src to dst. Right? But I can assign an address with the address operator & too? char *dst = &src. What's the difference between *dst = (char *)src and *dst = &src and
0
8863
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
9384
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
9157
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
9088
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...
1
6681
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
4502
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
4762
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
3207
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
2
2602
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.

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.