int (*p)[5] = (int (*)[5])new int[5];
How do I delete the allocated memory?
Is it:
a) delete[] p;
b) delete[] *p;
c) delete[] (int*)p;
?? Any ideas??
You have casted the pointer type returned from new into a different pointer, but
regardless, new allocated an array of 5 ints, so you call delete [] on the
pointer that new returned.
delete [] reinterpret_cast<int*>(p);
my correction: should say you have casted the pointer type returned from new
into a different pointer "type"
I'd like to point out that AFAIK the first cast may result in a loss
of information. You're only guaranteed round-way trips through void*,
char*, and unsigned char*, (and an integer type of sufficient size).
Thus the delete[] could be UB on a conforming platform. That's right,
right?
i not use delete-new i use always malloc()-free()
or my version of these functions
I think that c) but why you reinterpret_cast at first place?
I start to wonder do you ever use raw dynamic arrays and if then why
do you use them? I don't. In C code I do but there are allocated with
malloc() and deallocated with free(). Usage of "delete[]" itself
usually indicates that some novice in team has copy-pasted something
cheesy from google or from a book into our code base.
In C++ it is often clear how a particular container of T's should be
used (as stack or as set or as queue or as vector). Sometimes it is
unclear. I usually take std::vector<T> first when it is unsure how
container will be used. Later it settles and usually it remains as
such for ages after.
Sometimes very rarely it later becomes apparent that a container
causes performance or maintainability issues related to nature or
usage of it. Then i revisit what exact underlying container type is
used. Refactoring vector into some other container may make sense at
that spot.
The chosen type depends on what is done with container and what is not
done with it. There are so lot of somewhat similar to vector
containers to choose. boost::array<T>, boost::scoped_array<T>,
std::map<int,T>, std::list<T>, boost::intrusive::slist<T> and so on.
Basically ... just describe exact nature and usage of container and no
doubt that there is very close template available and free to use.
Vector may become even raw static array, but i see no reasons to use
raw dynamic array in C++.
Raw static arrays i use for static tables. Sometimes initial
requirements described some "list" of information and vector was
chosen and later it did appear that it is actually static table of
information. There is so elegant (IMHO) syntax for initializing static
arrays in C so it is lot better to maintain. Like i understand C++0x
will allow using such syntax for initializing other containers as
well.
That depends on:
a) which cast is used and
b) what the alignment requirement for the involved types are.
According to [5.2.10/7] you can reinterpret_cast round trip from T1* to T2*
and back provided the alignment of T2 are not stricter than the ones for T1.
To me, the C-style cast within the expression
(int (*)[5]) new int[5]
looks like a reinterpret_cast. Thus, [5.2.10/7] applies. As to whether
int[5] may have stricter alignment requirements than int, I think the
standard remains silent.
Best,
Kai-Uwe Bux
template<typename T, int S, typename U= T (&)[S]>
class R{
public:
R():pp((int (*)[S])new int[S+1]), r(*(pp+1)){r[-1]=S;}
U getArray(){return r;}
void delete_it(){ delete[] (int*)pp; }
private:
int (*pp)[S];
T (&r)[S];
};
template<typename T>
void foo(T r){
std::cout<<"size of array:\t" << r[-1];
std::cout<< "\ntype of array:\t" << typeid(T).name();
}
int main() {
R<int, 7> r;
int (&r1)[7] = r.getArray();
foo(r.getArray());
std::cout<<"\ntype of r1:\t"<< typeid(r1).name();
r.delete_it();
}
>I start to wonder do you ever use raw dynamic arrays and if then why
>do you use them? I don't. In C code I do but there are allocated with
>malloc() and deallocated with free(). Usage of "delete[]" itself
>usually indicates that some novice in team has copy-pasted something
>cheesy from google or from a book into our code base.
OFC dynamic arrays are very usefull , especially if creating a specialised
container.
>In C++ it is often clear how a particular container of T's should be
>used (as stack or as set or as queue or as vector). Sometimes it is
>unclear. I usually take std::vector<T> first when it is unsure how
>container will be used. Later it settles and usually it remains as
>such for ages after.
std::vector is not always the best solution for use within specialised class
designs. I don't see std::vector as a replacement for dynamic arrays, its a
good quick and easy solution if you need a basic resizeable vector with safe
some built in safety.
>Sometimes very rarely it later becomes apparent that a container
>causes performance or maintainability issues related to nature or
>usage of it. Then i revisit what exact underlying container type is
>used. Refactoring vector into some other container may make sense at
>that spot.
I think in C++ we have the power to create a wide variety of specialised
types, data records etc. I don't like to think that there is a certain
limited amount of types, defined by the std lib , that we should use.
>The chosen type depends on what is done with container and what is not
>done with it. There are so lot of somewhat similar to vector
>containers to choose. boost::array<T>, boost::scoped_array<T>,
>std::map<int,T>, std::list<T>, boost::intrusive::slist<T> and so on.
>Basically ... just describe exact nature and usage of container and no
>doubt that there is very close template available and free to use.
>Vector may become even raw static array, but i see no reasons to use
>raw dynamic array in C++.
I prefer to design my own type for a spefic need, if there is a something
suitable in the std lib then great I will use it. but often they are just
not perfectly suited to the job.
>Raw static arrays i use for static tables. Sometimes initial
>requirements described some "list" of information and vector was
>chosen and later it did appear that it is actually static table of
>information. There is so elegant (IMHO) syntax for initializing static
>arrays in C so it is lot better to maintain. Like i understand C++0x
>will allow using such syntax for initializing other containers as
>well.
You are probably basing your views on personal experience as many of us do.
One of the major attractions to C++ , for me , is the ability to easily
create specialised types whereas assembly its a bit more complex, I like to
use this feature of the language often , and I get much satisfaction from
doing so.
As you may have guessed I am no big fan of the std lib, I do like some of
the template features but generally I don't bother with it unless it suits
the job perfectly.
AFAIK boost multi-array, and I don't think this is part of the std lib, is
the closest thing to my needs and its a bit overkill tbh.
Also learning about different ways of allocating memory is usefull for
learning purposes and enhances your programming skills, sometimes I prefer
to invoke the OS's API directly for memory allocation simply to become more
familiar with the API.
HTH
Paul.
As your question has been answered elsewhere, I'll just add an
interesting aside from a language design perspective. If C++ had a
more regular design the type of the "new int [5]" expression would not
degenerate to "int*". A regular design would render the array
overloads of new and delete superfluous, and make your cast here
unnecessary. Consider the irregularity of:
typedef struct {int a, b, c, d, e;} Struct; // aggregate type
typedef int Array [5]; // aggregate type
Struct* ps = new Struct; // Ok!
Array* pa = new Array; // Error! Should be "int* pa".
delete ps; // Ok!
delete pa; // Error! Should be "delete [] pa".
If instead C++ was regular and this was correct code, the type of the
pointer would carry the size information and allow the regular delete
operator to release the correct amount of memory. These irregularities
are avoided by std::array:
typedef std::array <int, 5> Array; // aggregate type
Array* pa = new Array; // Ok!
delete pa; // Ok!
Dereferencing the pointer, (*pa), gives you a reference (lvalue) to
the array as a whole, and an indexing operator is implemented for the
array class itself (not via degeneration into pointer arithmetic).
The new std::array circumvents the numerous irregularities between
pointers and arrays that causes so much confusion. I.e. you can copy
arrays, pass and return arrays by value to and from functions, and the
array will never implicitly convert to a pointer to the first element.
Hence I recommend its use instead of C-style arrays.
Regards,
Vidar Hasfjord
d) when you allocate memory using new T[], you use delete [], passing
it a T* returned to you by a prior cal to "new T[]". This is how new/
delete are supposed to work. You broke that with your casts, which is
the original sin of this code.
I would guess that all of a, b, and c will work on many
implementations, but I know of no guarantee for that. One can imagine
an implementation with bounds-checking where such code fails badly.
Your "R" example further down makes little sense, perhaps you should
have given it a bit more of thought. (E.g. what's with r[-1] = S, that
requires that T has operator=(int) or something, and S is a compile-
time constant anyhow!?)
Did you mean to create a variant of the old C trick with size,
followed by an array of struct, where size is a run-time value? There
was a +/- heated discussion some time ago about this here, somebody
made one half-decent C++ implementation then. (No conversion to an
array though, that wasn't the discussion's goal).
Goran.
For the size to be part of the pointer _type_ this size must be a
compile-time constant. But new[] does not require a compie-time
constant for the number of elements:
void foo(int x) {
new int[x]; // x is not a compile-time constant
}
So, the current new[] operator can do something that you can't emulate
with "new array<T,N>" properly.
Perhaps an alternate syntax would have been better and more regular:
void foo(int x)
{
int *p = new[x] int; // not real C++ code (unfortunately)
delete[] p;
int (*q)[5] = new int[5]; // not real C++ code (unfortunately)
delete q;
}
Anyhow, I consider new[]/delete[] and raw arrays to be nearly useless.
We have better alternatives and soon get some more: vector<T>,
array<T,N>, unique_ptr<array<T,N>>, for example. So, "fixing" arrays
and new[] w.r.t. regularity wouldn't buy you much. You'd mainly lose
compatibility with old code.
my 2 cents,
SG
Good point. But, if C++ was regular it would require the size to be a
compile-time constant; as it does everywhere else in the language
where an array type is expressed. I.e. the argument to new would
simply be a regular type expression.
The unrelated use of square brackets to specify a run-time argument is
highly irregular. And, more over, with templates in the language it is
unnecessary. Dynamic allocation can be implemented as a library
function. All you need is a low-level memory allocation function
(malloc) and placement-new (or a similar construct to allow you to
construct an object in allocated memory). E.g.
template <class T> T* construct (size_t n = 1); // replaces new
template <class T> void destruct (T*); // replaces delete
> Anyhow, I consider new[]/delete[] and raw arrays to be nearly useless.
> We have better alternatives and soon get some more: vector<T>,
> array<T,N>, unique_ptr<array<T,N>>, for example.
Agree. C++ programmers, except those dealing with legacy code or
implementing the standard library, can now avoid these irregularities.
Regards,
Vidar Hasfjord
This seems contradictory, the irregularity of array with runtime size
is AFAIS intended for providing a regular type expression syntax to
use with new operator.
> And, more over, with templates in the language it is
> unnecessary. Dynamic allocation can be implemented as a library
> function. All you need is a low-level memory allocation function
> (malloc) and placement-new (or a similar construct to allow you to
> construct an object in allocated memory). E.g.
>
> template <class T> T* construct (size_t n = 1); // replaces new
> template <class T> void destruct (T*); // replaces delete
And how do you handle constructor parameters for non-array
initialisation ?
For a workable solution, you would need perfect forwarding which isn't
yet standard.
Moreover, this means that unless you standardise it, every project
would have it's own syntax for allocation class-objects; if you
standardize it, why not make it an operator with a nice syntax.
> > Anyhow, I consider new[]/delete[] and raw arrays to be nearly useless.
> > We have better alternatives and soon get some more: vector<T>,
> > array<T,N>, unique_ptr<array<T,N>>, for example.
>
> Agree. C++ programmers, except those dealing with legacy code or
> implementing the standard library, can now avoid these irregularities.
Then, how do you implement a dynamic length array of non-copiable
objects ?
--
Michael
Neither copyable nor movable? One may consider either
boost::scoped_array<T> or std::vector<unique_ptr<T>> depending on
other constraints.
start using std::vector (or some other container) instead and forget about
manual memory management. leave it to compiler. you'll have much less memory
leaks.
since i started using stl i forgot about how stupid all that manual handling
of pointers and arrays used to be.
look how simpler it is:
// init
std::vector<int*> p(5);
// automatically deleted when it loses scope
Both statements are correct. What you actually need to correct is,
"...so you call delete [] on the pointer that new returned," to, "...so
you call delete [] on the same pointer type that new returned." Key
point here is that casting creates new objects.
>As your question has been answered elsewhere, I'll just add an
>interesting aside from a language design perspective. If C++ had a
>more regular design the type of the "new int [5]" expression would not
>degenerate to "int*". A regular design would render the array
>overloads of new and delete superfluous, and make your cast here
>unnecessary. Consider the irregularity of:
I don't think my question has bene answered, what I was asking was the
difference between each delete invocation, it seems that each is identical
but I get warning for delete *p, see code:
class Base{
public:
Base() {std::cout<<"Constructing base\n";}
~Base(){std::cout<<"Destructing base\n";}
};
int main() {
Base (*pA)[4] = (Base (*)[4])new Base[4];
Base* pB = new Base[3];
std::cout<<"\nDeleting pA:\n";
delete[] pA;
//delete[] *pA;
std::cout<<"\nDeleting pB:\n";
delete[] pB;
If you run the above code you see that each invocation of delete[] produces
the desired effect, even if you use *pA instead of pA. This however gives a
warning but I think the array is converted to a pointer. I did my tests on a
windows platform but it may not be the same on other platforms.
This suggests to me that the pointer-type is not rellevant, on my platform
at least, when calling delete[].
> typedef struct {int a, b, c, d, e;} Struct; // aggregate type
> typedef int Array [5]; // aggregate type
> Struct* ps = new Struct; // Ok!
> Array* pa = new Array; // Error! Should be "int* pa".
> delete ps; // Ok!
> delete pa; // Error! Should be "delete [] pa".
>If instead C++ was regular and this was correct code, the type of the
>pointer would carry the size information and allow the regular delete
>operator to release the correct amount of memory. These irregularities
>are avoided by std::array:
Yeah but it's never going to be a regular language, that is not the nature
of comp programming. All you can do is wrap it up in some class and make it
apper like regular syntax. I'm no big fan of unnecessary wrapping.
> typedef std::array <int, 5> Array; // aggregate type
> Array* pa = new Array; // Ok!
> delete pa; // Ok!
Yes but look at all the extra code you need to introduce behind the scenes
to get these semantics. I don't see any advantage in using an STL class over
a pointer in many cases, there are some cases where they are perfect and
really good , but not always.
>Dereferencing the pointer, (*pa), gives you a reference (lvalue) to
>the array as a whole, and an indexing operator is implemented for the
>array class itself (not via degeneration into pointer arithmetic).
Thats simple to achieve without the introduction of a STL class, for
example:
int (*pA)[6] = (int (*)[6])new int[6];
int (&rA)[6] = *pA;
The only advantage I see for using STL vectors is that they are expandable.
If you need a quick fix generic expandable array I agree they are the
solution. But for a simple fixed size array I wouldn't bother with an STL
class.
>The new std::array circumvents the numerous irregularities between
>pointers and arrays that causes so much confusion. I.e. you can copy
>arrays, pass and return arrays by value to and from functions, and the
>array will never implicitly convert to a pointer to the first element.
>Hence I recommend its use instead of C-style arrays.
I've never really used it TBH, my compiler setup doesn't seem to have that
library.
I don't really see the need for it in most cases, I'm quite happy with
normal C++ arrays, I'm just a bit rusty on C++ so I was trying to confirm
the behaviour of delete[] with the given cases.
TY for your post
Paul.
While it may not make a difference in this particular example, in
general it is very much relevant. The correct type is needed for
delete to call the correct destructor. Also note that both "delete"
and "delete[]" can be overloaded globally and per class, in which case
the correct type is needed to select the correct overload.
Regards,
Vidar Hasfjord
[...]
The above seems to be rather roundabout. Also, the templates indicate a
generality that is not really there: if you try to instantiate R<long,7> the
code will not compile. Furthermore, I do not understand why you would want
to store size information within the array when it is available through the
type system: after all, the array size is passed as a template parameter
whence it must be a compile time constant. Finally, the casting could invoke
undefined behavior as soon as you access array elements (any use other than
casting back is undefined, I think).
For comparison look at the free functions new_it<> and delete_it<>. To me,
it seems, that they do the same as the above class R<> except that the size
is not required to be a compile time constant. (Also, now the templates work
for types T!=int.)
#include <iostream>
#include <ostream>
#include <typeinfo>
template<typename T, int S, typename U= T (&)[S]>
class R{
public:
R():pp((int (*)[S])new int[S+1]), r(*(pp+1)){r[-1]=S;}
U getArray(){return r;}
void delete_it(){ delete[] (int*)pp; }
private:
int (*pp)[S];
T (&r)[S];
};
template < typename IntegerType >
IntegerType * new_it ( int size ) {
IntegerType * ptr = new IntegerType [size+1];
ptr[0] = size;
return ( ptr+1 );
}
template < typename IntegerType >
void delete_it ( IntegerType * ptr ) {
delete ( ptr-1 );
}
template<typename T>
void foo(T r){
std::cout<<"size of array:\t" << r[-1];
std::cout<< "\ntype of array:\t" << typeid(T).name();
}
int main() {
{
R<int, 7> r; // try R<long,7> here.
int (&r1)[7] = r.getArray();
foo(r.getArray());
std::cout<<"\ntype of r1:\t"<< typeid(r1).name();
r.delete_it();
}
{
std::cout << "\n";
int * ptr = new_it<int>(7); // try long * ptr = new_it<long>(7) here;
foo(ptr);
delete_it( ptr );
std::cout << "\n";
}
}
Best
Kai-Uwe Bux
I'm not talking about pointer-types , in general. I'm talking about pointer
to arrays and pointer to array-object types as in:
int* or int(*)[size];
Base* or Base (*)[size]
etc etc.
If I call delete[] on int*, it's no different to int (*)[size]? Or is it?
How does the compiler know how many destructors to call?
And what if call delete[] *(int (*)[size])? Is it implicitly converted to
int*?
>
>"Vidar Hasfjord" <vattila...@yahoo.co.uk> wrote in message
>news:80d512c9-799d-445d-bd99->58c30a...@l11g2000yqb.googlegroups.com...
>>On Mar 27, 5:34 am, "Paul" <pchris...@yahoo.co.uk> wrote:
>>> [Suppose I have the following code:
>>>
>>> int (*p)[5] = (int (*)[5])new int[5];
>>>
>>> How do I delete the allocated memory?
>
>>As your question has been answered elsewhere, I'll just add an
>>interesting aside from a language design perspective. If C++ had a
>>more regular design the type of the "new int [5]" expression would not
>>degenerate to "int*". A regular design would render the array
>>overloads of new and delete superfluous, and make your cast here
>>unnecessary. Consider the irregularity of:
>
>I don't think my question has bene answered, what I was asking was the
>difference between each delete invocation, it seems that each is identical
It is an issue of type as Vidar points and myself have pointed out. The only
thing that your three choices from the OP have in common is that the address
stored by the pointer is the same. Not to re-open a whole can of worms, but had
you walked away from the previous seven threads that you started in agreement
with those that replied, you would not be confused on this point.
I don't think that's what he means when he says regular language, but anyway, I
think it is more of an issue of backwards compatibility with C than simply the
nature of programming in general.
>
>> typedef std::array <int, 5> Array; // aggregate type
>> Array* pa = new Array; // Ok!
>> delete pa; // Ok!
>
>Yes but look at all the extra code you need to introduce behind the scenes
>to get these semantics. I don't see any advantage in using an STL class over
>a pointer in many cases, there are some cases where they are perfect and
>really good , but not always.
I see several advantages, even for many simple cases. See below.
>
>>Dereferencing the pointer, (*pa), gives you a reference (lvalue) to
>>the array as a whole, and an indexing operator is implemented for the
>>array class itself (not via degeneration into pointer arithmetic).
>
>Thats simple to achieve without the introduction of a STL class, for
>example:
>
>int (*pA)[6] = (int (*)[6])new int[6];
>int (&rA)[6] = *pA;
>
>The only advantage I see for using STL vectors is that they are expandable.
>If you need a quick fix generic expandable array I agree they are the
>solution. But for a simple fixed size array I wouldn't bother with an STL
>class.
std::vector gives you size management, memory management, and a set of
guarantees with regards to behavior. Because it is an STL container, you can
define custom allocators as well as use the class iterators to access the
container or perform standard algorithms on the container data. Keep in mind
that std::vector is the "quintessential generic" general purpose container.
Other containers give you a variety of other standardized behaviors and
functionality. Even for a fixed array, std::vector's type safety and
interoperability with the other C++ built in class types make it a worthy
consideration.
For me personally, only for the case of lookup tables of constants or tables of
data that does not change do I generally prefer raw arrays over STL containers.
>>The new std::array circumvents the numerous irregularities between
>>pointers and arrays that causes so much confusion. I.e. you can copy
>>arrays, pass and return arrays by value to and from functions, and the
>>array will never implicitly convert to a pointer to the first element.
>>Hence I recommend its use instead of C-style arrays.
>
>I've never really used it TBH, my compiler setup doesn't seem to have that
>library.
>I don't really see the need for it in most cases, I'm quite happy with
>normal C++ arrays, I'm just a bit rusty on C++ so I was trying to confirm
>the behaviour of delete[] with the given cases.
>TY for your post
>Paul.
Just as a side note and a bit off-topic (but not entirely out of context)
consider the benefits of a smart pointer class over using raw pointers in
general. As cases become more complex, such as with COM, for example, you stand
to benefit greatly from not having to manage things such as reference counts,
pointer validitiy, and internal allocation.
>
>"Vidar Hasfjord" <vattila...@yahoo.co.uk> wrote in message
>news:35e223bd-251f-4697-aa66->6809d0...@w7g2000yqe.googlegroups.com...
>>On Mar 28, 6:37 pm, "Paul" <pchris...@yahoo.co.uk> wrote:
>>> This suggests to me that the pointer-type is not rellevant, on my
>>> platform
>>> at least, when calling delete[].
>
>>While it may not make a difference in this particular example, in
>>general it is very much relevant. The correct type is needed for
>>delete to call the correct destructor. Also note that both "delete"
>>and "delete[]" can be overloaded globally and per class, in which case
>>the correct type is needed to select the correct overload.
>
>I'm not talking about pointer-types , in general. I'm talking about pointer
>to arrays and pointer to array-object types as in:
>int* or int(*)[size];
>Base* or Base (*)[size]
>etc etc.
Then yes, you are in fact talking about pointer types. I knew that this thread
inevitably was going to come to this. It was just a matter of time as the
preceding seven Paul discussion threads have shown.
agreed.
Granted, you can say a similarity of syntax is regularity, but the
semantic irregularity it causes is high, and it was the semantic
irregularities I alluded to here. I view it as undesirable that the
type-id syntax has been reused to specify a run-time parameter.
> > template <class T> T* construct (size_t n = 1); // replaces new
> > template <class T> void destruct (T*); // replaces delete
>
> And how do you handle constructor parameters for non-array
> initialisation ?
> For a workable solution, you would need perfect forwarding which isn't
> yet standard.
Sorry, these were meant to replace just "new[]" and "delete[]",
leaving "new" and "delete" as before, but with regular semantics.
Perfect forwarding would make it feasable to also replace "new" and
"delete", although the language would still need placement-new, or
something similar, to construct objects in allocated memory.
> Moreover, this means that unless you standardise it, every project
> would have it's own syntax for allocation class-objects; if you
> standardize it, why not make it an operator with a nice syntax.
I'm just hypothesising about a regular subset of C++ here, but yes,
you may assume it would have the necessary features in the language
and support in the library. But I don't see how an operator can be
much nicer than template syntax. This is the road we're on, anyway (C+
+0x):
auto pa = make_shared <A> (...); // Create A, return shared_ptr.
Regards,
Vidar Hasfjord
You may have to consult the C++ standard to see if it gives any
guarantees. Despite your casts, "int*" is what "new" returned, so that
seems the only sure thing. Maybe allowing "int (*)[size]" is a
concession from the compiler for having decayed the type in the first
place? :-)
> How does the compiler know how many destructors to call?
See:
http://www.parashift.com/c%2B%2B-faq-lite/freestore-mgmt.html#faq-16.14
> delete[] *(int (*)[size])? Is it implicitly converted to int*?
Yes, and Visual C++ 2010 also produces a warning in this case (warning
C4154: deletion of an array expression; conversion to pointer
supplied).
Regards,
Vidar Hasfjord
Yes I already knew about these techniques.
What my concern was that with delete [] called on int (*)[size] type
pointer...
C++ would call the destructor for the 1st element, then move
size*sizeof(int), that is sizeof( *(int (*)[size]) ) to look for the second
element. As oppose to moving only sizeof(int) per element, in the case of
delete[] int*
. Therefore I would be freeing more memory than I allocated, but this
doesn't seen to happen
>
>> delete[] *(int (*)[size])? Is it implicitly converted to int*?
>
> Yes, and Visual C++ 2010 also produces a warning in this case (warning
> C4154: deletion of an array expression; conversion to pointer
> supplied).
>
Ah nice that confirms that , for VC++ at least.
Ty again for your post.
You are repeatedly trying to get into UB land. You should __not__ ask
the question you are asking. You never allocated int (*)[size]. Can't
do that, perhaps because of array type erasure: as soon as the array
type hits operator new, array type is erased and new sees a pointer (a
double one, "**", but nonetheless). You never got an __array__ out of
new, and you can't pass an array to delete.
If you have TYPE* that you need to delete, you must know how you
allocated it, end of. If you did p = new TYPE(), you do delete p; if
you did p = new TYPE[1], you do delete [] p; (yes, even if you put 1
in []). If you did p = new TYPE(*)[1], you do delete [] p (but, p's
type is TYPE**).
> How does the compiler know how many destructors to call?
Not ours to know (hint: implementation's heap management internals
serve for that).
> And what if call delete[] *(int (*)[size])? Is it implicitly converted to
> int*?
I'd wager yes, due to array-type-erasure. But you did not __allocate__
that, now did you? (That is, you have some other problem in your code,
so this question should not be asked in the first place).
Goran.
>If you have TYPE* that you need to delete, you must know how you
>allocated it, end of. If you did p = new TYPE(), you do delete p; if
>you did p = new TYPE[1], you do delete [] p; (yes, even if you put 1
>in []). If you did p = new TYPE(*)[1], you do delete [] p (but, p's
>type is TYPE**).
The type is the same , both int type arrays, only the level of dereference
is different for example:
int (*p1)[5] = (int (*)[5])new int*[5]; /*2d array*/
int (*p2)[5] = (int (*)[5])new int[5]; /*1d array*/
int (*p3)[5] = new int[5][5]; /*2d array*/
delete[] p1;
delete[] p2;
delete[] p3;
What is the difference with the above deletes?
>
>> How does the compiler know how many destructors to call?
>
>Not ours to know (hint: implementation's heap management internals
>serve for that).
>> And what if call delete[] *(int (*)[size])? Is it implicitly converted to
>> int*?
>I'd wager yes, due to array-type-erasure. But you did not __allocate__
>that, now did you? (That is, you have some other problem in your code,
>so this question should not be asked in the first place).
I don't know this term "array type erasure". What do you mean by that?
An inane question since the case itself is inane. Not to mention this has been
asked and answered more than once.
What you should be concerned with asking yourself is why you are casting the
pointer types returned by new into a different types without at least first
storing the uncasted returned type .
Each of the above new expressions returns a different type of pointer. As others
have said more than once, it is a bad idea to cast the type of new's return and
then call delete [] on it because it opens the door to UB for every case where
new's return type does not match the type of pointer you pass to delete [].
In case it has not been said, allocating multidimensional arrays with new
creates complexity with the deallocation. Specifically referring to the third
case for your example, delete [] p3 fails to deallocate the memory allocated.
You must loop delete []. Yet another reason to prefer STL vector for your
dynamic array needs.
As far as I am concerned, difference is: first two are UB (platform-
specific at best), because of wrong casts in corresponding "new",
whereas the third one is correct.
> I don't know this term "array type erasure". What do you mean by that?
FAQ uses term "decay". I meant same thing (that was the term used to
explain the thing to me).
Goran.
Why are they UB? After having a read through the rellevant pages of the
standard I don't think that it is UB. The standard specifically states that
the pointer returned from new must be castable.
Consider this more complex example:
class Base{
public:
Base() {std::cout<<"Constructing base\n";}
virtual ~Base(){std::cout<<"Destructing base\n";}
};
class Derived: public Base{
public:
Derived() {std::cout<<"Constructing derived\n";}
~Derived(){std::cout<<"Destructing derived\n";}
};
int main() {
Base (*p2)[3] = (Base (*)[3])new Derived[2][3];
delete[] p2;
}
The cast is required , otherwise you'd need to loop through the array
columns for allocation and deallocation..
I could cast it back prior to deletion with:
delete[] (Derived (*)[3])p2;
But this is unneccessary because Base type is an acceptable pointer type.
The type is only neccessay for the correct destruction of objects. For
example:
Base *p2 = new Derived[3];
delete[] p2;
is identical to
Base (*p2)[3] = (Base (*)[3])new Derived[3];
deletep[] p2;
The type that is relevant here is that it is Base or Derived, the number of
elements destructed is decided by the C runtime. As long as the dereferenced
pointer passed to delete has the same value as the pointer returned by new
all is ok, because it is converted to void* anyway. The C runtime decides
whether it deletes 3 objects or 1 , not the type system.
If int[3] and int* both point to the same address, then converted to void*
they are identical.
The C++ type system is only interested in if its an array of int-typ,
Derived-type , or Base-type, It not up to the type system to deicde how many
destructors to call.
It would be UB if you converted the pointer to a different type altogether
for example:
double* p = (double*)new int[6];
delete[] p;
This would be UB , because you are converting to a new type of array..
>
>> I don't know this term "array type erasure". What do you mean by that?
>
>FAQ uses term "decay". I meant same thing (that was the term used to
>explain the thing to me).
Ok I see you are talking about implicit pointer conversion.
HTH
Paul.
>
> "Goran" <goran...@gmail.com> wrote in message
> news:bed4b5d7-1577-4a11...@k9g2000yqi.googlegroups.com...
>>On Mar 29, 1:07 pm, "Paul" <pchris...@yahoo.co.uk> wrote:
>>> int (*p1)[5] = (int (*)[5])new int*[5]; /*2d array*/
>>> int (*p2)[5] = (int (*)[5])new int[5]; /*1d array*/
>>> int (*p3)[5] = new int[5][5]; /*2d array*/
>>> delete[] p1;
>>> delete[] p2;
>>> delete[] p3;
>>>
>>> What is the difference with the above deletes?
>>
>>As far as I am concerned, difference is: first two are UB (platform-
>>specific at best), because of wrong casts in corresponding "new",
>>whereas the third one is correct.
>
> Why are they UB? After having a read through the rellevant pages of the
> standard I don't think that it is UB.
We shall see.
> The standard specifically states that the pointer returned from new must
> be castable.
Correct: [5.2.10/7] states:
A pointer to an object can be explicitly converted to a pointer to an
object of different type.65) Except that converting an rvalue of type
"pointer to T1" to the type "pointer to T2" (where T1 and T2 are object
types and where the alignment requirements of T2 are no stricter than
those of T1) and back to its original type yields the original pointer
value, the result of such a pointer conversion is unspecified.
That implies that after casting, you have an unspecified result. The only
thing you can do with it, is casting back, and even that presupposes
compatible alignment requirement.
In particular, passing the unspecified value obtained by casting to delete
or delete [] is undefined behavior.
> Consider this more complex example:
> class Base{
> public:
> Base() {std::cout<<"Constructing base\n";}
> virtual ~Base(){std::cout<<"Destructing base\n";}
> };
>
> class Derived: public Base{
> public:
> Derived() {std::cout<<"Constructing derived\n";}
> ~Derived(){std::cout<<"Destructing derived\n";}
> };
>
> int main() {
> Base (*p2)[3] = (Base (*)[3])new Derived[2][3];
> delete[] p2;
> }
>
> The cast is required , otherwise you'd need to loop through the array
> columns for allocation and deallocation..
> I could cast it back prior to deletion with:
> delete[] (Derived (*)[3])p2;
>
> But this is unneccessary because Base type is an acceptable pointer type.
What do you mean by "acceptable"?
Also, the value of the variable p2 is _unspecified_ as it is obtained
through casting.
> The type is only neccessay for the correct destruction of objects. For
> example:
> Base *p2 = new Derived[3];
> delete[] p2;
>
> is identical to
> Base (*p2)[3] = (Base (*)[3])new Derived[3];
> deletep[] p2;
>
> The type that is relevant here is that it is Base or Derived, the number
> of elements destructed is decided by the C runtime. As long as the
> dereferenced pointer passed to delete has the same value as the pointer
> returned by new all is ok, because it is converted to void* anyway. The C
> runtime decides whether it deletes 3 objects or 1 , not the type system.
Sameness of value is not guaranteed by the standard (pretending we know what
it means). Consider:
int main () {
Derived (*p1) [3] = new Derived [2][3];
Base (*p2) [3] = (Base (*)[3]) p1;
assert( p1 == p2 );
}
This does not even compile as p1 and p2 are of different type.
> If int[3] and int* both point to the same address, then converted to void*
> they are identical.
So this is what we mean by "sameness of values". Ok, let's consider
int main () {
Derived (*p1) [3] = new Derived [2][3];
Base (*p2) [3] = (Base (*)[3]) p1;
assert( (void*)p1 == (void*)p2 );
}
Now, the code compiles. However, contrary to expectations, the assert is
allowed to _fail_ because the value of p2 is unspecified. In fact, using the
unspecified value as an argument for a cast is UB. So, we could do:
int main () {
Derived (*p1) [3] = new Derived [2][3];
Base (*p2) [3] = (Base (*)[3]) p1;
assert( p2 == (Base (*) [3]) p1 );
}
This looks as though it could not fail. However, the two sides of the == are
both unspecified values. It is neither clear that they are equal nor that
comparing them does not result in a core dump.
If you see more guarantees in the standard that would render any of the
above defined behavior, please cite them.
[...]
Best,
Kai-Uwe Bux
> In particular, passing the unspecified value obtained by casting to delete
> or delete [] is undefined behavior.
What is unspecified , the cast does not make the pointer *unspecified*
>
>
>> Consider this more complex example:
>> class Base{
>> public:
>> Base() {std::cout<<"Constructing base\n";}
>> virtual ~Base(){std::cout<<"Destructing base\n";}
>> };
>>
>> class Derived: public Base{
>> public:
>> Derived() {std::cout<<"Constructing derived\n";}
>> ~Derived(){std::cout<<"Destructing derived\n";}
>> };
>>
>> int main() {
>> Base (*p2)[3] = (Base (*)[3])new Derived[2][3];
>> delete[] p2;
>> }
>>
>> The cast is required , otherwise you'd need to loop through the array
>> columns for allocation and deallocation..
>> I could cast it back prior to deletion with:
>> delete[] (Derived (*)[3])p2;
>>
>> But this is unneccessary because Base type is an acceptable pointer type.
>
> What do you mean by "acceptable"?
Acceptable pointer type, that is a base(with virtual destructor) or derived
class. There are probably many other acceptable pointer conversions which
are Implementation specific e.g: short to int where they are both the same
size.
>
> Also, the value of the variable p2 is _unspecified_ as it is obtained
> through casting.
Casting doesn't make it *unspecified*.
>
>> The type is only neccessay for the correct destruction of objects. For
>> example:
>> Base *p2 = new Derived[3];
>> delete[] p2;
>>
>> is identical to
>> Base (*p2)[3] = (Base (*)[3])new Derived[3];
>> deletep[] p2;
>>
>> The type that is relevant here is that it is Base or Derived, the number
>> of elements destructed is decided by the C runtime. As long as the
>> dereferenced pointer passed to delete has the same value as the pointer
>> returned by new all is ok, because it is converted to void* anyway. The C
>> runtime decides whether it deletes 3 objects or 1 , not the type system.
>
> Sameness of value is not guaranteed by the standard (pretending we know
> what
> it means). Consider:
>
> int main () {
> Derived (*p1) [3] = new Derived [2][3];
> Base (*p2) [3] = (Base (*)[3]) p1;
> assert( p1 == p2 );
> }
>
> This does not even compile as p1 and p2 are of different type.
That doesn't mean the values are not the same though does it.
>
>> If int[3] and int* both point to the same address, then converted to
>> void*
>> they are identical.
>
> So this is what we mean by "sameness of values". Ok, let's consider
>
> int main () {
> Derived (*p1) [3] = new Derived [2][3];
> Base (*p2) [3] = (Base (*)[3]) p1;
> assert( (void*)p1 == (void*)p2 );
> }
>
> Now, the code compiles. However, contrary to expectations, the assert is
> allowed to _fail_ because the value of p2 is unspecified. In fact, using
> the
> unspecified value as an argument for a cast is UB. So, we could do:
I don't know what your problem is with understand the meaning of two of the
same values.
its simple:
float f = 65;
int x = 65;
long l = 65;
same values.
>
> int main () {
> Derived (*p1) [3] = new Derived [2][3];
> Base (*p2) [3] = (Base (*)[3]) p1;
> assert( p2 == (Base (*) [3]) p1 );
> }
>
> This looks as though it could not fail. However, the two sides of the ==
> are
> both unspecified values. It is neither clear that they are equal nor that
> comparing them does not result in a core dump.
I don't have a clue what you are talking about, what is an unspecified
value? What fails?
A pointers' value is the address it points to , if two pointers point to the
same address they have they same value, simple as that.
>
> If you see more guarantees in the standard that would render any of the
> above defined behavior, please cite them.
>
What guarantees you talknig about here?
Return type of "new int(*)[5]" is int**. You cast that into int(*)[5],
using C cast. That, as far as I can see, ends up in same effect as
reinterpret_cast, and reinterpret_cast is UB (or platform specific at
best).
> Consider this more complex example:
> class Base{
> public:
> Base() {std::cout<<"Constructing base\n";}
> virtual ~Base(){std::cout<<"Destructing base\n";}
>
> };
>
> class Derived: public Base{
> public:
> Derived() {std::cout<<"Constructing derived\n";}
> ~Derived(){std::cout<<"Destructing derived\n";}
>
> };
>
> int main() {
> Base (*p2)[3] = (Base (*)[3])new Derived[2][3];
> delete[] p2;
>
> }
>
> The cast is required , otherwise you'd need to loop through the array
> columns for allocation and deallocation..
First, the cast is not required, because
Derived (*p2)[3] = new Derived[2][3];
delete [] p2;
works just as well.
Second, the problem with your exact example is that in practice just
does not work. And I mean, at all!
Try this:
class Base{
public:
Base() : i(0) {}
int i;
};
class Derived: public Base{
public:
Derived() : j(1) {}
int j;
};
Base (*p2)[3] = (Base (*)[3])new Derived[2][3];
const Base& b = p2[0][1];
assert(0 == b.i); // Fires on common implementations
assert(1 == b.i); // Does not fire on common implementations. Eh!?
Of course, problem is that pointer returned by "new Derived[2][3]" and
"Base (*)[3]" have unrelated types, and my code snippet shows why that
is required.
Goran.
> >FAQ uses term "decay". I meant same thing (that was the term used to
> >explain the thing to me).
>
> Ok I see you are talking about implicit pointer conversion.
Nice try ;-);
Goran.
[...]
Ok, so you are saying that the C-style cast you are using is _not_ governed
by clause [5.2.10/7]. Please specify which clause of the standard you are
relying on in determining the behavior of the cast expression.
Best,
Kai-Uwe Bux
But you did cast to a different type in both of the above cases that you casted:
1) from int** to int(*)[5]
2) from int* to int(*)[5]
or in language that even you should understand since it appears that you are
confused by the Standard's use of what pointer to and object of different type
means:
1) from "pointer to int pointer" to "pointer to array of int"
2) from "pointer to int" to "pointer to array of int"
Once again, this takes us back to all of the previous message threads that you
have started which demonstrate some form of your confusion with the fact that a
pointer to int and pointer to array of int are not the same thing.
Now whether or not there are stricter alignment requirements for T2 than T1 is
another story. I do not think there is under Windows for the above types, but
the idea is that UB is potentially there where C++ is concerned. Something that
could easily be remedied by not casting the return in the first place.
#include <iostream>
class BaseA{
public:
int k;
BaseA() {std::cout<<"Constructing base a\n";}
virtual ~BaseA(){std::cout<<"Destructing base a\n";}
};
class BaseB {
public:
int i;
BaseB() {std::cout<<"Constructing base b\n";}
virtual ~BaseB(){std::cout<<"Destructing base b\n";}
};
class Derived: public BaseA, BaseB {
public:
int j;
Derived() {std::cout<<"Constructing derived\n";}
~Derived(){std::cout<<"Destructing derived\n";}
};
int main() {
Derived (*p1) [3] = new Derived [2][3];
BaseB (*p2)[3] = (BaseB (*)[3])p1;
delete [] p2;
}
This program segfaults on my machine.
I think, it is allowed to do so.
Best,
Kai-Uwe Bux
So, as far as you can see, any use of a c-style cast will immediately cause
UB?
<snip>
>Of course, problem is that pointer returned by "new Derived[2][3]" and
>"Base (*)[3]" have unrelated types, and my code snippet shows why that
>is required.
Your code shows me nothing except that you are a noob who uses assert, If
you want to expalin something to me in code please don't use noob statements
like assert.
> >FAQ uses term "decay". I meant same thing (that was the term used to
> >explain the thing to me).
>
> Ok I see you are talking about implicit pointer conversion.
Nice try ;-);
What does this mean? What am I trying to do in your mind?
Sorry for snipping etc but dont have time to manually indent all that crap.
Not will. Could. Your cast up there __will__, however (and a very
simple example has shown that).
> >Of course, problem is that pointer returned by "new Derived[2][3]" and
> >"Base (*)[3]" have unrelated types, and my code snippet shows why that
> >is required.
>
> Your code shows me nothing except that you are a noob who uses assert, If
> you want to expalin something to me in code please don't use noob statements
> like assert.
First, assert is not a statement, it's a function. Second, it's use is
incidental to the problem. Noob or not, assert shows that your cast
does not work.
In slightly more detail: in common implementations, object's memory
layout is such that your cast, on your example, fails horribly. Line
const Base& b = p2[0][1];
does not produce a reference to b (and it should). It does not do it,
because the cast on the line where new is called is __wrong__.
In even more detail: what new allocated (on common implementations) is
6 consecutive instances of Derived. So let's presume a 32-bit platform
and a common implementation. New gives (memory layout):
32 bits: Base.i
32 bits: Derived.j
32 bits: Base.i
32 bits: Derived.j
... 6 of those in total
You tried to cast that to (memory layout on common implementations):
32 bits: Base.i
32 bits: Base.i
... 6 of those in total
Your cast causes "b" to "reference" Derived.j, which makes no sense
whatsoever. "assert" was only there to show you this. I hoped not so
many words were needed, but alas...
Goran.
------------------------------------------
Who the hell do you think you are ?
You cant even communicate properly I cant be arsed with arseholes who cant
communicate properly.
Im not gonna bother indenting and making an effort for someone who obviously
thinks he is abov eme.
I told you your example showed me nothing except that you are some noob who
uses *STATEMENTS* like assert
I was mistaken, I apologize. assert is not a function, it's rather a
macro.
It's not a statement though. Please refer to section 6 of the current
language standard for more detail on what a statement is.
Goran.
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
I dont care what its called in the standards I called it a statement and you
knew what i meant.
What I dont understand is what exactly your argument is, you fail to
communicate properly.
You said something was UB but no expalanation, just because it appeared to
be UB to you.
Now you are blabbing on about some assert thing. WHat exactly has all this
got to do with delete[] ?
Your cast is on the new side invokes UB. By consequence, your examples
are buggy, and so is your call to operator[].
You do not seem to accept that cast invokes UB, so I made you a piece
of code that shows why your cast is, and should be, UB.
For that piece of code, I used assert to ascertain what should be true
(that "0" equals "b.i"). If you compile this snippet without NDEBUG,
"assert(0 == b.i)" should not fire, because, clearly, Base() sets i to
0. And yet, this assert does fire (on common implementations). Why?
Because your cast invoked UB. Consequently, everything else is wrong,
including delete[] you're trying to pull off.
Goran.
Casting from derived to base is called "upcasting" not "downcasting".
/Leigh
Your cast is on the new side invokes UB. By consequence, your examples
are buggy, and so is your call to operator[].
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Why?
Please explain why it is UB?
Any time we cast in C++ we produce UB?
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
You do not seem to accept that cast invokes UB, so I made you a piece
of code that shows why your cast is, and should be, UB.
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Your code doesn't prove the cast is UB. I would accept it if it is UB but as
far as I can see all the standard says is that new must return a castable
pointer, this implies that its allowed to be casted.
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
For that piece of code, I used assert to ascertain what should be true
(that "0" equals "b.i"). If you compile this snippet without NDEBUG,
"assert(0 == b.i)" should not fire, because, clearly, Base() sets i to
0. And yet, this assert does fire (on common implementations). Why?
Because your cast invoked UB.
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Eh? Because you code asserts something to be not equal you assert this to
mean the cast produces UB? How do you come to that conclusion?
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Think about how you draw a family tree: ancestors toward the top;
descendants toward the bottom (the tree is upside down).
Anyway it doesn't matter how it *seems* to you; what is important is to
be technically accurate and to use correct terminology: casting from
derived to base is called "upcasting"; casting from base to derived is
called "downcasting".
/Leigh
A family tree is exact opposite of a class inheritance, a parent object is
the most derived object.
In a family tree the children are most derived.
>
> Anyway it doesn't matter how it *seems* to you; what is important is to be
> technically accurate and to use correct terminology: casting from derived
> to base is called "upcasting"; casting from base to derived is called
> "downcasting".
>
Yes says the proven idiot who thinks p doesn't point to an array with:
int* p = new int[5]
Because you are casting from a pointer of one type to a pointer of an
unrelated type (and that's what the compiler told you, too, when you
tried without a cast, now did it?)
> You do not seem to accept that cast invokes UB, so I made you a piece
> of code that shows why your cast is, and should be, UB.
> xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
> Your code doesn't prove the cast is UB.
It does. See below.
> For that piece of code, I used assert to ascertain what should be true
> (that "0" equals "b.i"). If you compile this snippet without NDEBUG,
> "assert(0 == b.i)" should not fire, because, clearly, Base() sets i to
> 0. And yet, this assert does fire (on common implementations). Why?
> Because your cast invoked UB.
> xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
> Eh? Because you code asserts something to be not equal you assert this to
> mean the cast produces UB? How do you come to that conclusion?
> xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
That something is b.i, which is initialized to 0 and never changed.
Yet, assert does fire.
My claim is that it fires because cast was UB, and, on common
implementations, result is that code sees that b.i equals one, not
zero.
My claim is that implementation is correct in everything it has done,
that code is correct in every detail, except for the UB cast. If cast
wasn't UB, assert(0 == b.i) would not fire. Since it does, it's
because cast is UB.
Goran.
A family tree was an example of a tree which you typically draw upside
down (the root is at the top); an inheritance hierarchy is typically
viewed as a tree where the base classes are at the root of the tree and
similar to a family tree the root is at the top hence the term "upcast".
>
>>
>> Anyway it doesn't matter how it *seems* to you; what is important is
>> to be technically accurate and to use correct terminology: casting
>> from derived to base is called "upcasting"; casting from base to
>> derived is called "downcasting".
>>
> Yes says the proven idiot who thinks p doesn't point to an array with:
> int* p = new int[5]
p is not a pointer to an array; p is a pointer to an int.
You are the one who continually provides evidence to everyone reading
your posts as to who the idiot actually is; you certainly have yet to
provide any evidence or proof that those who continually correct you are
idiots although giving a troll such as yourself any time probably *is*
idiotic.
If you are not a troll and you actually believe the bullshit you post
then your cause is a hopeless one.
/Leigh
Not _every_ cast. Just the one in your code :-)
> A cast from int* to int*[] doesn't seem like a major conversion of any
> major concern to me.
It is a conversion not governed by anything else than [5.2.10/7]. And the
governing clause [5.2.10/7] specifies that the result of the cast is
unspecified. Using those unspecified values farther down the road in any way
not listed in [5.2.10/7] is undefined behavior as per:
1.3.12 undefined behavior
behavior, such as might arise upon use of an erroneous program construct
or erroneous data, for which this International Standard imposes no
requirements. Undefined behavior may also be expected when this
International Standard omits the description of any explicit definition of
behavior.
Best,
Kai-Uwe Bux
I don't say that.
> Or are you saying that its only UB to cast a pointer of Derived (*)[size]
> to BaseB (*)[size], but its ok to cast a Derived* to a baseB*?
I don't even say that. What I say is that casting the pointer p1 (of type
Derived(*)[3]) to the type (BaseB(*)[3]) results in an unspecified value of
p2. What is UB is calling delete[] on the unspecified value p2.
> As far as I was aware is perfectly ok to downcast to a Base class. As long
> as the Base class has a virtual destructor the object destruction will
> destruct the whole Dervied object.
True. If we had
Derived* p1 = new Derived;
BaseB* p2 = (BaseB*)p1;
delete p2;
everything would be perfectly fine. Note, however, that the case is
_entirely_ different, starting with the C-style cast (BaseB*)p1 being a
static_cast<> as opposed to the reinterpret_cast<> from the previous
snippet. Now, the (redundant) cast is governed by [5.2.9/2]. The delete
expression is governed by [5.3.5/3].
Note, however, that this snippet has UB:
Derived* p1 = new Derived [3];
BaseB* p2 = (BaseB*)p1; // fine so far, but p2[1] would be UB
delete [] p2; // UB as per [5.3.5/3]
This involves the distinction of dynamic and static types: p2 has dynamic
type Derived* and static type BaseB*.
Best,
Kai-Uwe Bux
Because you are casting from a pointer of one type to a pointer of an
unrelated type (and that's what the compiler told you, too, when you
tried without a cast, now did it?)
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
No my code compiles fine, The types are not unrelated they are both int
types.
I can cast from int[] to int* implicitly because its a realated type.
UB doesn't mean that something will or will not work.
It means that the Standard simply does not guarantee the behaviour.
>>>So are you are saying is that its
>>> UB to cast a pointer to Derived into a pointer to BaseB?
>>
>> I don't say that.
>>
>>> Or are you saying that its only UB to cast a pointer of Derived (*)[size]
>>> to BaseB (*)[size], but its ok to cast a Derived* to a baseB*?
>>
>> I don't even say that. What I say is that casting the pointer p1 (of type
>> Derived(*)[3]) to the type (BaseB(*)[3]) results in an unspecified value
>> of
>> p2. What is UB is calling delete[] on the unspecified value p2.
>>
>I thought you might actually have a valid point, but now its quite clear
>your just another idiot who has no other objective than to prove anything I
>say is wrong.
Everybody that disagrees with Paul is an idiot, espectially when they use logic
or proper citation of the Standard to prove him wrong.
>
>"Leigh Johnston" <le...@i42.co.uk> wrote in message
>news:sNOdnZtNWPu3-A7Q...@giganews.com...
>> On 30/03/2011 18:06, Paul wrote:
>>>
>>> "Leigh Johnston" <le...@i42.co.uk> wrote in message
>>> news:dqydndSmfoUl1Q7Q...@giganews.com...
>>>> On 30/03/2011 15:38, Paul wrote:
>>>>> As far as I was aware is perfectly ok to downcast to a Base class. As
>>>>> long as the Base class has a virtual destructor the object destruction
>>>>> will destruct the whole Dervied object.
>>>>
>>>> Casting from derived to base is called "upcasting" not "downcasting".
>>>>
>>> Thats a rather back to front way of looking at it. Casting to a
>>> subobject is casting up?
>>
>> Think about how you draw a family tree: ancestors toward the top;
>> descendants toward the bottom (the tree is upside down).
>
>A family tree is exact opposite of a class inheritance, a parent object is
>the most derived object.
>In a family tree the children are most derived.
I am starting to think you are making shit up as you go along here. And when
you are called on your wrongness, you become pridefully defensive and argue the
most inane points instead of just acknowledging those who have helped you to be
correct.
TCPPPL 15.4 Class Hierarchies:
"Casting from base class to a derived class is often called a downcast because
of the convention of drawing inheritance trees growing from the root down.
Similarly, a cast from the derived class to the base is called an upcast."
Of course, you're entitled to your own language with its own vocabulary and its
own set of terms, but keep in mind that when you come to these forums, you are
going to be severely limited in such a way that you feel that everybody here is
trying to prove everything that you say is wrong.
>
>>
>> Anyway it doesn't matter how it *seems* to you; what is important is to be
>> technically accurate and to use correct terminology: casting from derived
>> to base is called "upcasting"; casting from base to derived is called
>> "downcasting".
>>
>Yes says the proven idiot who thinks p doesn't point to an array with:
>int* p = new int[5]
Ahh, I see, you're still confused. Well I am all too happy to help. That's
what we are here for :)
p is a pointer to the single int that was returned by new.
p is pointer of "int type", not "array of int type"
p only points to a single int
Anything else that you think p points to is meaningful only in your mind.
Consult ISO/IEC 14882 for further information and clarification if you are still
confused.
By the way, I proudly stand among those that you call idiots since this
distringuished group of idiots are all of those that have successfully used
simple logic and proper citation of The Standard to prove you wrong.
Welcome to the club. The rest of us realized this a month or two ago.
Just ignore the troll.
>
> You are the one who continually provides evidence to everyone reading your
> posts as to who the idiot actually is; you certainly have yet to provide
> any evidence or proof that those who continually correct you are idiots
> although giving a troll such as yourself any time probably *is* idiotic.
>
> If you are not a troll and you actually believe the bullshit you post then
> your cause is a hopeless one.
>
Very good but it's obvious to anyone, with isn't an idiot, that you are an
idiot. As for the idiots who agree with you, I don't really care what they
think .
:-)
Whilst p does point to the initial element of an array that does not
mean that p is a pointer to an array; p is a pointer to an int.
[...]
/Leigh
Irrelevant. There's gigabytes of source that compile fine, but does
not work.
> , The types are not unrelated they are both int
> types.
> I can cast from int[] to int* implicitly because its a realated type.
You can, but that is irrelevant for what you're trying to do. Besides,
cast is already implicit, so why would you!?
The problem is elsewhere: when you do "new TYPE[size1][size2]", the
type of result is "TYPE**", and that is __unrelated__ to "TYPE (*)
[size2]". Ppeople already have quoted you relevant portions of the
standard, and I even went through the hassle of showing you, in great
detail, __why__ what you are trying to do can't work well. In the
process of doing so, I offered you, effectively, a __proof__ that your
cast is UB (this type of proof is commonly called "proof by
contradiction", and I can rephrase my proof more formally if you
wish).
You should take note of this, I believe: by your own words: "I can
cast from int[] to int* __implicitly__ (emphasis mine) because its a
realated type". However, no implementation allowed you to assign
result of new TYPE[size1][size2] to TYPE(*)[size2]. There is __no__
implicit conversion there (and with a good reason, too, see above). So
you resorted to a cast. An UB one.
Goran.
I don't know what definition you are talking about, but either the
definition, or your interpretation thereof, is wrong.
Return type of expression "new TYPE[5]" is "TYPE*", not e.g. TYPE[5],
or, I dunno, TYPE(*)[5]. Array (as in TYPE[size]) is in no way
involved there. Arrays and pointers mix in some other contexts^^^.
It looks like the syntax (new TYPE[5]), that resembles an array
declaration, confuses you. You might want to think of it this way:
int* p = new int(1); // p is a pointer to int.
p = new int[2];
// p is __still__ a pointer to int
int i;
p = &i;
// p is __still__ a pointer to int
int a[3];
p = a; // ^^^ implicit array-to-pointer conversion
// p is __still__ a pointer to int
You seem to believe that there is something as pointer-to-array
conversion (or pointer-to-pointertoarray conversion). That belief is
wrong.
Goran.
I don't know what definition you are talking about, but either the
definition, or your interpretation thereof, is wrong.
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
The definition in the C++ standard says it points to the first element OF AN
ARRAY.
therefore by definition it points to an array you idiot.
<snip >
>
>"Goran" <goran...@gmail.com> wrote in message
>news:362fae78-1af4-4f00...@k22g2000yqh.googlegroups.com...
>On Mar 31, 3:22 am, "Paul" <pchris...@yahoo.co.uk> wrote:
>> >>>> Yes says the proven idiot who thinks p doesn't point to an array
>> >>>> with:
>> >>>> int* p = new int[5]
>>
>> >>> p is not a pointer to an array; p is a pointer to an int.
>> >> No p points to the initial element *of an array*, by definiton it
>> >> points
>> >> to an array.
>
>I don't know what definition you are talking about, but either the
>definition, or your interpretation thereof, is wrong.
>
>xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
>
>The definition in the C++ standard says it points to the first element
stop right there and you'll seem like less of a degenerate.
>OF AN ARRAY.
Pointing to the first element is not the same thing as pointing to the array.
The array is a different type than is the first element, no matter how many
times you beligerantly say otherwise.
>therefore by definition it points to an array you idiot.
lol, by your definition, which everybody who has responded to you has indicated
is meaningless.
your points are all meaningless paul. congratulations for all your time well
spent :)
First part, I agree. Second part (the "therefore" one), is false (and
is not in the standard, either).
Here, a practical example why __your__ "therefore" is wrong:
class A
{
public:
A() : i(0) {}
const int i;
};
class B : public A
{
public:
B() : j(1) {}
const int j;
};
int main(int, char*[])
{
const B b[2];
const A* a = b;
if (a->i == 0)
std::cout << "a points to the array b" << std::endl;
a++;
std::cout << "I did a++; now it points to the second element of the
array b;" << std::endl;
std::cout << "That's what pointers do, right?" << std::endl;
if (a->i == 1)
{
std::cout << "Hmmm... no object of type A has i that equals 1." <<
std::endl;
std::cout << "I must have invoked UB somewhere. I wonder where..."
<< std::endl;
std::cout << "Perhaps in the part where I said that a points to
the array b?" << std::endl;
std::cout << "Nooo... Un-possible!";
}
return 0;
}
Goran.
No, it is not. The type of this new expression is TYPE(*)[size2]
(assuming TYPE is not an array-type).
On 31 Mrz., 11:52, Paul wrote:
> [...]
> The definition in the C++ standard says it points to the first element
> OF AN ARRAY. therefore by definition it points to an array [...]
Wow. Apparently, the discussion is still about the banana vs bunch of
bananas thing. I still see no definition of the word "pointer" or the
expression "points to X" in the C++ ISO standard that would justify
your use of the words "therefore by definition" in this context.
Consider the possibility that you are (perhaps unintentionally)
augmenting the standard's text with your personal understanding of
what "points to X" means exactly.
Regardless of the interpretation of "points to X", an array is not a
pointer. Since you evaded revisiting this claim of yours in favour of
this stupid discussion about the semantics of "points to X", my
conclusion is you are too proud to admit that you were wrong about the
"an array is just a pointer" issue.
SG
By whose definition? Yours? Your own personal definitions of things
carry no weight here. The fact that p points to the initial element of
an array does not mean that p is a pointer to an array; p is a pointer
to an int.
> Were you born stupid or did you grow into it?
Occam's Razor my dear chap: which is more likely: everybody except Paul
is stupid or just Paul is stupid?
/Leigh
Whoops, indeed. Heat of the discussion ;-) ...
Goran.
First part, I agree. Second part (the "therefore" one), is false (and
is not in the standard, either).
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
It IS the defintioon in the standard, the standard states it points to the
first element OF AN ARRAY, therefore it cannot NOT point to an array.
The standard certainly doesn't state, that it doesn't point to an array, as
you are saying.
You do not accept the opinion of experts who say that a T* can point to a T,
or an array of T's.
<snip>
You are just going round in circles. Again: there is a difference
between the not so technical term "points to" and the technical term "a
pointer to".
A *pointer to an int* is *a pointer to an int* not *a pointer to an
array*; pretty simple IMO so I wonder why you don't "get" it.
/Leigh
> Regardless of the interpretation of "points to X", an array is not a
> pointer. Since you evaded revisiting this claim of yours in favour of
> this stupid discussion about the semantics of "points to X", my
> conclusion is you are too proud to admit that you were wrong about the
> "an array is just a pointer" issue.
>
This is absolute bollocks , I never said an array was the same as a pointer,
I say that in some situations it is, for all intensive purposes, the same.
Now you say you know more about my views than I do? Go to France you fin
idiot.
You obviously have an overwhelming desire to get your own back after the
many times i have proved you wrong. I have won this argument arleady and I
see no need to reply to your idiotic nonsense anymore.
Indeed; nobody said otherwise.
> This is a pointer to an array , not a pointer to a single int, pretty
> simple:
> int* p = new int[6];
p is a pointer to an int not a pointer to an array; you can bleat that
this is incorrect as much as you like but it will not change the fact
that it is a correct statement.
>
> You obviously have an overwhelming desire to get your own back after the
> many times i have proved you wrong. I have won this argument arleady and
> I see no need to reply to your idiotic nonsense anymore.
>
Get my own back? Why? You have not proven me or anybody else wrong so
far. If you ever do prove me wrong about something I will admit my
mistake; I certainly wouldn't want to "get my own back". Also: the ad
hominem is a logical fallacy.
/Leigh
First things first. You do understand now that casts you tried to pull
off are UB, right?
Goran.
OK, so, let's say that what you say is true... (proof by contradiction
follows...)
In my previous example... What does "a" in "const A* a = b" points to
then? Clearly, b is an array. So what does a points to? To an array of
A, an array of B, or what? Clearly, b is an array, code is legal, no
casting, no funny business...
Further, if a points to an array of A, why incrementing it gives
strange results? If it's an array of B, how can that even compile? (B
__is__ A, but A __is not__ B).
I know that you have no relevant answer to any of these questions, so
I'll give it to you: "a" points to __the first element of "b"__. It
points to no array, ever.
Goran.
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
What exactly is UB? Casting in general produces UB, or only when I cast?
Is it a case that you are not interested in discovering the true language
technicalities and that your sole intention is to prove that I am wrong
about something.
In your post here: http://groups.google.com/group/comp.lang.c++/msg/1948e01fd0971cac,
I claimed that first two casts were UB. You claimed that they were
not. I proved you that they were (read back, please).
Goran.
I quoted you correctly. You said "an array is just a pointer". You
used this as subject to one of the threads that spawned over 200 other
posts.
> I say that in some situations it is, for all intensive purposes, the same.
An array is never a pointer. What you tried to say should have been
worded like this: One can use an array expression in contexts where a
pointer is required due to the array-to-pointer standard conversion.
That's about it. You're just being overly broad and imprecise, as
ever. If you want to avoid looking dumb, you should put a little more
effort into precise wording.
Also, it strikes me as odd that a presumably native English speaker
who claims to be smarter than everybody who disagrees with him in here
says "intensive purposes" when "intents and purposes" is what he
meant.
> Go to France you fin idiot.
Oh, how could I forget the name calling. Yes, that's definitely
indicating cleverness.
SG
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
You haven't proved anything is UB, In C++ casting is not UB , its
conversion form one type to another. Initially you said casting the return
from new was UB but since I have stated the standards states the return from
new must be castable you have changed your tune to , "your cast is UB
because I say so". Your code with assets and comparisons does not prove that
a cast is UB it only proves you can write code that has bugs.
Are you saying that casting a pointer to an array is UB? , Who knows because
you are not being specific, you are simply stating my cast is UB because you
say so.
Is this UB in your mind then:
template <typename T, int S>
T* foo(){
return static_cast<T*>(::operator new(S * sizeof(T)));
}
int main() {
int (*p)[6] = foo<int[6], 6>();
}
.
You do not define what I say , I do.
*facepalm*
I kept wondering what was so intensive about the purposes...
Peter
lulz.
/Leigh
lol, priceless
I guess your repetitive misuse of that expression shows that you
literally "don't know what you're talking about", i.e. what the words
you fail to use actually mean.
I bet you're one of those who don't get there/their/they're right.
Your response only shows that you are unable to own up to your mistakes.
Peter
Admit to your mistakes you liar.
/Leigh
Intent sieve porpoises?
The very idea is full of holes.
--
Drew Lawson I had planned to be dead by now, but
the schedule slipped, they do that.
-- Casady
A friend just posted this link on another group:
http://www.politicsforum.org/images/flame_warriors/flame_77.php
I though it apt here as well.
--
Ian Collins
Yes I have. Read this again:
http://groups.google.com/group/comp.lang.c++/msg/e274c527afabc5f4
Now... (proof by contradiction follows... Do you know what "proof by
contradiction" means, BTW? I hope so. If not, I hope you can google
it.)
So... See the code? See the line:
Base (*p2)[3] = (Base (*)[3])new Derived[2][3];
?
You claimed that one should be able to do it, in this post:
http://groups.google.com/group/comp.lang.c++/msg/310cebb655d59715
So, presuming that your cast is not UB, I made you a bit of code that
uses your cast and doesn't work correctly. I'll repeat offending part,
slightly modified, since you seem to have an issue with assert macro
(a macro is not a statement, which is something you don't seem to
understand well):
Base (*p2)[3] = (Base (*)[3])new Derived[2][3]; // Presumption: no UB
in cast.
const Base& b = p2[0][1];
if (b.i) std::cout << "This is not possible!";
I'll also show you the correct code:
Derived(*p2)[3] = new Derived[2][3];
const Base& b = p2[0][1];
if (b.i) std::cout << "This is not possible!";
Contradiction is: the only difference between these two snippets is
the the cast^^^. If there's no UB in the cast, why doesn't first
snippet work? Answer: cast is UB; by consequence, anything that
follows is wrong.
^^^ Bar the use of Base type. But since e.g. "Base (*p2)[3] = new
Derived[2][3];" doesn't even compile, that's immaterial.
Goran.
Yes I have. Read this again:
http://groups.google.com/group/comp.lang.c++/msg/e274c527afabc5f4
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
This is your code that is wrong not the cast. You cannot even explain what
is wrong with the cast in your opinion , its just wrong?
I provided the following code as an alternative which you snipped and
ignored. And you replaced it with your buggy shit code.
The following is the same C cast but in C++ style, is this also UB in your
mind?
template <typename T, int S>
T* foo(){
return static_cast<T*>(::operator new(S * sizeof(T)));
}
int main() {
int (*p)[6] = foo<int[6], 6>();
}
<Snip>
http://groups.google.com/group/comp.lang.c++/msg/e274c527afabc5f4
?
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
This is because you think that the pointer-type Base (*)[3], points to an
array of Base[3], but it doesn't it points to an array of Derived[3].
Its your code that is wrong because you derefernce p2 as if it were a Base,
but it points to a Derived.
p2[i] returns i*sizeof(Base[3]), this is not the same as
i*sizeof(Derived[3]).
The memory layout of the object array is as follows:
[[Base][Derived]] [[Base][Derived]] [[Base][Dervied]]
You are trying to index this array in chunks sizeof(Base[3]).
This example to shows that the pointer-type does not define the object it
points to.
p2 points to an array of Derived, not an array of Bases.
Problem line is
Base (*p2)[3] = (Base (*)[3])new Derived[2][3];
and __you__ wrote it first.
I changed Base in a way that shows that your code won't work. But I
did not change the offending part.
It looks like you think that "not UB" means "seems to work on my
code"?
> You cannot even explain what
> is wrong with the cast in your opinion , its just wrong?
My explanation is fine compared to your lack of understanding what
"proof by contradiction" means.
> I provided the following code as an alternative which you snipped and
> ignored. And you replaced it with your buggy shit code.
Not true. Nothing in what __I__ wrote is wrong. Errors are in what
__you__ have written, that I took over. My purpose was clear: to show
you __how__ and __why__ what you wrote fails. You really seem to think
that "not UB" means "seems to work on my code".
> The following is the same C cast but in C++ style, is this also UB in your
> mind?
>
> template <typename T, int S>
> T* foo(){
> return static_cast<T*>(::operator new(S * sizeof(T)));}
>
> int main() {
> int (*p)[6] = foo<int[6], 6>();
>
> }
It does not matter whether cast is C or C++-style.
Yes, this is UB, and it's __much__ worse than your old examples. If
you try this on __any__ type that has a constructor, this is going to
fail __massively__. Just put e.g. this in your main:
std::string (*p)[6] = foo<string[6], 6>();
And watch this lunacy of yours fail.
You can legally use static_cast to go from void* to some other type,
that's OK, but that does not mean that code can't exhibit UB.
Goran.
Being polite when asking for help is somewhat better. You might want
to try e.g. this way:
"I don't understand compiler errors. I did ABC, compiler told me XYZ.
What should I do?"
Goran.
First off, p2 is not a Base, it's not even a pointer-to-a-Base, it's a
pointer to Base[3]. But that is irrelevant.
My code is perfectly fine. I can't possibly dereference p2 as if it
were Derived[3], because type of *p2 is Base[3], not Derived[3]. Why
did this happen? Because of __your__ cast, not because of anything in
__my__ code.
> The memory layout of the object array is as follows:
> [[Base][Derived]] [[Base][Derived]] [[Base][Dervied]]
>
> You are trying to index this array in chunks sizeof(Base[3]).
Oh. Well, I am glad that you managed to understand the explanation I
gave you earlier.
> This example to shows that the pointer-type does not define the object it
> points to.
> p2 points to an array of Derived, not an array of Bases.
... because __your__ cast was UB.
Goran.
Problem line is
Base (*p2)[3] = (Base (*)[3])new Derived[2][3];
and __you__ wrote it first.
I changed Base in a way that shows that your code won't work. But I
did not change the offending part.
It looks like you think that "not UB" means "seems to work on my
code"?
> You cannot even explain what
> is wrong with the cast in your opinion , its just wrong?
My explanation is fine compared to your lack of understanding what
"proof by contradiction" means.
> I provided the following code as an alternative which you snipped and
> ignored. And you replaced it with your buggy shit code.
Not true. Nothing in what __I__ wrote is wrong. Errors are in what
__you__ have written, that I took over. My purpose was clear: to show
you __how__ and __why__ what you wrote fails. You really seem to think
that "not UB" means "seems to work on my code".
> The following is the same C cast but in C++ style, is this also UB in your
> mind?
>
> template <typename T, int S>
> T* foo(){
> return static_cast<T*>(::operator new(S * sizeof(T)));}
>
> int main() {
> int (*p)[6] = foo<int[6], 6>();
>
> }
It does not matter whether cast is C or C++-style.
Yes, this is UB, and it's __much__ worse than your old examples. If
you try this on __any__ type that has a constructor, this is going to
fail __massively__. Just put e.g. this in your main:
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
It's your use of the code that produces undefined behaviour, this code is
identical to the code used in std::allocator.
Just because you can use this code in a way that produces UB does not mean
the code itself produces UB.
If you theory was correct every container in the std lib would produce UB
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
std::string (*p)[6] = foo<string[6], 6>();
And watch this lunacy of yours fail.
You can legally use static_cast to go from void* to some other type,
that's OK, but that does not mean that code can't exhibit UB.
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
As I said above you can make almost any code produce UB if you use it
incorrectly. It's not the code I posted that produces UB , its your
incorrect useage of the code.
If you think the code I posted produces UB then just compare that code to
the constructor in std::allocator. As the code is identical you must also
think std::allocator produces UB.
You call it lunacy but its your usage that is lunacy not the code from the
std lib.
... In some implementation you saw somewhere, you mean, right? Cause I
don't think standard prescribes exact code for
std::allocator::allocate.
> Just because you can use this code in a way that produces UB does not mean
> the code itself produces UB.
How do I know that your goal was to return uninitialized storage?
That's very unusual, clearly documented for allocator::allocate, and
in no way implied or visible by your code.
> If you theory was correct every container in the std lib would produce UB
I don't do theory. I do practice. I had no way of knowing that your
goal was to return uninitialized memory from "f". (In fact, I think
you didn't even realize what you did before reading my response). In
practice, you don't do that without clearly stating so. If you do, I
am glad you I don't work where you work. In practice, also, all
containers __construct__ objects in storage returned by
allocator::allocate (what, did you think otherwise!?).
> xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
>
> std::string (*p)[6] = foo<string[6], 6>();
>
> And watch this lunacy of yours fail.
>
> You can legally use static_cast to go from void* to some other type,
> that's OK, but that does not mean that code can't exhibit UB.
>
> xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
> As I said above you can make almost any code produce UB if you use it
> incorrectly. It's not the code I posted that produces UB , its your
> incorrect useage of the code.
My usage is just fine given the interface of "f". It returns T*. Why
__wouldn't__ I be able to use it with std::string? Answer: because
either code itself is bad, either it's intention is unclear or poorly
documented.
> If you think the code I posted produces UB then just compare that code to
> the constructor in std::allocator. As the code is identical you must also
> think std::allocator produces UB.
That conclusion is wrong and based on poor logic. No, I do not think
that allocator::allocate (one that does static_cast<T*>(::new(sizeof T
* n), which, I claim, is not __required__ by the standard) produces
UB, because I know that whatever it produces will be constructed
before reaching any other code, or else, implementation has a bug.
Your function, OTOH, spit out uninitialized storage as if it was
something people do as a matter of fact.
(By the way, there's no reason to mention any constructor. You are
clearly talking about allocator::allocate, and that does no
construction whatsoever).
Goran.
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
You said this code produced UB , so even if it's only one implementation you
still say this particular implementation of the std lib produces UB.
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
> Just because you can use this code in a way that produces UB does not mean
> the code itself produces UB.
How do I know that your goal was to return uninitialized storage?
That's very unusual, clearly documented for allocator::allocate, and
in no way implied or visible by your code.
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Your argument is that an int* points to a single int and not to an array, or
have you forgotten that?
I have said that an int* can point to a single int or an array of int. I am
trying to show you that pointers can point to anything.
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
> If you theory was correct every container in the std lib would produce UB
I don't do theory. I do practice. I had no way of knowing that your
goal was to return uninitialized memory from "f". (In fact, I think
you didn't even realize what you did before reading my response). In
practice, you don't do that without clearly stating so. If you do, I
am glad you I don't work where you work. In practice, also, all
containers __construct__ objects in storage returned by
allocator::allocate (what, did you think otherwise!?).
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
No? well funnily enough thats what new does, it returns memory. Strange how
you couldn't work that out.
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
> xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
>
> std::string (*p)[6] = foo<string[6], 6>();
>
> And watch this lunacy of yours fail.
>
> You can legally use static_cast to go from void* to some other type,
> that's OK, but that does not mean that code can't exhibit UB.
>
> xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
> As I said above you can make almost any code produce UB if you use it
> incorrectly. It's not the code I posted that produces UB , its your
> incorrect useage of the code.
My usage is just fine given the interface of "f". It returns T*. Why
__wouldn't__ I be able to use it with std::string? Answer: because
either code itself is bad, either it's intention is unclear or poorly
documented.
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Your usage is not fine , it produces UB.
The code presented doesn't produceUB without your code. Its behaviour is
perfectly defined until your code is added.
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
> If you think the code I posted produces UB then just compare that code to
> the constructor in std::allocator. As the code is identical you must also
> think std::allocator produces UB.
That conclusion is wrong and based on poor logic. No, I do not think
that allocator::allocate (one that does static_cast<T*>(::new(sizeof T
* n), which, I claim, is not __required__ by the standard) produces
UB, because I know that whatever it produces will be constructed
before reaching any other code, or else, implementation has a bug.
Your function, OTOH, spit out uninitialized storage as if it was
something people do as a matter of fact.
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
The code is perfectly legal and defined code, it can be used anywhere by any
procedure. Your incorrect usage produces UB not the code on its own.
If a piece of code allocates an array of Cats and you treat it like an array
of Dogs your code is wrong , not the code that creates the array of Cats.
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
(By the way, there's no reason to mention any constructor. You are
clearly talking about allocator::allocate, and that does no
construction whatsoever).
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Whether its a constructor or not is irrelevant to the discussion, this is
simply an avoidance tactic to change the subject. You say this code produces
UB when it is actually YOUR code that produces the UB.
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
No, your conclusion is wrong. The differences between your code and
the standard library one are:
* standard library won't ever pass said pointer to code that can use
it to produce UB
* standard library __in question__ knows that it's safe to go from
void* allocated from ::operator new to T*, because standard library is
tied to implementation. As far as I know, this passage is __not
guaranteed__ by the standard. The problem, obviously, are alignment
requirements of the platform (e.g. ::operator new returns pointers
aligned on 4-byte boundary, but e.g. double must be aligned on 8-byte
boundary, in which case the very cast inside f is UB).
> > Just because you can use this code in a way that produces UB does not mean
> > the code itself produces UB.
>
> How do I know that your goal was to return uninitialized storage?
> That's very unusual, clearly documented for allocator::allocate, and
> in no way implied or visible by your code.
> xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
> Your argument is that an int* points to a single int and not to an array, or
> have you forgotten that?
Irrelevant. Your question __here__ was if the code you offered was OK.
It wasn't (or at best, it was hardly OK).
> I have said that an int* can point to a single int or an array of int. I am
> trying to show you that pointers can point to anything.
Why, yes, they can, in hands of people like you, who cast nilly-willy
and claim that code is correct because they see it works, on code they
need, on implementation they need. Things are, however, slightly more
complicated and their very code might not work tomorrow on their very
implementation (like when they use "f" with std::string).
That said... In your code, "p" is int(*)[6]. Type-wise, f returns that
very same thing. You showed __nothing__ on the lines of your argument.
In addition, implementation of f is just bad, because it returns
uninitialized storage, and because it's implementation-dependent.
But fair enough. So your argument is that a pointer can point to __an
array__. If so, how do you explain what is happening here?
int a[2][2] = {1, 2, 3, 4};
int* p = a[0]; // By your argument, p points to an array, right?
assert(*p = 1); // OK;
p++;
assert(*p==2);
Now, hang on! p points to an array. I incremented p. Normally, when
you increment a pointer, it points to a next element. If p points to
an __array__ (a[0]), and I increment it, then it should point to a[1].
Yet, it doesn't. Why? Perhaps because p actually points to a __first
element__ of an array? (proof by contradiction, remember that?)
In other words... Saying that pointer points to an array leads to
surprising results when employing simple logic to pointers, array-to-
pointer conversion, pointer arithmetic and who knows what else. Saying
that is __choke full__ of contradictions (first of them obviously
being what pointer __type__ is).
People do say what you say ("p points to _that_ array"), and that's,
quite frankly, OK as far as ease of communication is concerned. What
is __implied__, however, is that pointer actually points to the first
element. Muddling waters like you're trying to do serves no-one.
Goran.
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Its up to you to use the code responsibly. According, to you every piece of
code that is breakable would produce UB.
It was clear what the piece of code posted did. You, either deliberately or
unknowingly, used this code inappropriately to produce an error.
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
> > Just because you can use this code in a way that produces UB does not
> > mean
> > the code itself produces UB.
>
> How do I know that your goal was to return uninitialized storage?
> That's very unusual, clearly documented for allocator::allocate, and
> in no way implied or visible by your code.
> xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
> Your argument is that an int* points to a single int and not to an array,
> or
> have you forgotten that?
Irrelevant. Your question __here__ was if the code you offered was OK.
It wasn't (or at best, it was hardly OK).
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Yes quite true , your argument is quite irrelevant.
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Its not me you argue agaisnt , its the C++ language. It doesn't matter how
much you try to explian how you think the type system works, if you had any
clue you'd understand that the asm PTR directive doesn't define what is
pointed to, and the C++ type doesn't define what is pointed to.
If you treat a pointer to an array, as if it doesn't point to an array then
you are going to make mistakes. And its your codes' bad use of pointers that
is erroneous here.
My original question was:
Suppose I have the following code:
int (*p)[5] = (int (*)[5])new int[5];
How do I delete the allocated memory?
Now you said this code produced UB , and I have asked you to ellaborate,
where exactly is the UB?
You have answered this by adding some of your own code that uses my code
irresponsibly but that is your code that causes the error , not my code.
The said pointer type points to a 1d array, but its type suggests it points
to a 2d array or the &address of a 1d array.
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
When you use the "new" operator to create an array, it gives you the
address of the first element in the array.
So if the array is "int[5]", the address of the first element will be
"int*".
If you want the address of the first element to be "int(*)[5]", then
you need to do:
int (*p)[5] = new int[1][5];
delete [] p;
Ah create a 1d array in 2d format. Nice simple solution, I like it.
The problem is rather that, according to you, it's somehow OK to
return uninitialized storage under the guise of T*. It's not (or at
least, it has to be clearly stated).
> It was clear what the piece of code posted did. You, either deliberately or
> unknowingly, used this code inappropriately to produce an error.
Yes, it was deliberate. Because if you try to actually __construct__
objects in the storage you allocated, things do not go so well, now do
they? And if you don't construct, well, so you managed to legally cast
a void* pointer to T*, which is rather underwhelming. Your cast is
legal, which does not make code good (or interesting, for that
matter).
> Its not me you argue agaisnt , its the C++ language. It doesn't matter how
> much you try to explian how you think the type system works, if you had any
> clue you'd understand that the asm PTR directive doesn't define what is
> pointed to,
Oh, come on! asm PTR directive might exist in some assembler toolkit,
but it bears no relevance to the language. Even asm itself is
implementation-dependent. It also bears no relevance to malloc/free,
or any operator new. Why are you mentioning that?
> and the C++ type doesn't define what is pointed to.
It does, and it's completely clear: T* points to an object of type T.
What are you on about!?
> If you treat a pointer to an array, as if it doesn't point to an array then
> you are going to make mistakes. And its your codes' bad use of pointers that
> is erroneous here.
Yes, but there's a purpose: it's to show you what your insistence on
saying that e.g. "p" in "p = new TYPE[s]" points to an array leads to.
It's just fraught with danger, and there's no practical purpose (or at
least, you failed to show one).
> My original question was:
> Suppose I have the following code:
>
> int (*p)[5] = (int (*)[5])new int[5];
>
> How do I delete the allocated memory?
And my original answer was: you allocated an array of ints, you should
call delete[] on the pointer to the first element of that array, which
was returned from "new. Easy as a pie. That is, your code should be:
int *p = new int[5];
delete [] p;
I have no idea why you want to use all these casts. You failed to
explain that. E.g. example you offered here:
http://groups.google.com/group/comp.lang.c++/msg/d0013eb81268f0ce
was pretty bad code, and you avoided to explain what you really
wanted. The other example, with Base and Derived, was also bad,
because it could only work when indexing a pointer to Base resulted in
a same value as when indexing a pointer to Derived> That is, I think,
implementation-dependent, and also rather constraining in practice.
Goran.
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
No, All you said was that is was UB.
I gave an example of doing the above weeks ago but as you are so
blinkered you missed it; this is further proof that you don't properly
read what people (or Standards) actually say.
/Leigh
You are the one full of bullshit:
On 17/03/2011 22:14, Leigh Johnston wrote:
[...]
Maybe the following will help you understand the semantic differences
involved:
int main()
{
int* p1 = new int[42]; // 'p1' is a pointer to the first
element of an array
int (*p2)[42] = new int[1][42]; // 'p2' is a pointer to an array
}
http://groups.google.com/group/comp.lang.c++/browse_thread/thread/8cb33b21e1a4b794/2646056e0efa270a
/Leigh
Why should I care if it is different thread of yours? You have a habit
of starting a new thread to hide the fact that you have lost an argument
in an existing thread.
Incorrect? p1 did point to an array.
> TY for confirming that you are indeed a bullshitter.
What am I bullshitting about exactly?
/Leigh
Of course I meant to say that p1 did *not* point to an array.
/Leigh
Not true.
This:
http://groups.google.com/group/comp.lang.c++/msg/b8ed179f99440d11
was my first response to your question.
Goran.
Not true.
This:
http://groups.google.com/group/comp.lang.c++/msg/b8ed179f99440d11
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Yes and after I answered this you said the cast was UB. And thats what this
particular subthread has been about.
As you are a troll I suspected that you would deliberately ignore my
correction: trying to make something out of a typo is a typical troll trait.
So just to be clear:
troll* p1 = new paul[1]; // p1 is a pointer to a troll
troll(*p2)[1] = new troll[1][1]; // p2 is a pointer to an array of troll
p1 above IS NOT A POINTER TO AN ARRAY; p1 above IS A POINTER TO A TROLL;
p2 IS A POINTER TO AN ARRAY.
Simple eh?
/Leigh
Oh I forgot to paste definitions "troll" and "paul":
struct troll
{
int sprinkling_of_vacuousness;
};
struct paul : troll // paul is-a troll
{
int sprinkling_of_cluelessness;
};
/Leigh
You can call me a troll and capitalise your bullshit as much as you like but
this doesn't change the fact that you're a proven idiot.
You have been proven incorrect already on this subject, ref thread: "You
snipped something".
My point was: it's not true that __all__ (emphasis added for better
reading comprehension) I said here was that your code had UB. I said
much more than that, and what you said was nonsense.
> And thats what this
> particular subthread has been about.
Not for me. For me, this thread was about you trying to pass
questionable-to-downright-unusable code as proof that a "pointer to T"
is somehow also a "pointer to array of T", and me trying to dissuade
you from that, with calm and rational thinking (as opposed to calling
people names, sending them insulting mails to their mailboxes and what
ever else that you did).
Goran.
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
A pointer type, pointer to T *is* also a pointer to a to an array of T. I
don't need to prove it, its a fact of the language.
1.
int i;
int* pi = &i;
What array are we talking about here? In other words, if pi __is__ a
pointer to an array of T, then why is the above possible and correct,
even? Because C type system is broken or because your claim is broken?
2.
int a[3];
int (*pa)[3] = &a;
if p __is__ a pointer to array, what is pa? I believe language
disagrees with your claim here.
3.
int a[3];
int* p = a;
Here, we __commonly say__ that p is a pointer to array. But p is
__not__ a pointer to array. Instead, e.g. in "int (pa)[3] = &a;",
__pa__ is a pointer to array.
Your claim leads to confusion and errors, and is possibly the reason
why you want to write code such as that you've shown us here
(downright wrong, like Base/Derived example, very unsafe like
template<> foo example, and also at odds with what's prescribed, like
your very first example).
Goran.
1.
int i;
int* pi = &i;
What array are we talking about here? In other words, if pi __is__ a
pointer to an array of T, then why is the above possible and correct,
even? Because C type system is broken or because your claim is broken?
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
The only thing broken is your brain. Obviously the above pointer doesn't
point to an array but the same type of pointer below points o an array:
int* p_to_array = new int[5];
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
2.
int a[3];
int (*pa)[3] = &a;
if p __is__ a pointer to array, what is pa? I believe language
disagrees with your claim here.
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
pa is also a pointer to an array, its just a different type of pointer.
pa is the same type of pointer generally used to point to a 2d array. If pa
is dereferneced it returns a 1dim array, thus obeying the C++ language rules
for arrays.
Your use of the &addressof operator is simply creating a pointer that needs
to be dereferenced twice to access the array.
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
3.
int a[3];
int* p = a;
Here, we __commonly say__ that p is a pointer to array. But p is
__not__ a pointer to array. Instead, e.g. in "int (pa)[3] = &a;",
__pa__ is a pointer to array.
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
No p is a pointer to an array of 3 ints, that's why we commonly say .it's a
pointer to an array.
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Your claim leads to confusion and errors, and is possibly the reason
why you want to write code such as that you've shown us here
(downright wrong, like Base/Derived example, very unsafe like
template<> foo example, and also at odds with what's prescribed, like
your very first example).
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
You certainly seem confused, I'm not.
A pointer to a 1d array is dereferenced once to return an element:
p_arr_1d[0];
A pointer to a 2d array is dereferneced twice to return an element:
p_arr_2d[0][0];
With your theory you think a pointer to a 1d array is like so :
int (*p)[5] = &a_1d_array;
All this does it make a pointer which has another level of indircetion and
would unneccessarily need to be dereferenced twice to access the array.
(*p)[0];
You, and many others, are obviously unable to garsp the simple facts of how
pointers to arrays work in C++ . For this reason and many other unreasonable
arguments I have seen in these forums , I am going to try and stop reading
this shit and eventually I will have fully plonked this well and trully
disgusting newsgroup that is full of arseholes know-it-alls who don't have a
clue, but they actually think they are expert programmers.
Clueless arseholes with no personailty, only bad personality, and too much
time to spend reading documents they dont understand.
Just look at your point 1 to see how much of an unreasonable idiotic
arsehole you are. What goes through your idiot brain?
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Seems to me a classic case of what happens when someone who's learnt high
level C++ or Java is now trying to learn the low level C part of the language.
I've seen it time and time again. A very good reason why anyone who interviews
for a C++ job interview should also be interviewed to test their C knowledge
too since if they don't understand pointers, arrays, pointer arithmetic and
the like there's a good chance they'll eventually mess something up badly.
B2003
No, it points to the first element of array allocated by new int[5].
But OK, I see what is your problem: you don't understand the
difference between __is__ and __points to__. That's what's confusing
you. No biggie, I can explain that to you. Consider:
class A {};
class B : public A {};
A a;
B b;
A* p=&a; // p __is__ a pointer to A and it points to an A.
p = &b; // p __is__ a pointer to A, but it points to a B.
The above is an example of a pointer that __is__ one thing (a pointer
to an A), but can __point to__ two different types. Types related, but
different nonetheless. See, there's a difference between __is__ and
__points to__? Relevant one at that, too.
Consider also:
TYPE* p; int i; int a[2]; int* p1=i; int* p2=a;
Now... Expression (*p) is of type T&. Expression (p->) is also of type
T&. That much is clear. Same for p1.
But what about p2? Following your claim and basic logic, it's int[2]&,
which is, of course, utter nonsense.
Goran.
No, it points to the first element of array allocated by new int[5].
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Bollocks you idiot , it points to both the first element *and* the array.
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
But OK, I see what is your problem: you don't understand the
difference between __is__ and __points to__. That's what's confusing
you. No biggie, I can explain that to you. Consider:
class A {};
class B : public A {};
A a;
B b;
A* p=&a; // p __is__ a pointer to A and it points to an A.
p = &b; // p __is__ a pointer to A, but it points to a B.
The above is an example of a pointer that __is__ one thing (a pointer
to an A), but can __point to__ two different types. Types related, but
different nonetheless. See, there's a difference between __is__ and
__points to__? Relevant one at that, too.
Consider also:
TYPE* p;
int i;
int a[2];
int* p1=i;
int* p2=a;
Now... Expression (*p) is of type T&. Expression (p->) is also of type
T&. That much is clear. Same for p1.
But what about p2? Following your claim and basic logic, it's int[2]&,
which is, of course, utter nonsense.
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
What a load of bollocks.
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Only a pointer to an array can point to an array; p_to_array is
erroneously named as it points to an int not an array.
/Leigh
void* p_to_leighs_head = (void*)zero_sized_array_of_leighs_brain_cells;
What is "p" exactly? I see no variable named "p" here.
>
> void* p_to_leighs_head = (void*)zero_sized_array_of_leighs_brain_cells;
Again you show you n00bness: conversion to void* is implicit so your
(void*) C-style cast is superfluous. Also you should prefer C++-style
casts to C-style casts (not doing so is another sign of n00bness).
HTH.
/Leigh
Consider this:
int aa[2][2]; int* p=aa[0];
So you say that p points to the array. That's aa[0]. If p points to
aa[0], then ++p must point to aa[1]. That's what incrementing a
pointer does.
Obviously, this is not true. ++p points to a[0][1].
In other words, your claim, that p points to an array, is false.
Because if it were true, simple things like pointer arithmetic
wouldn't work.
Goran.
>Goran.
You are correct of course, but I made this exact point in more than one of
Paul's threads. It is also true that using logic on Paul doesn't work either
because he is not here to learn, nor does he listen to any post that uses simple
logic to make valid points. Surely his next reply will be to either call you an
idiot or go on about something else while ignoring the proof regarding pointer
arithmetic.
And he still won't have worked out how to configure is new client.
It really is time to stop trying to reason with this bloke.
--
Ian Collins
Unfortunately, it's not just a matter of "logic". If it was a matter
of proving something wrong with a deductive argument, then this would
not persist so long. The entire discussion is over terminology. Given
sufficient time, and some prodding, Paul could probably conclude the
same as the rest of us as to which programs are UB and which have
defined results, and what are those results (assuming he's not a
troll). Paul just adamantly chooses to use our terminology. He makes
arguments with his own unique set of words and definitions, and he
argues that his definitions are the "right" ones, which makes useful
discussion near impossible. As a separate point, one could prove that
he's wrong on a separate but related point about which set of words
are in common usage, but it appears that he's so steeped in his
certainty that he is correct that he will not listen (or he's a
troll).
I merely mean to emphasize that the problem is over which definitions
of words should we use, which usually makes for the most useless
discussions.
Ack. Should read: "Paul just adamantly *refuses* to use our
terminology."
Consider this:
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Yes p points to an array. Just because pointer arithmetic confuses you,
doesn't mean p doesn't point to an array.
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
In other words, your claim, that p points to an array, is false.
Because if it were true, simple things like pointer arithmetic
wouldn't work.
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
I didn't claim p pointed to anything because I haven't replied to it until
now. :-S
Can you be an any bigger arsehole that you are now?
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
OK, say that I am confused. You say that P points to X. I say, fine,
when I increment it, it must point to next X (this is a __very__
simple truth of the language). And yet, incremented, P __does not__
point to X.
So either P does not point to X, either incrementing it does not work.
Which is true? Show the flaw in, my logic, or in yours. Or show logic
that reconciles the two.
Claims like "Just because pointer arithmetic confuses you, doesn't
mean p doesn't point to an array" is neither logic nor explanation.
It's an assertion that means nothing if not based in something
tangible. It's like a kid saying in a school playground: "Martians
exist, my dad saw them".
Goran.
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Why would you be incrementing something if you didn't know what it pointed
to?
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
I do know what it points to. Saying that I am confused is a (obviously
false) premise. Kindly explain what is wrong in my logic.
Goran.
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
You don't know what this points to:
int* p = new int[6];
With the above p points to an array , you think it only points to a single
int. You do not have any consideration for what is pointed to , you
incorrectly think the pointer type defines what is pointed to.
> "Goran" <goran...@gmail.com> wrote in message
> news:e8b5f588-4dbb-4fc2...@27g2000yqv.googlegroups.com...
>> > Consider this:
>>
>> > int aa[2][2]; int* p=aa[0];
>>
...
> With the above p points to an array , you think it only points to a
> single int. You do not have any consideration for what is pointed to ,
> you incorrectly think the pointer type defines what is pointed to.
Is it correct that in your opinion, in the above example,
the pointer p points to all of
1) aa[0][0] ,
2) aa[0] and
3) aa
?
/L
--
Lasse Reichstein Holst Nielsen
DHTML Death Colors: <URL:http://www.infimum.dk/HTML/rasterTriangleDOM.html>
'Faith without judgement merely degrades the spirit divine.'
That's not the explanation, that's an assertion, and it's false.
__You__ incorrectly think that, when pointer points to the first
element of the array, it somehow points to the array as a whole. But
if you say that, pointer operations do not work as defined (as shown
by my dereferencing and incrementing examples). and yet they do. Hence
your claim is false.
Let's try the same explanation, this time from array standpoint...
typedef int (a6)[6];
a6 a[2] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 };
a6& ar0 = a[0];
a6& ar1 = a[1];
//a6* pa_wrong = a[0];
a6* pa = &a[0];
if (*pa != ar0) // XX
std::cout << "pointer dereferencing doesn't work";
if (*(++pa) != ar1) // YY
std::cout << "pointer incrementing doesn't work";
Here, pa __is__ a pointer to an array, and it __does__ point to an
array, array I typedef-ed as a6. When I dereference it, I get a
reference to a[0], as aptly shown by XX. When I increment it, I get a
reference to a[1], as aptly shown by YY.
If what you are saying was true, pa_wrong would compile, *pa would
give a reference to a (not a[0]), and ++pa would be UB (and it isn't,
it's legal, and it produces a reference to a[1]).
So... When you do have an array, you can easily have a pointer to that
array (pa). Your claim that a pointer to the first element of the same
array is __also__ a pointer to the array. Given that you can have
actual pointer to the array, your claim is both harmful (leads to
programming errors) and impractical.
Goran.
That's not the explanation, that's an assertion, and it's false.
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
You have made your opinion, that a pointer-type always defines what is
pointed to, very clear.
I haven't asserted anything , you have provided this evidence. If it's false
then it's your opinion that's false, not mine
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
<snip>
Yes you have. All you have are assertions. Not even opinions, plain
assertions. The "Martians exist, my dad saw them!" kind.
Explain how it is possible that both pointer points to an array, and
incrementing it makes it point to the next ___element in the array__.
Goran.
I think it points to the int lvalue aa[0][0].
What do you think it points to?
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Explain how what is possible?
I'm sorry but what you say is unclear.
He is quite clear. Explain how incrementing a pointer to an array will
make the pointer point to the next element in the array? It can't as it
is not a pointer to an array but a pointer to an array element; if it
was a pointer to an array incrementing it would make it point to the
next array not the next array element.
/Leigh
>>> its not my code.
That's totally irrelevant. The question's purpose was to clarify your
position. Even though you constantly promulgate your ultimate truths and
fulminate at everyone who disputes them, you can't stand by your
position when directly asked? You make me sick.
>>> You tell me what do you think it points to, in your words..
You are unable to answer a simple question.
You evade by deflecting the question.
>> I think it points to the int lvalue aa[0][0].
>> What do you think it points to?
>>
> I think it poiints to a section of memory.
You are unable to answer a simple question.
You evade by using dummy answers.
Peter
My position cannot be any clearer, you make me sick.
>
>>>> You tell me what do you think it points to, in your words..
>
> You are unable to answer a simple question.
> You evade by deflecting the question.
And what question can't I answer?
>
>>> I think it points to the int lvalue aa[0][0].
>>> What do you think it points to?
>>>
>> I think it poiints to a section of memory.
>
> You are unable to answer a simple question.
> You evade by using dummy answers.
>
No I answered it correctly. You obviously have a problem with all things
that are correct.
There is not much we can do if you cannot (or will not) understand the
basics.
/Leigh
>>>>> its not my code.
>> That's totally irrelevant. The question's purpose was to clarify your
>> position. Even though you constantly promulgate your ultimate truths and
>> fulminate at everyone who disputes them, you can't stand by your position
>> when directly asked? You make me sick.
>
> My position cannot be any clearer, you make me sick.
Then why can't you answer a simple question? It was even a yes-or-no
question. Even *you* should be able to type two-letter and three-letter
words.
>>>>> You tell me what do you think it points to, in your words..
>>
>> You are unable to answer a simple question.
>> You evade by deflecting the question.
> And what question can't I answer?
You are unable to answer a simple question.
You evade by pretending you are unaware of any question.
You are playing dumb just to be annoying, aren't you?
>>>> I think it points to the int lvalue aa[0][0].
>>>> What do you think it points to?
>>>>
>>> I think it poiints to a section of memory.
>>
>> You are unable to answer a simple question.
>> You evade by using dummy answers.
>>
> No I answered it correctly. You obviously have a problem with all things
> that are correct.
You deny that it is a dummy answer?
Peter
>>>>> I think it points to the int lvalue aa[0][0].
>>>>> What do you think it points to?
>>>>>
>>>> I think it poiints to a section of memory.
>>>
>>> You are unable to answer a simple question.
>>> You evade by using dummy answers.
>>>
>> No I answered it correctly. You obviously have a problem with all things
>> that are correct.
>
> You deny that it is a dummy answer?
>
The only dummy here is you, the answer I gave is 100% correct.
However I do understand how to increment a pointer to an array, which
obviously you find challenging.
>>>>>>> its not my code.
>>>> That's totally irrelevant. The question's purpose was to clarify your
>>>> position. Even though you constantly promulgate your ultimate truths
>>>> and
>>>> fulminate at everyone who disputes them, you can't stand by your
>>>> position
>>>> when directly asked? You make me sick.
>>>
>>> My position cannot be any clearer, you make me sick.
>> Then why can't you answer a simple question? It was even a yes-or-no
>> question. Even *you* should be able to type two-letter and three-letter
>> words.
> I did answer the question, please stop being wrong.
By using a dummy answer. That's... childish. Try to be less childish.
>>>>>>> You tell me what do you think it points to, in your words..
>>>>
>>>> You are unable to answer a simple question.
>>>> You evade by deflecting the question.
>>> And what question can't I answer?
>> You are unable to answer a simple question.
>> You evade by pretending you are unaware of any question.
>>
>> You are playing dumb just to be annoying, aren't you?
>>
> No you are the one who fits the adjective "dumb" here, not I.
Hm yeah. Deflecting adjectives. That's... childish. Try to be less childish.
>>>>>> I think it points to the int lvalue aa[0][0].
>>>>>> What do you think it points to?
>>>>>>
>>>>> I think it poiints to a section of memory.
>>>>
>>>> You are unable to answer a simple question.
>>>> You evade by using dummy answers.
>>>>
>>> No I answered it correctly. You obviously have a problem with all things
>>> that are correct.
>>
>> You deny that it is a dummy answer?
>>
> The only dummy here is you, the answer I gave is 100% correct.
Hm yeah. Deflecting nouns. That's... childish. Try to be less childish.
It was a decoy answer. Correct but too trivial to be a serious answer.
Only trying to distract from your inability to really answer this simple
question. Try to be less childish.
Peter
No, it's clear enough, and you are lying when saying it's not. If you
say that pointer of type "T*" (somehow, sometime, whatever) points to
an __array__ of T, then simplest of pointer operations (indexing,
incrementing) are broken.
Since pointer operations clearly aren't broken, your claim is false.
Goran.
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
What is broken about indexing and incrementing?
I don't know what you are talking about, it works fine on my system, please
explain.
int a[2][2]={1,2,3,4};
int* p1 = a[0]; // p1 points to an array (your claim).
p1++;
if (*p1 != a[1])
std::cout << "incrementing is broken.";
int* p2 = a[0]; // p2 points to an array (your claim).
if (*p2[1] != a[1])
std::cout << "indexing is broken.";
Goran.
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
You create a 2d array, then you create a pointer to a 1d-subarray of this 2d
array.
Then after that I don't know what you are trying to do. You say its broken
but you don't say what you expect it to do.
It looks like you increment the pointer to the 1d-subarray and expect it to
increment the 2d array , or something stupid like that. But surely you can't
be that stupid?
What exactly is your code trying to do?
> You create a 2d array, then you create a pointer to a 1d-subarray of this 2d
> array.
(Specifically, the first 1d-subarray.)
> Then after that I don't know what you are trying to do.
He's trying to increment the pointer to the FIRST 1d-subarray, in the
expectation that doing so will cause it to point to the SECOND 1d-
subarray. Do *you* think this should work?
I expect both pointers to point to a[1]. This is because you say that
they point to one array (a[0]), and I know that incrementing, or
indexing pointers with 1, must make them point to next element. Thats
a[1]. This is how pointers work. Explain why this doesn't happen.
Goran.
Goran,
I am seeing some oddities with your example. I agree with what I believe your
point is, but I think the "if" expressions may perhaps not be what you're trying
to express.
consider:
if (*p1 != a[1])
You are attempting to compare a dereferenced pointer (an int value) with an
array type. This should not even compile imo.
Now if you meant to say:
if (*p1 != a[0][1])
similarly:
if (p1 != &(a[0][1]))
then i think the test is valid.
As a side note:
The 2-dimensional array example isn't even necessary.
A 1-dimensional array is more than sufficient to make the case for how many
bytes are incremented by incrementing the pointer.
int a[4] = {1,2,3,4}; // a is an array
int* p1 = a; // a is still an array and Paul thinks p1 points to an array
int* p2 = p1; // p1's value is stored in p2
++p1; // p1 is incremented
std::cout << sizeof(int[4]) << std::endl; // size of our array in bytes
std::cout << sizeof(p1-p2) << std::endl; // bytes between p1 and p2
output:
16
4
on my machine, a is a 16-byte array
we store the address of p1 in p2
we then increment p1 by 1
the bytes jumped on my machine is 4
the sizeof(int) on my machine is 4
if p1 pointed to an array instead of an int, then the difference between p1 and
p2 would be 16, not 4.
p1 irrefutably points to an int element, not the array.
(this is the part where Paul is backed into a wall logicall and starts calling
everybody an idiot)
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Incrementing it will make it point to a[0][1] becuase you increment a
pointer to a 1d array. If you want to make it point to a[1][0] then you must
use a pointer to a 2d array like so:
int (*p)[2] = a;
p++;
/*now p points to a[1][0]*/
I don't see what you find so difficult about this.
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
wrong, the pointer is a pointer to int, not 1d array.
incrementing an int pointer makes it point to a[0][1]
> If you want to make it point to a[1][0] then you must
>use a pointer to a 2d array like so:
>int (*p)[2] = a;
wrong again, p is now a pointer to an array of int object with 2 elements.
this pointer type is a 1-dimensional array type, not 2.
incrementing the 1d array pointer makes it point to a[1][0]
std::cout << "p type is : " << typeid(p).name() << std::endl;
output: p type is : int (*)[2]
you're so confused it is comical.
Not only that, the fool still hasn't worked out how to configure his
news client!
--
Ian Collins
OK. So, I'll presume then this claim is true, that int* is a pointer
to 1d array. If so (continuing from previous example)...
p1 = &a[0][1]; // 1
int i;
p1 = &i; // 2
If p is a pointer to a 1d array, how come I can assign address of a
single int to it? a[0][1] and i are clearly not arrays.
Also, if your claim is true, then in:
int aa[2];
int(*pa)[2] = &aa; // 3
pa is a pointer to a 2d array. But aa is clearly __not__ a 2d array.
Since all of 1, 2, 3 is both correct and legal code, your claim, that
T* is a pointer to 1d array of T, is false.
Goran.
When he says "p is a pointer to a 1d array" he means "p currently
stores an address of an array or the address of something that is part
of that array". So, when he says "p is ..." he's mainly considering
runtime properties and the raw type-agnostic address some object
pointer stores. Unlike others, he ignores the type of a pointer
variable when it comes to describing what a certain pointer "is".
That's why he brought up the broken finger/bunch/banana analogy.
Guys, don't you realize that this is going around in circles? Don't
you have anything better to do?
SG
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Its not a claim its a fact.
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
p1 = &a[0][1]; // 1
int i;
p1 = &i; // 2
If p is a pointer to a 1d array, how come I can assign address of a
single int to it? a[0][1] and i are clearly not arrays.
Also, if your claim is true, then in:
int aa[2];
int(*pa)[2] = &aa; // 3
pa is a pointer to a 2d array. But aa is clearly __not__ a 2d array.
Since all of 1, 2, 3 is both correct and legal code, your claim, that
T* is a pointer to 1d array of T, is false.
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Whether your code is legal or valid , I don't care but it certainly doesn't
look right to me.
Believe what you want on this subject I have explained enough and if you
still do not understand then IDC.
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
>So, when he says "p is ..." he's mainly considering
> runtime properties and the raw type-agnostic address some object
> pointer stores.
A pointer stores an address of an entity. A pointer needs to be treated as
if it points-to the entity which it was created and initialised to point to.
> Unlike others, he ignores the type of a pointer
> variable when it comes to describing what a certain pointer "is".
> That's why he brought up the broken finger/bunch/banana analogy.
No I acknowledge what type of pointers I use.
>
> Guys, don't you realize that this is going around in circles? Don't
> you have anything better to do?
>
Like you obviously do?
Ok, so it's a fact that it's a pointer to an array. And one can assign
address of a single int to it, too (that's a fact, too). So pointer is
now not a pointer to an array. Therefore, your fact is in conflict
with itself. Therefore, your fact is nonsense.
Goran.
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
This would be correct.
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Therefore, your fact is in conflict
with itself. Therefore, your fact is nonsense.
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
No your conclusion is nonsense, the same pointer can point to a single int
or and array of int. If you assign to it the address of an array, then it
points to an array. If you assign to it the address of a single int, then it
points to a single int.
A pointer can point to almost anything, it is the programmers job to know,
understand or test for what it points to. In many cases you cannot assume a
pointer is not null, so you must test for this. If a pointer is expected to
point to a single int you cannot treat it as if it points to an array. If a
pointer is supposed to point to an array of int then it should be treated as
a pointer to array, not pointer to single int.
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
If you assign to it the address of an array, then we __commonly say__
that it points to an array. If you assign to it the address of a
single int, then it points to a single int.
FTFY.
You want to conflate "points to" and "is". We commonly do that out of
expedience, but giving any more meaning to that leads to bugs,
horrible and/or easily misunderstood code, which is what you yourself
have done on several occasions in the beginning of this thread.
Therefore such conflating is unwarranted.
Goran.
>If you assign to it the address of an array, then we __commonly say__
>that it points to an array. If you assign to it the address of a
>single int, then it points to a single int.
No we don't normally take the address of an array , using the address&of
operator. Doing this creates an extra level of indirection show by
comparison to pointer to int:
int x;
int arr[4];
/*create pointers*/
int* p_x = &x; /*pointer to integer*/
int* p_arr = arr; /*pointer to array*/
/*create another level of indirection*/
int** pp_x = &p_x;
int (*pp_arr)[5] = &arr;
int** pp_p_arr = &p_arr;
The above two array pointers are at the same level of indirection. The
difference is what happens when you..
a) dereference them
b) increment them
They both point to exactly the same memory loaction(where the array has been
allocated). The pointer-type allows the compiler to know how many bytes of
memory will be addressed when the pointer is derefernced
>FTFY.
>You want to conflate "points to" and "is". We commonly do that out of
>expedience, but giving any more meaning to that leads to bugs,
>horrible and/or easily misunderstood code, which is what you yourself
>have done on several occasions in the beginning of this thread.
>Therefore such conflating is unwarranted.
I don't know what you are trying to say here. What "points to" generally
means is what has been allocated at the pointed to memory.
actually what "points to" means is:
For a type T, T* is the type "pointer to T." That is, a variable of type T* can
hold the address of an object of type T.
The allocation is not relevant, but do not take my word for it, the Standard is
very well-defined for this case.
ISO/IEC 14882:2003(E) 5.3.4 New, paragraph 5
"When the allocated object is an array (that is, the direct-new-declarator
syntax is used or the new-type-id or type-id denotes an array type), the
new-expression yields a pointer to the initial element (if any) of the array.
[Note: both new int and new int[10] have type int* and the type of new
int[i][10] is int (*)[10]. ]
type allocated: int[10]
type pointed to: int*
Best Regards & hth.,
Charles
typo: this should read: type of object: int*
This implies that what pointer is, i.e. it's type, changes. Given that
C and C++ are statically typed languages, that can't be correct.
Consequently, claim that pointer changes it's type is incorrect.
What is correct, though, is that, out of expedience, we __commonly
say__ that pointer __is__ a point to an array.
Goran.
No, conclusion is fine. Nonsense are your attempts to equal "is" and
"points to". And, they lead to poor coding and errors (see your own
attempts earlier in this thread to explain your stance).
Goran.
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Do you accept that the same pointer-type can point to an char or an array of
char's?
Or do you somehow feel that you are equally as special as cg_chas and its
quite ok for you to dismiss Stroustrup and others experts as bullshitters
who dont know what they're talking about?
I accept that when pointer points to the first element of an array, we
commonly say that it points to an array.
But in
int a[1];
int (*p)[1] = &a;
p is an actual, in C type system sense, pointer to an array. And
because of such things, one should take mental note when saying
"pointer to an array" for a pointer pointing to array's first element.
Goran.
But in
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Do you accpet that when Bjarne Stroustrup says a char* can point to a single
char or an array of chars. He is in fact techincally correct. And he fully
understand the C++ type system.
Do you not think its more likely that you are incorrect, if you disagree
with him?
Also do you accept what is detailed int he C++ standards where it clarifies
that a pointer to an array, when dereferenced , returns an (n-1) dim array?
Stop appealing to authority. Bjarne is being informal but obviously he
is correct as what he is saying does not disagree with what others have
been telling you; basically "type" in the following two phrases can
refer to a *different* type:
1) "pointer to a type"
2) "the type of the object pointed to".
Your problem is your inability to differentiate the two phrases above.
"pointer to" is different to "pointed to" or "points to" as "pointer to"
partially describes the type of the pointer variable not what is being
pointed to.
/Leigh
Now if Bjarne says one thing and you say it is incorrect, then who is more
likely to be wrong?
Additionally if the C++ standards defines something and you say its
incorrect, then who is more likely to be wrong?
You obviously did not read my reply: "pointer to" is different to
"points to". Take the time to properly read the replies people make or
fuck off and stop posting to this newsgroup you time waster.
> You say that a char* does not point to an array and only points to a
> single char. You further your wrongness by saying that a type:
> char (*)[3]
> is a pointer to a 1d array, when this is actually a pointer to a 2d
> array , because pointers to arrays are (n-1) dimensions of the pointed
> to array.
You are wrong again:
char a[3]; // 1d array
char(*p)[3] = &a; // pointer to a 1d array
>
> Now if Bjarne says one thing and you say it is incorrect, then who is
> more likely to be wrong?
Your appeal to authority is wrong on two counts:
1) An appeal to authority is a logical fallacy;
2) The authority you are appealing to actually does not agree with your
claim/argument (as I have described above).
> Additionally if the C++ standards defines something and you say its
> incorrect, then who is more likely to be wrong?
Where have I have said that the C++ Standard is incorrect? I haven't
said any such thing so you are either lying or are confused.
People may as well be talking to a brick wall when talking to you.
/Leigh
>> You say that a char* does not point to an array and only points to a
>> single char. You further your wrongness by saying that a type:
>> char (*)[3]
>> is a pointer to a 1d array, when this is actually a pointer to a 2d
>> array , because pointers to arrays are (n-1) dimensions of the pointed
>> to array.
>
> You are wrong again:
>
> char a[3]; // 1d array
> char(*p)[3] = &a; // pointer to a 1d array
No you are wrong because this doesn't mean that this type of pointer cannot
be used as a pointer to a 2d array like so:
char a[3][3];
char (*p)[3] =a;
You take the address of a thus introducing an unneccessary extra level of
indirection.
>
>>
>> Now if Bjarne says one thing and you say it is incorrect, then who is
>> more likely to be wrong?
>
> Your appeal to authority is wrong on two counts:
>
> 1) An appeal to authority is a logical fallacy;
> 2) The authority you are appealing to actually does not agree with your
> claim/argument (as I have described above).
The authority states that char* can point to a single char or an array of
chars. Which is in direct agreement with me and disagrees with you.
>
>> Additionally if the C++ standards defines something and you say its
>> incorrect, then who is more likely to be wrong?
>
> Where have I have said that the C++ Standard is incorrect? I haven't said
> any such thing so you are either lying or are confused.
You said that char (*p)[3] points to a 1d array and not to a 2d array, but
the standard states different.
No they are not "more or less the same thing"; "more or less the same
thing" is woolly language and has no place in a technical discussion;
also see below.
>
>>> You say that a char* does not point to an array and only points to a
>>> single char. You further your wrongness by saying that a type:
>>> char (*)[3]
>>> is a pointer to a 1d array, when this is actually a pointer to a 2d
>>> array , because pointers to arrays are (n-1) dimensions of the pointed
>>> to array.
>>
>> You are wrong again:
>>
>> char a[3]; // 1d array
>> char(*p)[3] = &a; // pointer to a 1d array
>
> No you are wrong because this doesn't mean that this type of pointer
> cannot be used as a pointer to a 2d array like so:
> char a[3][3];
> char (*p)[3] =a;
No p is still a pointer to a 1d array; your code is invoking array
pointer decay as it is equivalent to:
char a[3][3];
char (*p)[3] =&a[0];
Your understanding of arrays and pointers is flawed.
>
> You take the address of a thus introducing an unneccessary extra level
> of indirection.
Of course; a pointer to an array is an extra level of indirection; a
pointer to an array element isn't.
>
>
>>
>>>
>>> Now if Bjarne says one thing and you say it is incorrect, then who is
>>> more likely to be wrong?
>>
>> Your appeal to authority is wrong on two counts:
>>
>> 1) An appeal to authority is a logical fallacy;
>> 2) The authority you are appealing to actually does not agree with
>> your claim/argument (as I have described above).
> The authority states that char* can point to a single char or an array
> of chars. Which is in direct agreement with me and disagrees with you.
Again: there is a difference between "a pointer to" and "points to".
Consider:
struct base {};
struct derived : base {};
derived o;
base* p = &o;
p is a pointer to a base even though it points to an object of derived type.
>
>
>>
>>> Additionally if the C++ standards defines something and you say its
>>> incorrect, then who is more likely to be wrong?
>>
>> Where have I have said that the C++ Standard is incorrect? I haven't
>> said any such thing so you are either lying or are confused.
> You said that char (*p)[3] points to a 1d array and not to a 2d array,
> but the standard states different.
>
p is a pointer to a 1d array and the standard does not state different;
p may point to a 1d array subobject of a 2d array and if it is pointing
to the first 1d array subobject of the 2d array then one can say it
points to a 2d array but this is informal language and technically
inaccurate. As others have said "points into" is a more acceptable term
that covers all bases.
/Leigh
Your understanding is flawed, the C++ standard defines a pointer to a 2d
array to be of this type/ level of indirection.
>
>>
>> You take the address of a thus introducing an unneccessary extra level
>> of indirection.
>
> Of course; a pointer to an array is an extra level of indirection; a
> pointer to an array element isn't.
>
No. According to the C++ standards, a pointer to an array is a different
level of indirection, but in the opposite direction from what you are
saying.
>>
>>
>>>
>>>>
>>>> Now if Bjarne says one thing and you say it is incorrect, then who is
>>>> more likely to be wrong?
>>>
>>> Your appeal to authority is wrong on two counts:
>>>
>>> 1) An appeal to authority is a logical fallacy;
>>> 2) The authority you are appealing to actually does not agree with
>>> your claim/argument (as I have described above).
>> The authority states that char* can point to a single char or an array
>> of chars. Which is in direct agreement with me and disagrees with you.
>
> Again: there is a difference between "a pointer to" and "points to".
> Consider:
>
> struct base {};
> struct derived : base {};
>
> derived o;
> base* p = &o;
>
> p is a pointer to a base even though it points to an object of derived
> type.
>
Its a pointer to what it points to , its the same thing.
You are confused by the pointer-type and what it points to.
>>
>>
>>>
>>>> Additionally if the C++ standards defines something and you say its
>>>> incorrect, then who is more likely to be wrong?
>>>
>>> Where have I have said that the C++ Standard is incorrect? I haven't
>>> said any such thing so you are either lying or are confused.
>
>> You said that char (*p)[3] points to a 1d array and not to a 2d array,
>> but the standard states different.
>>
>
> p is a pointer to a 1d array and the standard does not state different; p
> may point to a 1d array subobject of a 2d array and if it is pointing to
> the first 1d array subobject of the 2d array then one can say it points to
> a 2d array but this is informal language and technically inaccurate. As
> others have said "points into" is a more acceptable term that covers all
> bases.
>
This is utter nonsesne the C++ standard states clearly what a pointer to an
array is and how it behaves.
A pointer to a 2d array, when derefernced returns a 1d array subobject. And
that is a FACT defined in the C++ Standard.
It doesn't matter how much you try to worm your way around this fact, it is
clearly defined in the standards and until you accept this fact you will
always be wrong.
Your understanding is flawed:
char(*)[N] is a pointer to a 1d array
char(*)[N1][N2] is a pointer to a 2d array
>
>>
>>>
>>> You take the address of a thus introducing an unneccessary extra level
>>> of indirection.
>>
>> Of course; a pointer to an array is an extra level of indirection; a
>> pointer to an array element isn't.
>>
> No. According to the C++ standards, a pointer to an array is a different
> level of indirection, but in the opposite direction from what you are
> saying.
That was just gibberish.
>
>>>
>>>
>>>>
>>>>>
>>>>> Now if Bjarne says one thing and you say it is incorrect, then who is
>>>>> more likely to be wrong?
>>>>
>>>> Your appeal to authority is wrong on two counts:
>>>>
>>>> 1) An appeal to authority is a logical fallacy;
>>>> 2) The authority you are appealing to actually does not agree with
>>>> your claim/argument (as I have described above).
>>> The authority states that char* can point to a single char or an array
>>> of chars. Which is in direct agreement with me and disagrees with you.
>>
>> Again: there is a difference between "a pointer to" and "points to".
>> Consider:
>>
>> struct base {};
>> struct derived : base {};
>>
>> derived o;
>> base* p = &o;
>>
>> p is a pointer to a base even though it points to an object of derived
>> type.
>>
> Its a pointer to what it points to , its the same thing.
No it isn't. A pointer has a type; a pointer's type does not have to be
the same type as the object it points to.
>
> You are confused by the pointer-type and what it points to.
It is obvious to all that it is you who has been confused; is currently
confused and probably will continue to be confused as you refuse to
learn from others.
>
>>>
>>>
>>>>
>>>>> Additionally if the C++ standards defines something and you say its
>>>>> incorrect, then who is more likely to be wrong?
>>>>
>>>> Where have I have said that the C++ Standard is incorrect? I haven't
>>>> said any such thing so you are either lying or are confused.
>>
>>> You said that char (*p)[3] points to a 1d array and not to a 2d array,
>>> but the standard states different.
>>>
>>
>> p is a pointer to a 1d array and the standard does not state
>> different; p may point to a 1d array subobject of a 2d array and if it
>> is pointing to the first 1d array subobject of the 2d array then one
>> can say it points to a 2d array but this is informal language and
>> technically inaccurate. As others have said "points into" is a more
>> acceptable term that covers all bases.
>>
> This is utter nonsesne the C++ standard states clearly what a pointer to
> an array is and how it behaves.
> A pointer to a 2d array, when derefernced returns a 1d array subobject.
> And that is a FACT defined in the C++ Standard.
> It doesn't matter how much you try to worm your way around this fact, it
> is clearly defined in the standards and until you accept this fact you
> will always be wrong.
You are the one spouting utter nonsense; the Standard says no such
thing. Dereferencing a pointer to a 2d array results in a reference to
a 2d array as the following code shows:
template <typename T, std::size_t N1, std::size_t N2>
void is_a_2d_array(T (&a)[N1][N2])
{
std::cout << "2D array; dimensions = " << N1 << " x " << N2;
}
int main()
{
char a[7][42]; // 2D array
char (*p)[7][42] =&a; // pointer to a 2D array
is_a_2d_array(*p); // dereferenced pointer to a 2D array is a 2D array
reference
}
/Leigh
[snip]
> >> You said that char (*p)[3] points to a 1d array and not to a 2d array,
> >> but the standard states different.
>
> > p is a pointer to a 1d array and the standard does not state different; p
> > may point to a 1d array subobject of a 2d array and if it is pointing to
> > the first 1d array subobject of the 2d array then one can say it points to
> > a 2d array but this is informal language and technically inaccurate. As
> > others have said "points into" is a more acceptable term that covers all
> > bases.
>
> This is utter nonsesne the C++ standard states clearly what a pointer to an
> array is and how it behaves.
> A pointer to a 2d array, when derefernced returns a 1d array subobject. And
> that is a FACT defined in the C++ Standard.
No, the standard says that a 2d array (NOT a _pointer_ to a 2d array,
but just
a 2d array) will be converted to a pointer to 1d array, and this
pointer-to-
1d-array, when dereferenced, yields (of course) a 1d array.
Read 8.3.4p7 a little more carefully. If this isn't your reference
(and it
_is_ the one you've used in the past), then what part of the standard
supports
your claim?
And just to be clear "is_a_2d_array" could be renamed to
"an_array_with_at_least_two_dimensions" as you can pass it an array with
more than 2 dimensions but you *cannot* pass it an array with just 1
dimension. The fact that the above code compiles is proof that your
claim that dereferencing a pointer to a 2d array returns a 1d array.
/Leigh
.. is invalid
/Leigh
Come on, get it right. Is there one standard that defines the C++
language or more than one? Which sections on the mythical other
language (not library extension) standard are you referring to?
Citations, please.
--
Ian Collins
>No, the standard says that a 2d array (NOT a _pointer_ to a 2d array,
>but just
>a 2d array) will be converted to a pointer to 1d array, and this
>pointer-to-
>1d-array, when dereferenced, yields (of course) a 1d array.
Yes it says exactly what I say.
The following is a 2d array converted to a pointer:
char arr[8][8];
char (*p)[8] = arr;
The pointer is a pointer to a 2dim array, its type is pointer to (2-1)dim
array so that when its dereferenced it returns an (n-1) dim array. That is
how pointers to arrays work in C++ and its explained so in the C++
standards.
The above is how an array is converted to a pointer the following is
possible but not what is generally meant by array to pointer conversion:
char (*pp)[8][8] = &arr;
This is not what happens when an array is converted to a pointer.
Similarly with 1d arrays:
char arr[8];
char* p = arr; /*Convert array to pointer*/
char (*p)[8] = &arr; /*Differs in level of indirection , not a standard
conversion.*/
According to the C++ standard the correct terminology for array to pointer
conversion is exactly what I have said.
An array of 10 chars , when converted to a pointer, is of pointer-type
char* , not char (*p)[10].
>Read 8.3.4p7 a little more carefully. If this isn't your reference
>(and it
>_is_ the one you've used in the past), then what part of the standard
>supports
>your claim?
I quote the section below , it fully explains how arrays work in C++.
Its all explained in the standards.
This is where you fail , because you have on many occassions said that a
pointer to T, can only point to a T.
As you say a char* can only point to a single char and cannot point to an
array of chars.
But when I post quotations from Stroustrup and the C Faqs , you start to
look stupid.
You are inconsistent and seem confused.
According to the C++ standards when a 2d array is converted to a pointer the
pointer-type is a (n-1) dim array. Thus the correct conversion for a 2d
array to a pointer is:
char a[7][7];
char (*pa)[7] = a;
The C++ standard explains this is how a 2d array is converted to a pointer,
so that when dereferenced it returns a 1d array(one of its subarrays).
What you have done is not a standard array-pointer conversion. You have
created an extra level of indirection.
I accept, no problem. He is not saying that a char* __is__ a pointer
to an array of char, he is saying that it can __point to__.
He is merely using common expedient way of talking about these things,
where we say that TYPE*, when it points to the __first element__ of
the array, points to the __array__.
> Also do you accept what is detailed int he C++ standards where it clarifies
> that a pointer to an array, when dereferenced , returns an (n-1) dim array?
I don't know what part of standard are talking to, but I am pretty
sure that you are wrong. It rather returns a __reference to same-
dimension array__, e.g.:
void f()
{
int a[2][2]; // 2 dim array
int (*p)[2] = &a[0]; // pointer to 1d array.
int (&br)[2] = *p; // dereferencing returns a reference to a 1d array.
}
Goran.
OK, so... p is a pointer to a 2d array, but it's __type__ is a pointer
to 1d array. That's the first time I have heard of such a distinction
in this context. So what is the difference between "X is" and "type of
X is"? (I'll tell you: there's no distinction, and p __is__ what its
type is, and that is a pointer to 1d array. And because at runtime p
points to the first element of arr, we __commonly say__ that it points
to arr).
Goran.
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
So what is
a) Your confusion
b) your argument?
As far as I am aware you , like the others , beleive that with a simple 1d
array:
int* p= new int[6];
p is a pointer to a single int and not a pointer to the array. But
according tot he standards, Bjarne and C FAQs, a pointer to a 1d array is
exactly the same type of pointer as a pointer to a single element.
So what exactly is your disagreement with this? Why do you have a problem
accepting this is the way pointers to arrays work in C++?
If you are just going to continue arguing because you cannot accept that
you're wrong, then lets clarifiy what exactly are you trying to argue about
now? What is your argument now exactly, the definition of the word "is" or
some other bullshit?
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Do you accept that the char* points to an array of chars or not?
Do you accpet that
int* p = new int[7];
p points to an array of ints?
If you do shut up and accept defeat. If you don't shut up you are wrong.
I accept that we __commonly say__ that, when such pointer points to
the first element of an array, it points to the array. Underlying
truth is, though, that such pointer __is__ a pointer to a __single__
array element (here, first).
Goran.
> As far as I am aware you , like the others , beleive that with a simple 1d
> array:
> int* p= new int[6];
> p is a pointer to a single int and not a pointer to the array. But
> according tot he standards, Bjarne and C FAQs, a pointer to a 1d array is
> exactly the same type of pointer as a pointer to a single element.
This is your __interpretation__, and is __not__ an accurate one.
Goran.
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
What is your interpretation?
Is it the case that, as I said, you think p does not point to an array?
I say p can point to an array you say this is not accurate. What exactly,
IYO, is innacurate about this?
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Well you have to accept it don't you. Because this is the way it works.
But you add a "but" clause to your acceptance, so you still disagree.
You seem confused, inconsistent and you don't know what you are talking
about.
Your "but" clause seems to suggest that the pointer doesn't really point to
an array because the pointer-type is a pointer to int.
But you cannot make this clear because instead of saying the pointer-type
you say such pointer___is__a pointer to a___single___ array element. When
you probably mean to say the pointer-type is a pointer to an int.
No I haven't; I have said that a pointer to a scalar is not a pointer to
an array and have said that "pointer to" is different to "points to" if,
like you, we disregard technical accuracy.
>
> As you say a char* can only point to a single char and cannot point to
> an array of chars.
> But when I post quotations from Stroustrup and the C Faqs , you start to
> look stupid.
I have said that a pointer to a scalar is not a pointer to an array; a
pointer to a scalar can point to an array element of the same scalar type.
>
> You are inconsistent and seem confused.
I am not inconsistent; you are both confused and cause confusion due to
your use of ambiguous terminology and lack of technical accuracy.
pa above is *not* a pointer to a 2D array; it is a pointer to a 1D array.
> The C++ standard explains this is how a 2d array is converted to a
> pointer, so that when dereferenced it returns a 1d array(one of its
> subarrays).
Indeed; this is implicit array-to-pointer conversion; nobody has said
that this is incorrect.
>
> What you have done is not a standard array-pointer conversion. You have
> created an extra level of indirection.
Correct I have created an extra level of indirection to create a pointer
to a 2D array; without that extra level of indirection I would be
creating a pointer to a 1D array via implicit array-to-pointer conversion.
/Leigh
> This is your __interpretation__, and is __not__ an accurate one.
Do you have this conception that, after being told this a large finite
number of times, a light Paul will come to believe it? Because I have
no freaking idea how you came by that conception.
I believe he's wrong.
You believe he's wrong.
Paul believes he's right.
Maybe some others agree with him - I don't know
There is no possible way on earth any of us are going to convince the
other. None at all.
Accept that. And let it go.
Let it go, man. Just let it go.
And when he starts a new thread in an attempt to restart his argument,
ignore it. Please. Just ignore it. However much it riles you - and
it clearly upsets you quite a lot - please, please, please, in the
name of rationality, just ignore it.
Please.
If you saw a man on the street wearing a sandwich board amd shouting
"Justin Bieber is the antichrist", and quoting scripture to back it
up, I don't believe you'd waste hours of your life debating him on the
street - and exhaustively searching the Bible for evidence that the
antichrist will not appear as a mildly annoying Canadian - not least
because you'd look as crazy as he is.
Well, that applies on the internet too.
You don't have to prove yourself right - just prove yourself sane.
You are incorrectly trying to suggest that the term "is a pointer to" means
something different than the pointed to object.
If you mean its a pointer type pointer to X then say that because this is
the techincally accurate term. Not your twisted nonsense.
>>
>> As you say a char* can only point to a single char and cannot point to
>> an array of chars.
>> But when I post quotations from Stroustrup and the C Faqs , you start to
>> look stupid.
>
> I have said that a pointer to a scalar is not a pointer to an array; a
> pointer to a scalar can point to an array element of the same scalar type.
>
>>
>> You are inconsistent and seem confused.
>
> I am not inconsistent; you are both confused and cause confusion due to
> your use of ambiguous terminology and lack of technical accuracy.
>
You are one who is inaccurate , the term "points to" and "is a pointer to"
both refer to the same pointed to object.
You attempt to use the term "is a pointer to" to mean is of type pointer to.
No , it points to a 2d array.
Therefore it is a pointer to a 2d array. Its type is a pointer to a 1d array
because this is how pointers ot arrays work in C++.
You're POV that if something points to an array it is not a pointer to an
array is very confused and techincally inaccurate.
>
>> The C++ standard explains this is how a 2d array is converted to a
>> pointer, so that when dereferenced it returns a 1d array(one of its
>> subarrays).
>
> Indeed; this is implicit array-to-pointer conversion; nobody has said that
> this is incorrect.
>
You are saying it doesn't point to a 2d array, so therefore you don't seem
to accept that this type of pointer is used to point to a 2d array.
>>
>> What you have done is not a standard array-pointer conversion. You have
>> created an extra level of indirection.
>
> Correct I have created an extra level of indirection to create a pointer
> to a 2D array; without that extra level of indirection I would be creating
> a pointer to a 1D array via implicit array-to-pointer conversion.
>
No you are talking about the pointer type but you use incorrect terminology.
When we say X is a pointer to an array this doesn't not mean the same as x
is a pointer-type pointer to an array.
The term "is a pointer to" refers to the pointed-to object and is not a term
that defines the pointer type for example:
void* p = (void*)new int[6];
p is a pointer to an array of 6 ints. p is not a pointer to void.
> This is your __interpretation__, and is __not__ an accurate one.
Do you have this conception that, after being told this a large finite
number of times, a light Paul will come to believe it? Because I have
no freaking idea how you came by that conception.
I believe he's wrong.
You believe he's wrong.
Paul believes he's right.
Maybe some others agree with him - I don't know
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
I believe Bjarne stroustrup and the C faq's and the C++ standard.
Yes I beleive Bjarne Stroustrup is correct when he says that a char* can
point to an single char OR an array of chars.
Just accept you are in the wrong and run away, with a few defiant name
calling insults as you run off.
This must be a royal "we" as nobody else (nor the Standard) agrees with you.
>
> void* p = (void*)new int[6];
>
> p is a pointer to an array of 6 ints. p is not a pointer to void.
No; p *is* a pointer to void.
/Leigh
My "but" accepts the desire for expediency in communication, nothing
more. Pointer still __is__ a pointer to the first element of the
array.
Goran.
I don't need interpretation, I know what is technically and
practically correct. And your __interpretation__ isn't any of that.
Goran.
Well the standard uses the term "is a pointer to" to refer to the pointed to
object, for example the standard uses terms like:
is a pointer to an incomplete object.
It's obviously refering to the pointed to object, and not the pointer-type.
>
>>
>> void* p = (void*)new int[6];
>>
>> p is a pointer to an array of 6 ints. p is not a pointer to void.
>
> No; p *is* a pointer to void.
>
Your terminology is incorrect, the pointer-type is void pointer but this
does not mean it points to a void.
p is a pointer to....*drumroll*.. what it points to. Your attempt to
suggest otherwise is nothing more than a desperate attempt to make your
arguemnt correct, but it only makes you even more incorrect.
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
My interpretation is backed up by quotations form Bjarne Stroustrup and the
C FAQs, and the C++ standard.
You don't even have an argument anymore because your original argument has
been proven incorrect.
It's not. You are __attempting__ to back it up through faulty logic
and spurious insults.
Goran.
You can repeat your nonsense as many times as you like but it will
remain as incorrect nonsense. It is obviously not referring to the
pointed to object as you cannot have an object of an incomplete type;
you can have an "incomplete object type" though which is the term the
Standard actually uses not "incomplete object".
>>
>>>
>>> void* p = (void*)new int[6];
>>>
>>> p is a pointer to an array of 6 ints. p is not a pointer to void.
>>
>> No; p *is* a pointer to void.
>>
> Your terminology is incorrect, the pointer-type is void pointer but this
> does not mean it points to a void.
My terminology is correct; p is a pointer to void.
> p is a pointer to....*drumroll*.. what it points to. Your attempt to
> suggest otherwise is nothing more than a desperate attempt to make your
> arguemnt correct, but it only makes you even more incorrect.
p is a pointer to void; what object p points to does not change the type
of p; "pointer to void" is the type of p.
/Leigh
>> p is a pointer to....*drumroll*.. what it points to. Your attempt to
>> suggest otherwise is nothing more than a desperate attempt to make your
>> arguemnt correct, but it only makes you even more incorrect.
>
> p is a pointer to void; what object p points to does not change the type
> of p; "pointer to void" is the type of p.
>
As I have said you are talking about the pointer-type not what it points to.
A pointer-type void pointer, does not point to a void as you incorrectly
suggest.
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Yes it is.
Who are you to say otherwise when you don't even have an argument anymore?
Remind me what exactly is your argument again?
Oh you cant because your argument has been proven to be incorrect.
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
You argument was that it was a pointer to the first element and only to the
first element. It did not point to any array.
Now since I have presented evidence that proves the experts think otherwise
you seem to have semi accepted the truth , but you do not fully accpet it.
So be it , that is your problem.
<shrug>
I never said there was a void object however "pointer to void" is a
correct term; from the Standard:
3.9.2/4
"Objects of cv-qualified (3.9.3) or cv-unqualified type void* (pointer
to void), can be used to point to objects
of unknown type."
>
>
>>> p is a pointer to....*drumroll*.. what it points to. Your attempt to
>>> suggest otherwise is nothing more than a desperate attempt to make your
>>> arguemnt correct, but it only makes you even more incorrect.
>>
>> p is a pointer to void; what object p points to does not change the
>> type of p; "pointer to void" is the type of p.
>>
> As I have said you are talking about the pointer-type not what it points
> to.
> A pointer-type void pointer, does not point to a void as you incorrectly
> suggest.
I never said anything "pointed to a void"; I said p was a "pointer to
void" which is a correct term (see above).
I do not care about terms such as "pointer-type" that you define; I care
about terms defined by the C++ Standard.
/Leigh
The type of pointer is not always what it points to, especially with a void
pointer.
>
>>
>>
>>>> p is a pointer to....*drumroll*.. what it points to. Your attempt to
>>>> suggest otherwise is nothing more than a desperate attempt to make your
>>>> arguemnt correct, but it only makes you even more incorrect.
>>>
>>> p is a pointer to void; what object p points to does not change the
>>> type of p; "pointer to void" is the type of p.
>>>
>> As I have said you are talking about the pointer-type not what it points
>> to.
>> A pointer-type void pointer, does not point to a void as you incorrectly
>> suggest.
>
> I never said anything "pointed to a void"; I said p was a "pointer to
> void" which is a correct term (see above).
>
No its incorrect if you omit the word "type".
It's type is void pointer.
When a pointer is a pointer to X, X is the pointed to object, not the
pointer type.
When you say a pointer is type pointer to X, then there is a different
meaning implied altogether.
You INCORRECTLY use the former term , with the later definition.
> I do not care about terms such as "pointer-type" that you define; I care
> about terms defined by the C++ Standard.
>
You don't care about anything except YOU being right, even when you are
blatantly wrong.
You have once again been proven wrong and you are and always will be a
proven idiot. Why don't you go fuck off back into yur hole or something and
stop speaking bullshit as usual :-)
A void pointer points to a void HAHA , you are such a fuckin moron Leigh.
Sometimes you really need to take a good look in the mirror and maybe bang
your head of it a few times. Not to hard though or you might break it. (the
mirror not your head)
>
> A void pointer points to a void HAHA , you are such a fuckin moron
> Leigh. Sometimes you really need to take a good look in the mirror and
> maybe bang your head of it a few times. Not to hard though or you might
> break it. (the mirror not your head)
Who said a void pointer points to a void? I certainly didn't; I said
"pointer to void" which is a correct term (according to the C++
Standard) and is a synonym of "void pointer".
You are just one big fail troll with nothing better to do; it is quite
pathetic really.
/Leigh
You said it was a pointer to a void. This is different from saying its a
type pointer to void.
Now you are backed into a corner you can only respond to argument by
telling lies. I did not say it was a "pointer to a void"; I said it was
a "pointer to void" which is a synonym of "void pointer". Read the
Standard.
/Leigh
I said what I meant and I meant what I said.
> You were incorrect, and I'm not in a corner.
Yeah, whatever, dream on.
/Leigh
int* p = new int[7];
The above is a pointer to an array of ints. Its type is int* because thats
the way pointers to arrays work in C++.
This is supported by many authorities and the C++ standard, why do you
refuse to acccept its the way things are?
Your latest attempt to disprove this has been an attempt to twist the
meaning of "is a pointer to" to mean "is type pointer to", where you posted
a snippet from the standards ref:
3.9.2/4
"Objects of cv-qualified (3.9.3) or cv-unqualified type void* (pointer
to void), can be used to point to objects
of unknown type."
The above snippet clearly states *TYPE* , it agrees with me not with you.
HAHA. You fail so much its becoming ridiculous.
Eh!? No, you presented no evidence. You __misinterpreted__ an
interview and a part of the standard.
Goran.
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
No I quoted some text from websites, no interview misquotations.
And I did not misinterpret that standard, the standard clearly states that
pointer representation of arrays are (n-1) dimensional.
Quotes are correct, your __interpretation__ is wrong.
> the standard clearly states that
> pointer representation of arrays are (n-1) dimensional.
Standard does no such thing. not. You made a leap from "array of
dimension n, when it appears in an expression, is __converted__ to a
pointer to an array of the dimension n-1. The opposite is not true,
and standard does not say that. You are misinterpreting that passage.
Goran.
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Yes so if we convert an array to a pointer , the resulting pointer is a
pointer to an (n-1) dim array.
So now we have a pointer to the array, the pointer-type just happens to be
type pointer to (n-1) dim array.
The pointer-type says what the pointer __is__. When dereferenced, it
will give you a reference to the first element of the array. When
incremented, it will give you next element of the array. When indexed,
it will index inside the array. It __never__ points to the array, only
to it's elements, first or otherwise.
It walks like a duck, it quacks like a duck, it __is__ a duck.
Now go huff and puff some more, I see you like that. And it amuses me,
too.
Goran.
The pointer-type says what the pointer __is__. When dereferenced, it
will give you a reference to the first element of the array. When
incremented, it will give you next element of the array. When indexed,
it will index inside the array. It __never__ points to the array, only
to it's elements, first or otherwise.
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
From the C standard this is the definition of a ponter-type:
"A pointer type describes an object whose value provides a reference to an
entity of the referenced type."
This is only part of the definiton, the whole definition is publicly
available in the C standard, and I am not trying to hide anything I am
quoting the part I think is releveant.
The value of a pointer provides a reference to an entity, of the referenced
type.
For a pointer to reference and array of T's, it must be type T*. T is the
referenced type not T[Size].
A pointer to T[Size], such as T (*p)[Size], does not reference the array, it
referneces an array-type, which is a different object than the array. It is,
under the hood, another pointer object, it does not reference THE ARRAY of
T's, it references a different array-type object.
You have no idea what you are talking about. Specifically, "A pointer
to T[Size], such as T (*p)[Size], does not reference the array, it
referneces an array-type, which is a different object than the array"
is simply nonsense. Among other things, it is nonsense because you are
mixing "array-type" and "object" (the latter being an instance of a
type).
You are also making stuff up as you go along. Standard __nowhere__
says that pointer references anything. It does say that pointer points
to something.
Therefore, your explanation is worthless.
Goran.
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
An array-type object is not an instance of a type. Its a fancy pointer with
typeinfo.
Apparently you have no idea, for example the object "arr" is an instance of
what type ?
int arr[10];
This is an array-type object. The instances here are the instances of
integer objects that make up the array.
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
You are also making stuff up as you go along. Standard __nowhere__
says that pointer references anything. It does say that pointer points
to something.
Therefore, your explanation is worthless.
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Its in the definition that C++ inherits from the C standard.
"Apointer type may be derived from a function type, an object type, or an
incomplete
type, called the referenced type. A pointer type describes an object whose
value
provides a reference to an entity of the referenced type. A pointer type
derived from
the referenced type T is sometimes called ''pointer to T''. The construction
of a
pointer type from a referenced type is called ''pointer type derivation''."
What you said up here is pretty correct. However, that bears no
relevance to what I quoted you about:
"A pointer to T[Size], such as T (*p)[Size], does not reference the
array, it referneces an array-type, which is a different object than
the array."
The above is still nonsense, and your subsequent post didn't explain
anything in there.
> You are also making stuff up as you go along. Standard __nowhere__
> says that pointer references anything. It does say that pointer points
> to something.
>
> Therefore, your explanation is worthless.
> xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
> Its in the definition that C++ inherits from the C standard.
>
> "Apointer type may be derived from a function type, an object type, or an
> incomplete
> type, called the referenced type. A pointer type describes an object whose
> value
> provides a reference to an entity of the referenced type. A pointer type
> derived from
> the referenced type T is sometimes called ''pointer to T''. The construction
> of a
> pointer type from a referenced type is called ''pointer type derivation''."
My words "standard never says that pointer references anything" are
correct. Your standard quote, e.g. "A pointer type derived from the
referenced type T is sometimes called ''pointer to T''" does not say,
nor mean, that pointer __references__ anything, which is what you
previous post said. Pointer __points to__ something, and this is what
standard does say. And especially in the context of C++, word
"reference" typically has another meaning.
I believe that you are arbitrarily muddying things up to support your
worthless point.
Goran.
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
The only nonsesne is coming from you.
You are trying to argue that a pointer to an array of chars, is a pointer to
an array-type object and not a pointer to char type objects.
Which is obviously technically incorrect.
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Its quite obviously you that are muddying things up.
You seem to speaking a big pile of shit abut what your interpretation of
"references" is.
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx