Unsigned types are DANGEROUS??

M

MikeP

James said:
[...]
There is the option to avoid "brain-damaged" language constructs
altogether, which no one has brought up. Of course if that is not
practical, then maybe the language is based upon weak foundation and
transition should be the goal. Something's gotta give.

Yes. Let's avoid brain-damaged language constructs entirely.

I imagine that you have many such corrective pieces of code in your
toolbox. Such as SafeInt and many others. Why stop short? Wrap every
primitive and only use "unboxed" ones as an optimization. That way you
can get any semantic you want.
Of course, that means not using C++.

It could mean that. That's what I alluded to with "transition".
Nor Java, nor C#, nor any
other language in the C family. Nor Ada, nor anything else
derived from Pascal. We'll just have to define our own
language, from scratch.

Sounds good.
And not let it evolve, or actually be
used for anything.

Oh, a skeptic.
The last will be easy, because there won't
be a compiler for it either.

Well it's not 1960, it's not that hard to write a compiler, especially if
reusing an existing backend.
In the end, C++ isn't really a very good language at all. It's
just that all of the others available are even worse.

I used to think that too, but I haven't examined C#, so I can't say that
anymore. It could be the way to go on the associated platform.
 
M

MikeP

James said:
Yes. Technically, I personally find the arguments against
unsigned convincing. But not overwhelmingly so, and I can
easily understand the other side. In fact, IMHO, the technical
arguments on either side are so underwhelming that they don't
outweigh the non-technical arguments.

Well said. I've been trying to convey that same thought.
Apparently.

It was a joke!
I was a contractor for many, many years; I've
worked in a lot of different places (in different domains---I'm
a telecom's specialist, but I currently work in an investment
bank). And I can't think of a single case where the rule wasn't
int, unless there are strong technical reasons otherwise. That
seems to be the general attitude. In most cases, I'm sure,
without ever having considered the technical aspects. One
learns C++ from Stroustrup, and Stroustrup uses int everywhere
(without ever giving a reason, as far as I know---I suspect that
he does so simply because the people he learned C
from---Kernighan, in particular) did so.

I postulated that also: I think they haven't thought of trying the
alternative or dismissed it too soon because of being too close to the
technology. Then again, I switched over when I was doing C and didn't
know all the ramifications (still don't, but close enough) but found the
change worthwhile and didn't really consider going back to preferring
signed. So I'm kind of the opposite.
You don't need a list.

Sometimes examples are an easier read.
The fundamental problem is: what do you
do when signed and unsigned meet.

Well there's more than that, such as loop counter rollover.
Generally, when two types
meet in an arithmetic expression, the one with the smaller range
is converted to the one with the larger range. The problem with
unsigned/int is that the range of one is not a subset of the
range of the other. So you have four possibilities:
-- convert both to signed,
-- convert both to unsigned,
-- convert both to some larger type, whose range is a superset
of both of there ranges.
-- declare the operation illegal without an explicit cast.
All things considered, I think that the last choice would be the
best. But it certainly doesn't fit into the philosophy of C,
and by the time the C committee was discussing standardization,
would have broken who knows how much existing code. The third
also sounds nice, until you realizde that there may not be some
larger type---on a 32 bit machine, both int and long are 32
bits, and back then, there was no long long. Historically, most
C compilers implemented the first; the C committee, after an
enormous amount of discussion, chose the second. With the
recognition that it also had problems.

Nothing wrappers wouldn't solve. I'm not sure how many cases get missed
by compilers that give warnings for signed/unsigned conversions.
size_t underwent similar discussions. The absolute requirement
was that it could represent the size of any object which you
could define in C. Which meant, on the 32 bit machines of the
day (and without long long), unsigned long (which was the same
as unsigned int). Short of making a C implementation impossible
on the VAX (the most widespread implementation of the day), they
had to allow size_t to be unsigned.

You make it sound like unsigned was a compromise. How so?
And given the problems
which occur if you don't even know if a type is unsigned or not,
they preferred requiring unsigned to making it implementation
defined.

Anyway, as mentionned above, the "killer" argument, if there is
one, is not technical, but rather what the average, everyday C++
programmer understands when he sees the type. (Of course, if
you don't care about the readability of your code, it's not a
killer argument at all.) And for whatever reasons, most C++
programmers learn, directly or indirectly, from Stroustrup.
Who, in his most recent book, doesn't mention unsigned until (as
far as I can tell) page 919, when he presents bitwise operators.
And where he refers to §25.5.3, where at one point he says:

So far, we have just used signed integers (e.g. int). A
slightly better set of rules would be:
-- Use signed integers (e.g. int) for numbers.
-- Use unsigned integers (e.g. unsigned int) for sets
of bits.

People read this, and live by it; when most C++ programmers see
"unsigned", they assume "sets of bits". Especially as earlier
(page 280, for example), he has examples like:

for (int i = 0; i < v1.size(); ++ i)
// ...

, where v1 is an std::vector.

All of which, IMHO, puts the burden of proof on those arguing in
favor of unsigned.

Well only for those who hold BS as infallible. I've seen the cfront code,
and that's a mess, so I hope he has improved since then (surely C++ has
helped him a lot).
Unless there are really strong technical
arguments in favor of unsigned (and I've yet to see really
strong technical arguments either way), readability says go with
the crowd.

You were doing great until that last "go with the crowd" statement!
(Unless you meant within an existing project rather than a new one, where
either alternative can be chosen. i.e., Consistency is of course
important). Also, I'm not sure whether you consider richness of semantics
a technical thing: using signed, you have one thing while using unsigned
you have "divided and conquered".
 
P

Paul

Peter Remmers said:
Am 15.03.2011 21:14, schrieb Paul:
message
Am 15.03.2011 19:17, schrieb Paul:

The important, practical consequence is that array size information
is
lost as soon as the array identifier is converted into a pointer.
You
can't even get it back when the information is still available to
the
compiler:

int arr[] = {1,2,3};
int * p = arr;

sizeof(arr) == 12
sizeof(p) == 4

With your interpretation a dynamic array is not an array, which is
obvioulsy
incorrect.


An array created by 'new' is an array that has no name. Just like with
everything that is dynamically created by new, there is no identifier
that
directly identifies the object created on the heap. All you get is a
pointer to the object which must be stored in a pointer variable that
you
have to provide. That pointer is not the array itself. It is a
different
object, with its own identifier and its own region of storage. This is
obvious if you consider what sizeof() returns for the two.

Consider this:

new int[3];

This statement does not contain any identifiers, and yet an array has
been
created on the heap. And because the pointer that new returned was not
saved, the array is leaked. There is just no way to get hold of the
array
without an identifier. A pointer only gives you indirect access to the
array.

The pointer is the arrays identifier.

No, it's not. An identifier is just a string of characters in the source
code - a compile-time entity. The pointer value returned by new is a
run-time entity. This value is stored in a pointer variable, which has an
identifier, an address (possibly in a completely different storage type as
the array), and a value (the address of the array's first element) which
is of course different from its own address.

This is just another example of word games the identifier is arr in
following:
int* arr = new int[16];

Yes its a pointer but it s a pointer to an array. And, as it's the only
identifier we have for the array, it's the arrays' idientifier.
A entity withiout an identifier is not a useable entity.

That pointer must be treated like an array, by this i mean you cannot
re-assign it an address of simple integer:
int x;
arr = &x;
This is wrong you unless you have previously taken all precautions to assign
the array to a new identifier, or you don't care about losing it. As soon as
you lose the pointer you lose the array because the pointer is the
identifier for that entity, or if you prefer exact standardesque it might
be... The identifier for the pointer is also the identifier for the array.

Do you think we should consider a dynamic array an unidentified entity? I
don't I think they are identifiable by the pointer returned from new, this
seems pretty logical to me.
If you disagree with the above please provide a *reasonable* argument why.
Not state the obvious fact that the identifier for the array is actually a
pointer.
Or suggest that I don't know what an identifier means in any sense of the
word , it was me who introduced the word to the discussion.
int arr[10];

int *p1 = &arr[0];
int *p2 = new int[10];

Here, p1 and p2 are completely equivalent in that they both are pointers
to int, and that they both point to the first element of a (each a
different) array of 10 ints. The difference is the way the respective
array has been created. p1 points to an array in automatic storage. p2
points to an array in dynamic storage. The array p1 points to has a name -
embodied by the identifier "arr". p2's array does not have a name and so
there is no identifier.
I disagree, the identifier p2 is the only identifier we have for the array
therefore it is the identifier for both pointer and array. See above
explanation.
It's nonsensical to suggest the array has no identifier, when it does.
Im the example above, p1 and p2 only provide indirect access because they
are distinct objects of pointer-type that only point to an array, but they
are not the array itself. In the case of p1, "p1" gives indirect access,
"arr" is direct access. For p2, there is no direct access because the
array does not have a name, and so p2 is the only (indirect) means of
access.
All memory is accesssed via a pointer address, thats just how computers
work. In this case p2 is the name we have to identify the array, so it does
have a name.

If I have a piece of paper with a picture of Paul on it, would you say the
paper *is* Paul himself? It is just a picture of Paul. The
4-character-string "Paul" is the identifier that represents the name of
Paul. If I name my piece of paper "Judy", "Judy" is an identifier that
represents the name of the Picture. "Judy" certainly is not an identifier
for Paul, and the piece of paper is even less so.

If I give you a picture of a person you don't know, then to you, that
person does not have a name, and you can not directly refer to that person
by their name, but only indirectly as "the person on that picture" ("the
array that the pointer points to"). If I happen to know that the person's
name is "Jerry", I can say "Jerry's hair is black", while you can only say
"The color of the hair of the person on that picture is black".
Show me how to pass an array to a function without giving the array a name.
:) I bet you can't do it, you need an identifier.

Would this suggest dynamic arrays cannot be passed to functions, I think not
because we can pass identifiers, which in this case happen to be pointers.

If two objects have a different type, they can't be the same object... nor
can one object be the identifier of the other.
Here you use identifier as if it's an object, but you were fast to correct
me earlier by stating it is just a string of characters in source code. Back
to the word games again.

An identifer for one object can also be the identifier for another object.
Who says an identifier can only identify one object?
An array can be considered a contiguous block of different objects,
therefore any array identifier identifies numerous objects.
I think what you are trying to explain is the following:
#include<iostream>
typedef int t_arr16[16];

void foo1(int* par){
std::cout<< "sizeof:"<< sizeof(par)<< "\t typeinfo:"<<
typeid(par).name();}

void foo2(t_arr16& par){
std::cout<< "sizeof:"<< sizeof(par)<< "\t typeinfo:"<<
typeid(par).name();}

int main(){
t_arr16 arr1 ={0};
std::cout<< "Calling foo1: ";
foo1(arr1);
std::cout<< std::endl<< "Calling foo2: ";
foo2(arr1);
}

That works because an array variable can be implicitly converted to a
pointer to its element type.

Try this:
int *p = &arr1[0]; // or int *p = arr1;
foo1(p); // OK
foo2(p); // error

The output I get for
foo1(arr1); // implicit conversion from int[16] to int*
foo2(arr1); // passed as reference
foo1(p); // p is already int*
//foo2(p) error: int* cannot be converted to int(&)[16]
I was posting the code to support your argument, that static arrays can
carry information, and array-types are different from pointer-types.
is this:

sizeof:4 typeinfo:pi
sizeof:64 typeinfo:A16_i
sizeof:4 typeinfo:pi

Different sizes, different types, different objects.

Of course, foo2's "par" is just an alias for the array and not the array
itself, because it is a reference type - for which we now that the
compiler most likely just uses a masqueraded pointer. It does not actually
pass those 10 integers by value.

This does not mean the following is not an array:
int* arr1 = new int[16];
++arr1;

It means that arr1 is a pointer, initialized with the address of the first
element of some unnamed integer array on the heap, and then its value is
changed to be the address of the second element of that array.
And it doesn't suggest an array must always have zero based indexing. The
C++ standard specifically states the rules about array indexing and its
clear that C++ allows non-zero based indexing.
What possible reason, even in the most idiotic minds, would there be to
restrict the language in such a way?

int arr1[10];

If you access the array's elements via the "arr1" identifier, you can't
use a negative index because that would be UB because your access would be
out of range. That's because "arr1" can only ever be converted to a
pointer to the *first* element (the one with the index zero) of the array.
arr1 connot be assigned to point to something else, say the second
element, because it *is not* a pointer whose value can be changed. It can
conly be *converted* to a pointer.

int *p = &arr1[1];

If you create a pointer variable, you can have it point anywhere you want,
for example somewhere in the middle of arr1. You can then use positive or
negative indices as offset to that pointer base, as long as you don't try
to access something that is not backed up by some object's storage. Of
course, interpreting the data you read from that address as an int may
still be UB.

How is it undefined behaviour?
An array is guaranteed to be a contiguous block, its completely defined in
C++ to create a non zero based array.

int* arr= new int[16];
/*Assume allocation succeeded*/
++arr;
arr[-1]=64;

arr[-1] is guaranteed to yield the first element of the array. It's not UB,
it's completely defined.


We're not playing word games. The terms "identifier", "name", "object",
and "array" etc. are clearly defined by the standard.
So can you tell me where the standard defines that these "names" or
"identifiers" cannot refer to more than one "object" or "entity"?
int x;
The actual integer object is just a a piece of memory, x is just an
identifier. So are we wrong to say x is an integer? Likewise:
int* arr = new int[16];
The actual array object is just a piece of memory, arr is just an
identifier. So are we wrong to say arr is an array?

I agree that in a programmer's everyday language, one could say "I create
a dynamic array 'arr' of 16 integers". But that does not mean that you can
close your eyes to the fact that formally, and in reality, "arr" is just a
pointer to an integer that is initialized to point to the first integer
element of some unnamed array in dynamic storage.

Of course its wrong to close your eyes to this fact, but it is even more
wrong to close your eyes to the fact that it's primarily an array.
The biggest entity here is the array , the pointer is just an intermediate
object used to identify the array. You seem to be trying to shift the foucs
so as the pointer is the the main entity, when it's not.
It's just that the formal laguange is too verbose to use it all day long.
So we use the formally incorrect short forms, where everybody knows what is
meant by it, but where also everybody knows that it is not completely
correct.

But most of the things we say is correct. You are interpreting correctnesss
as meaning "used in the same context as the standards".
Yes the standard is a refernece which defines the language and is therefore
the rules, but it is written in a context that must be interpeted correctly.

If I say, with:
int x =5;
x is an integer.
If someone "corrected" me by saying no that not strictly true because its
actually a sequence of characters, they are the ones who are incorrect for
misinterpreting(deliberately or otherwise) the context of the statement,
IMO.
I trust you will agree with the above, as it seems preety much common sense.

Now if I say an array can have a non zero based index as per:
int* arr = new arr[16];
arr++;

If someone says that's not an array it's a pointer they are incorrect
because it's both a pointer and an array.
The C++ language is defined in such a way that it has the flexibility to do
this, if not I think its userbase would be a fraction of it's size. Can you
imagine what a shitty language it would be if we couldn't even create a non
zero based array, I would drop it like a brick.
I agree that you could say "foo::bar() is a member function of xyz", where
xyz is some object of class-type foo. I use such informal speech myself,
and I admit that you can get pretty far with such a point of view. But I
do keep in mind that formally, foo() is a member of xyz's class, because
that's what it really is behind the scenes. And if it comes to corner
cases, and you don't have to go very far, these details become apparent.
Back to the old member function thing , hmm.
foo::bar() is a class scope expression, this does not imply any object.

An object is:
foo f;
An member function that is part of such object is :
f.bar();

I can see it both ways too, but I don't distinctly see one as correct and
the other is not correct, both are correct in their given context.

What is incorrect is to suggest that all member functions are members or a
class but not members of an object of that class type. As obviously this
only applies to static member functions.
Can you imagine what a shitty language it would be if we couldn't have
member functions for objects? It certainly wouldn't be an OOP language in
any sense of the term.
 
P

Paul

Garrett Hartshaw said:
Playing word games can work both ways, example:
int x;
The actual integer object is just a a piece of memory, x is just an
identifier. So are we wrong to say x is an integer? Likewise:
int* arr = new int[16];
The actual array object is just a piece of memory, arr is just an
identifier. So are we wrong to say arr is an array?

int x; /* x is an integer */
int * p = &x; /* p is a pointer to an integer */
int a[3]; /* a is an array of 3 integers */
int * pa = a; /* pa is a pointer to an integer */
int * dx = new int(); /* dx is a pointer to an integer */
int * da = new int[3]; /* da is a pointer to an integer */

Because 'pa' and 'da' both point to the first element of an array, it is
well defined to do pointer arithmatic on them as long as you stay within
the bounds of the underlying array (e.g 'pa[1]' which is equivalent to
'*(pa + 1)'). With 'a', 'a[1]' is again equivalent '*(a + 1)'. However,
since a is actually an array, a is implicitly converted to type int*
before operator+ can be applied, so it is equivalent to '*((int*)a + 1)'.
Basically what you are saying is that... yes it's well defined to create an
non zero based array in C++. ?

Look at this :

int* arr = new arr[16];
++arr;
arr[-1] = 10;

The name/identifier in the expression arr[-1] is the name of both a pointer
and an array. The expression is converted to *((arr)+(-1)).
That is, in the context of E1[E2], E2 is the -1th member of arr.
Normal people would probably prefer to think that -1, in this case, refers
to the 1st element.

This is the only reasonable way to interpret array indexing as defined in
the C++ standard. To suggest that array indices can never be negative just
seems like a foolish misconception through misintepretations of the
standards.
 
P

Paul

SG said:
I don't see what your confusion is. If the standard states:
"A name is a use of an identifier (2.10) that denotes an entity"
then with:

type* p_name = new type[16];

p_name is the name of the entity, that is the array.
The above expression creates an array, you seem confused about
this, similarly to Leigh and Noah.
Do you think this is not array?

What exacly? p_name? p_name denotes a pointer variable. You
initialized this pointer to store the address of the first element of
a dynamically allocated array.
The fact that the identifier is a pointer goes without saying,

Does it? I honestly can't tell what things go without saying and what
not when it comes to "discussing" something with you. btw: To be very
precise: The identifier *denotes* a pointer variable. An identifier is
a sequence of characters in your source code file.
as does the
fact that its name is p_name. The entity is an array structure,

The entity whose name is p_name is a pointer variable. Period.
No Period.
If I use the name in an expression like so:
p_name[AnIndex];
p_name is the name of an array entity.
You can
use this pointer to access the elements of your dynamically allocated
array, yes. But the "entity" that the standard is talking about w.r.t.
the identifier "p_name" would be the pointer variable. The array you
created has no name. It is created by the new operator which returns
just an address.
Nah your understanding does not ring true with me, sorry.
[...] why I don't understand.

Might I ask what book(s) you used to learn C and/or C++?

Turbo C++ version 3.0 or something. It came in a big brown box with 2 big
manuals and ran on win95.
My first pc was a win95 laptop with a pre mmx CPU Hitachi and cost £1999uk,
which was alot of dosh in those days and not many people had such a nice
laptop.
It involved those PCMCIA modems and dial up net connections which had to be
reconnected ever hour to save from being charged, and I often went out
forgetting to turn it off only to awake the next day and realise I'd left it
on all night, so one of my first programs was a windows background program
that disconnected/reconnected the net connection every 59 minutes..
What books did you learn C++ from?
 
P

Paul

MikeP said:
Well said. I've been trying to convey that same thought.
<prune>
Just to add my tuppence worth :

Some of the arguments for unsigned are not valid arguments, such as the
"array index can never be negative" argument.
As has been proven else-thread an array index can be negative.
This leads me to believe that the people who suggest this do not have a very
good understanding of the language, and are therefore not ideally suited to
always make the best judgment .

HTH.
 
G

Garrett Hartshaw

Garrett Hartshaw said:
Playing word games can work both ways, example:
int x;
The actual integer object is just a a piece of memory, x is just an
identifier. So are we wrong to say x is an integer? Likewise:
int* arr = new int[16];
The actual array object is just a piece of memory, arr is just an
identifier. So are we wrong to say arr is an array?

int x; /* x is an integer */
int * p = &x; /* p is a pointer to an integer */
int a[3]; /* a is an array of 3 integers */
int * pa = a; /* pa is a pointer to an integer */
int * dx = new int(); /* dx is a pointer to an integer */
int * da = new int[3]; /* da is a pointer to an integer */

Because 'pa' and 'da' both point to the first element of an array, it is
well defined to do pointer arithmatic on them as long as you stay within
the bounds of the underlying array (e.g 'pa[1]' which is equivalent to
'*(pa + 1)'). With 'a', 'a[1]' is again equivalent '*(a + 1)'. However,
since a is actually an array, a is implicitly converted to type int*
before operator+ can be applied, so it is equivalent to '*((int*)a + 1)'.
Basically what you are saying is that... yes it's well defined to create an
non zero based array in C++. ?

Look at this :

int* arr = new arr[16];
++arr;
arr[-1] = 10;

int * arr; /* arr has type 'int *' (eg pointer to int) */
arr = new int[16]; /* arr points to the first element of an array */
++arr; /* arr points to the second element of the array */
arr[-1] = 10; /* same as *(arr - 1) */

The important thing to note here is that arr does not suddenly become
an array when we assign 'new int[16]' to it. It remains a pointer
only (eg. I could assign the address of a normal integer to it. This
would not be smart without saving the origional value, but
nonetheless can be done).

I have not (and I don't think anyone else has) said that the argument
to operator[] (E2) must be nonnegative, only that it must stay within
the bounds of the underlying array object. What we have said is that
if E1 *is an array* then it is undefined behavior if you use a
negative index. (For if E1 is an array (not a pointer), any negative
value will be out of bounds (and therefore undefined behavior.))
The name/identifier in the expression arr[-1] is the name of both a pointer
and an array. The expression is converted to *((arr)+(-1)).
That is, in the context of E1[E2], E2 is the -1th member of arr.
Normal people would probably prefer to think that -1, in this case, refers
to the 1st element.

This is the only reasonable way to interpret array indexing as defined in
the C++ standard. To suggest that array indices can never be negative just
seems like a foolish misconception through misintepretations of the
standards.
 
P

Paul

Garrett Hartshaw said:
Garrett Hartshaw said:
Playing word games can work both ways, example:
int x;
The actual integer object is just a a piece of memory, x is just an
identifier. So are we wrong to say x is an integer? Likewise:
int* arr = new int[16];
The actual array object is just a piece of memory, arr is just an
identifier. So are we wrong to say arr is an array?

int x; /* x is an integer */
int * p = &x; /* p is a pointer to an integer */
int a[3]; /* a is an array of 3 integers */
int * pa = a; /* pa is a pointer to an integer */
int * dx = new int(); /* dx is a pointer to an integer */
int * da = new int[3]; /* da is a pointer to an integer */

Because 'pa' and 'da' both point to the first element of an array, it is
well defined to do pointer arithmatic on them as long as you stay within
the bounds of the underlying array (e.g 'pa[1]' which is equivalent to
'*(pa + 1)'). With 'a', 'a[1]' is again equivalent '*(a + 1)'. However,
since a is actually an array, a is implicitly converted to type int*
before operator+ can be applied, so it is equivalent to '*((int*)a + 1)'.
Basically what you are saying is that... yes it's well defined to create an
non zero based array in C++. ?

Look at this :

int* arr = new arr[16];
++arr;
arr[-1] = 10;

int * arr; /* arr has type 'int *' (eg pointer to int) */
arr = new int[16]; /* arr points to the first element of an array */
++arr; /* arr points to the second element of the array */
arr[-1] = 10; /* same as *(arr - 1) */

The important thing to note here is that arr does not suddenly become an
array when we assign 'new int[16]' to it. It remains a pointer only (eg. I
could assign the address of a normal integer to it. This would not be
smart without saving the origional value, but nonetheless can be done).

I have not (and I don't think anyone else has) said that the argument to
operator[] (E2) must be nonnegative, only that it must stay within the
bounds of the underlying array object. What we have said is that if E1 *is
an array* then it is undefined behavior if you use a negative index. (For
if E1 is an array (not a pointer), any negative value will be out of
bounds (and therefore undefined behavior.))
Yes what you are saying is that with a static array declared like so:
int arr[16];
....cannot have a negative array index because these arrays are always
zero-based. I agree(within the bounds of standard C++)


But I disagree with you saying E1 is not an array like so:
int* E1 = new int[16];
++E1;
E1[-1]= 6;

In the expression E1[-1].... E1 is used as an array. The name "E1" is the
name for both the pointer and the array.

The text from the standard seems to have been written to explain the
behaviour of both dynamic and static arrays. Please don't try to interpret
it to mean something along the lines of ..E1 is an array and not a pointer.
The standard also states someplace that array indexing with static arrays
is identical to using pointers, so its intended meaning is obvious.






The name/identifier in the expression arr[-1] is the name of both a pointer
and an array. The expression is converted to *((arr)+(-1)).
That is, in the context of E1[E2], E2 is the -1th member of arr.
Normal people would probably prefer to think that -1, in this case, refers
to the 1st element.

This is the only reasonable way to interpret array indexing as defined in
the C++ standard. To suggest that array indices can never be negative just
seems like a foolish misconception through misintepretations of the
standards.
 
P

Peter Remmers

Am 16.03.2011 04:52, schrieb Paul:
Peter Remmers said:
Am 15.03.2011 21:14, schrieb Paul:
message
Am 15.03.2011 19:17, schrieb Paul:

The important, practical consequence is that array size information
is
lost as soon as the array identifier is converted into a pointer.
You
can't even get it back when the information is still available to
the
compiler:

int arr[] = {1,2,3};
int * p = arr;

sizeof(arr) == 12
sizeof(p) == 4

With your interpretation a dynamic array is not an array, which is
obvioulsy
incorrect.


An array created by 'new' is an array that has no name. Just like with
everything that is dynamically created by new, there is no identifier
that
directly identifies the object created on the heap. All you get is a
pointer to the object which must be stored in a pointer variable that
you
have to provide. That pointer is not the array itself. It is a
different
object, with its own identifier and its own region of storage. This is
obvious if you consider what sizeof() returns for the two.

Consider this:

new int[3];

This statement does not contain any identifiers, and yet an array has
been
created on the heap. And because the pointer that new returned was not
saved, the array is leaked. There is just no way to get hold of the
array
without an identifier. A pointer only gives you indirect access to the
array.

The pointer is the arrays identifier.

No, it's not. An identifier is just a string of characters in the source
code - a compile-time entity. The pointer value returned by new is a
run-time entity. This value is stored in a pointer variable, which has an
identifier, an address (possibly in a completely different storage type as
the array), and a value (the address of the array's first element) which
is of course different from its own address.

This is just another example of word games the identifier is arr in
following:
int* arr = new int[16];

Yes its a pointer but it s a pointer to an array. And, as it's the only
identifier we have for the array, it's the arrays' idientifier.
A entity withiout an identifier is not a useable entity.

Of course it's usable. You do have indirect access to it via a pointer
to its members. You don't need an identifier for the array itself to use it.
That pointer must be treated like an array, by this i mean you cannot
re-assign it an address of simple integer:
int x;
arr =&x;
This is wrong you unless you have previously taken all precautions to assign
the array to a new identifier, or you don't care about losing it. As soon as
you lose the pointer you lose the array because the pointer is the
identifier for that entity, or if you prefer exact standardesque it might
be... The identifier for the pointer is also the identifier for the array.
How can one identifier be used as a name for two different objects at
the same time? The pointer's identifier cannot also be the identifier
for the array.
Do you think we should consider a dynamic array an unidentified entity? I
don't I think they are identifiable by the pointer returned from new, this
seems pretty logical to me.
If you disagree with the above please provide a *reasonable* argument why.
Not state the obvious fact that the identifier for the array is actually a
pointer.
It seems you know that pointers to arrays are just pointers to arrays.
You know that you can have the pointer point to somewhere else and you
know a dynamic array is lost if you don't save the pointer value
somewhere else.
Then why is it so hard to see that a dynamic array does not have a name
of itself? Just because the pointer to an array is the only means of
access, the pointer then automatically must be the identifier of the
array? Dude, no, it just doesn't. It stays a pointer in its own right,
no matter what it points to and no matter whether this thing it points
to does have a name or not.
Or suggest that I don't know what an identifier means in any sense of the
word , it was me who introduced the word to the discussion.
It is quite an automatism that when you don't make sense when using a
word or your usage of it suggest you think it means something different
from what it usually means, then one could think that you don't know
what the word means.
"Identifier" is not the first word.
int arr[10];

int *p1 =&arr[0];
int *p2 = new int[10];

Here, p1 and p2 are completely equivalent in that they both are pointers
to int, and that they both point to the first element of a (each a
different) array of 10 ints. The difference is the way the respective
array has been created. p1 points to an array in automatic storage. p2
points to an array in dynamic storage. The array p1 points to has a name -
embodied by the identifier "arr". p2's array does not have a name and so
there is no identifier.
I disagree, the identifier p2 is the only identifier we have for the array
therefore it is the identifier for both pointer and array. See above
explanation.
It's nonsensical to suggest the array has no identifier, when it does.
What you do here is say "I don't know the name of the guy on the
picture, but I do know that the name of the picture is 'Judy', so I'll
have to call the guy 'Judy' because that's the only name lying around here."

Don't be funny.
All memory is accesssed via a pointer address, thats just how computers
work. In this case p2 is the name we have to identify the array, so it does
have a name.


Show me how to pass an array to a function without giving the array a name.
:) I bet you can't do it, you need an identifier.
Yes, you can pass a pointer to the array's elements. That pointer does
have a name. But it's not the name of the array itself.
Would this suggest dynamic arrays cannot be passed to functions, I think not
because we can pass identifiers, which in this case happen to be pointers.
And pointers happen not to be arrays.
Here you use identifier as if it's an object, but you were fast to correct
me earlier by stating it is just a string of characters in source code. Back
to the word games again.
I should have said "... nor can one object's identifier also be the
other object's identifier"
An identifer for one object can also be the identifier for another object.
Erm. No. Each object has its own identifier, provided it has one at all.
Who says an identifier can only identify one object?
It does not seem logical to you, does it?
An array can be considered a contiguous block of different objects,
therefore any array identifier identifies numerous objects.
When I create an instance of a struct with some members in it, then the
whole struct has a name, and so do the members within.
When I create an array, then the array does have a name, but all the
elements inside don't have names.
I think what you are trying to explain is the following:
#include<iostream>
typedef int t_arr16[16];

void foo1(int* par){
std::cout<< "sizeof:"<< sizeof(par)<< "\t typeinfo:"<<
typeid(par).name();}

void foo2(t_arr16& par){
std::cout<< "sizeof:"<< sizeof(par)<< "\t typeinfo:"<<
typeid(par).name();}

int main(){
t_arr16 arr1 ={0};
std::cout<< "Calling foo1: ";
foo1(arr1);
std::cout<< std::endl<< "Calling foo2: ";
foo2(arr1);
}

That works because an array variable can be implicitly converted to a
pointer to its element type.

Try this:
int *p =&arr1[0]; // or int *p = arr1;
foo1(p); // OK
foo2(p); // error

The output I get for
foo1(arr1); // implicit conversion from int[16] to int*
foo2(arr1); // passed as reference
foo1(p); // p is already int*
//foo2(p) error: int* cannot be converted to int(&)[16]
I was posting the code to support your argument, that static arrays can
carry information, and array-types are different from pointer-types.
Hm I don't know why you did this, but you succeeded :)
int arr1[10];

If you access the array's elements via the "arr1" identifier, you can't
use a negative index because that would be UB because your access would be
out of range. That's because "arr1" can only ever be converted to a
pointer to the *first* element (the one with the index zero) of the array.
arr1 connot be assigned to point to something else, say the second
element, because it *is not* a pointer whose value can be changed. It can
conly be *converted* to a pointer.

int *p =&arr1[1];

If you create a pointer variable, you can have it point anywhere you want,
for example somewhere in the middle of arr1. You can then use positive or
negative indices as offset to that pointer base, as long as you don't try
to access something that is not backed up by some object's storage. Of
course, interpreting the data you read from that address as an int may
still be UB.

How is it undefined behaviour?
An array is guaranteed to be a contiguous block, its completely defined in
C++ to create a non zero based array.
C++ arrays are *always* zero-based. If you access a one-dimensional
array directly via the array's identifier, then you can't use negative
indices without UB. I leave the case of multi-dimensional arrays open to
discussion. The only time you can use negative indices is with pointers
or with classes that implement operator[].

You can only emulate a non-zero based array by having a pointer point
the logical origin and then use offsets from that.
int* arr= new int[16];
/*Assume allocation succeeded*/
++arr;
arr[-1]=64;

arr[-1] is guaranteed to yield the first element of the array. It's not UB,
it's completely defined.
Right.
We're not playing word games. The terms "identifier", "name", "object",
and "array" etc. are clearly defined by the standard.
So can you tell me where the standard defines that these "names" or
"identifiers" cannot refer to more than one "object" or "entity"?
I don't have the standard, as it costs money. I'm sure someone else can
help me out here...
int x;
The actual integer object is just a a piece of memory, x is just an
identifier. So are we wrong to say x is an integer? Likewise:
int* arr = new int[16];
The actual array object is just a piece of memory, arr is just an
identifier. So are we wrong to say arr is an array?

I agree that in a programmer's everyday language, one could say "I create
a dynamic array 'arr' of 16 integers". But that does not mean that you can
close your eyes to the fact that formally, and in reality, "arr" is just a
pointer to an integer that is initialized to point to the first integer
element of some unnamed array in dynamic storage.

Of course its wrong to close your eyes to this fact, but it is even more
wrong to close your eyes to the fact that it's primarily an array.
The biggest entity here is the array , the pointer is just an intermediate
object used to identify the array. You seem to be trying to shift the foucs
so as the pointer is the the main entity, when it's not.
It's just that the formal laguange is too verbose to use it all day long.
So we use the formally incorrect short forms, where everybody knows what is
meant by it, but where also everybody knows that it is not completely
correct.

But most of the things we say is correct. You are interpreting correctnesss
as meaning "used in the same context as the standards".
Yes the standard is a refernece which defines the language and is therefore
the rules, but it is written in a context that must be interpeted correctly.

If I say, with:
int x =5;
x is an integer.
If someone "corrected" me by saying no that not strictly true because its
actually a sequence of characters, they are the ones who are incorrect for
misinterpreting(deliberately or otherwise) the context of the statement,
IMO.
I trust you will agree with the above, as it seems preety much common sense.

Now if I say an array can have a non zero based index as per:
int* arr = new arr[16];
arr++;

If someone says that's not an array it's a pointer they are incorrect
because it's both a pointer and an array.
It can't be both at the same time.
The C++ language is defined in such a way that it has the flexibility to do
this, if not I think its userbase would be a fraction of it's size. Can you
imagine what a shitty language it would be if we couldn't even create a non
zero based array, I would drop it like a brick.
You can only emulate non-zero based arrays via pointers or operator[].
It's not like ada or pascal where you can declare your array with start
index and end index. C++ only allows you to specify a number of
elements, because that's all that is needed, because the starting index
is always implicitly at zero.
Back to the old member function thing , hmm.
foo::bar() is a class scope expression, this does not imply any object.
I only wrote it that way so I can refer to 'foo' later in the sentence.
An object is:
foo f;
An member function that is part of such object is :
f.bar();

I can see it both ways too, but I don't distinctly see one as correct and
the other is not correct, both are correct in their given context.
What is incorrect is to suggest that all member functions are members or a
class but not members of an object of that class type. As obviously this
only applies to static member functions.
Can you imagine what a shitty language it would be if we couldn't have
member functions for objects? It certainly wouldn't be an OOP language in
any sense of the term.

Believe me I'm with you. You can indeed see them as members of the
object. After all they appear in the list that pops up when you type in
the dot... But it really depends on the context and in the context of
the C++ standard's terminology it is clearly wrong because the standard
says they are members of the class. This POV thing is what SG kept
trying to get across to you.

Peter
 
P

puppi

If you investigate the tcmalloc code (by Google), you will find the
following warning:

// NOTE: unsigned types are DANGEROUS in loops and other arithmetical
// places. Use the signed types unless your variable represents a bit
// pattern (eg a hash value) or you really need the extra bit. Do NOT
// use 'unsigned' to express "this value should always be positive";
// use assertions for this.

Is it just their idiom? What's the problem with using unsigned ints in
loops (it seems natural to do so)? Are C++ unsigned ints "broken"
somehow?

Unsigned integers are dangerous in DESCENDING loops due to underflow.
For instance, consider the following function, that takes an integer
array as its argument and modifies it in the following way: if n is
the number of elements in the parameter array A, then the outputted
A, for 0<=i<n, equals A+A[i+1]+A[i+2]+...+A[n-1] for their
original values. Now consider this implementation:

void sum_up(int* A, int n)
{
for(unsigned int num = n-2; num >= 0; num--)
{
A[num] += A[num+1];
}
}

That's buggy. What we intended it to do was executing from num = n-2
to 0, and then halting. But since num is unsigned, when num == 0 the
instruction num-- causes it to underflow into a very large value, and
thus num >= 0 remains true, and the loop body executes again (and
quite likely causes a segmentation fault, when A is indexed with such
a large figure). I like unsigned integers, but I always have to be
careful. I've written faulty loops such as this one more times than I
can remember...
 
P

Paul

Peter Remmers said:
Am 16.03.2011 04:52, schrieb Paul:
message
Am 15.03.2011 21:14, schrieb Paul:

message
Am 15.03.2011 19:17, schrieb Paul:

The important, practical consequence is that array size
information
is
lost as soon as the array identifier is converted into a pointer.
You
can't even get it back when the information is still available to
the
compiler:

int arr[] = {1,2,3};
int * p = arr;

sizeof(arr) == 12
sizeof(p) == 4

With your interpretation a dynamic array is not an array, which is
obvioulsy
incorrect.


An array created by 'new' is an array that has no name. Just like
with
everything that is dynamically created by new, there is no
identifier
that
directly identifies the object created on the heap. All you get is a
pointer to the object which must be stored in a pointer variable
that
you
have to provide. That pointer is not the array itself. It is a
different
object, with its own identifier and its own region of storage. This
is
obvious if you consider what sizeof() returns for the two.

Consider this:

new int[3];

This statement does not contain any identifiers, and yet an array
has
been
created on the heap. And because the pointer that new returned was
not
saved, the array is leaked. There is just no way to get hold of the
array
without an identifier. A pointer only gives you indirect access to
the
array.

The pointer is the arrays identifier.

No, it's not. An identifier is just a string of characters in the
source
code - a compile-time entity. The pointer value returned by new is a
run-time entity. This value is stored in a pointer variable, which has
an
identifier, an address (possibly in a completely different storage type
as
the array), and a value (the address of the array's first element)
which
is of course different from its own address.

This is just another example of word games the identifier is arr in
following:
int* arr = new int[16];

Yes its a pointer but it s a pointer to an array. And, as it's the only
identifier we have for the array, it's the arrays' idientifier.
A entity withiout an identifier is not a useable entity.

Of course it's usable. You do have indirect access to it via a pointer to
its members. You don't need an identifier for the array itself to use it.
Of course you need an identifier to use it. Show me how to use an array
without an identifier...

I await your response
How can one identifier be used as a name for two different objects at the
same time? The pointer's identifier cannot also be the identifier for the
array.

Ah you don;t understand that, why not hmm. Not much more i can say if you
don't ubnderstand that , its pretty simple really 1 name refers to 2
entitites

It seems you know that pointers to arrays are just pointers to arrays. You
know that you can have the pointer point to somewhere else and you know a
dynamic array is lost if you don't save the pointer value somewhere else.
Then why is it so hard to see that a dynamic array does not have a name of
itself? Just because the pointer to an array is the only means of access,
the pointer then automatically must be the identifier of the array?
Exactlly, The pointer is the only means to access the array, what don't you
understand about that?
Dude, no, it just doesn't. It stays a pointer in its own right, no matter
what it points to and no matter whether this thing it points to does have
a name or not.
When a pointer points to a dynamic array , the pointer is a means of
accessing the array the array itself is the bigger entity.
You seem to think the pointer and array are unrelated, its not a pointer in
its own right , its an an array pointer becaus eof the way it is used.

It is quite an automatism that when you don't make sense when using a word
or your usage of it suggest you think it means something different from
what it usually means, then one could think that you don't know what the
word means.
"Identifier" is not the first word.
An identifiier and a name mean the same thing to me but more specifically an
identifier is something that *****drumroll***** identifies.
int arr[10];

int *p1 =&arr[0];
int *p2 = new int[10];

Here, p1 and p2 are completely equivalent in that they both are
pointers
to int, and that they both point to the first element of a (each a
different) array of 10 ints. The difference is the way the respective
array has been created. p1 points to an array in automatic storage. p2
points to an array in dynamic storage. The array p1 points to has a
name -
embodied by the identifier "arr". p2's array does not have a name and
so
there is no identifier.
I disagree, the identifier p2 is the only identifier we have for the
array
therefore it is the identifier for both pointer and array. See above
explanation.
It's nonsensical to suggest the array has no identifier, when it does.
What you do here is say "I don't know the name of the guy on the picture,
but I do know that the name of the picture is 'Judy', so I'll have to call
the guy 'Judy' because that's the only name lying around here."

Don't be funny.
All memory is accesssed via a pointer address, thats just how computers
work. In this case p2 is the name we have to identify the array, so it
does
have a name.


Show me how to pass an array to a function without giving the array a
name.
:) I bet you can't do it, you need an identifier.
Yes, you can pass a pointer to the array's elements. That pointer does
have a name. But it's not the name of the array itself.
Hang on is there is any code here?

I SEE NO CODE

I SEE NO CODE

I SEE NO CODE.

You cannot do it.
Would this suggest dynamic arrays cannot be passed to functions, I think
not
because we can pass identifiers, which in this case happen to be
pointers.
And pointers happen not to be arrays.
Here you use identifier as if it's an object, but you were fast to
correct
me earlier by stating it is just a string of characters in source code.
Back
to the word games again.
I should have said "... nor can one object's identifier also be the other
object's identifier"
An identifer for one object can also be the identifier for another
object.
Erm. No. Each object has its own identifier, provided it has one at all.
Who says an identifier can only identify one object?
It does not seem logical to you, does it?
An array can be considered a contiguous block of different objects,
therefore any array identifier identifies numerous objects.
When I create an instance of a struct with some members in it, then the
whole struct has a name, and so do the members within.
When I create an array, then the array does have a name, but all the
elements inside don't have names.
I think what you are trying to explain is the following:
#include<iostream>
typedef int t_arr16[16];

void foo1(int* par){
std::cout<< "sizeof:"<< sizeof(par)<< "\t typeinfo:"<<
typeid(par).name();}

void foo2(t_arr16& par){
std::cout<< "sizeof:"<< sizeof(par)<< "\t typeinfo:"<<
typeid(par).name();}

int main(){
t_arr16 arr1 ={0};
std::cout<< "Calling foo1: ";
foo1(arr1);
std::cout<< std::endl<< "Calling foo2: ";
foo2(arr1);
}

That works because an array variable can be implicitly converted to a
pointer to its element type.

Try this:
int *p =&arr1[0]; // or int *p = arr1;
foo1(p); // OK
foo2(p); // error

The output I get for
foo1(arr1); // implicit conversion from int[16] to int*
foo2(arr1); // passed as reference
foo1(p); // p is already int*
//foo2(p) error: int* cannot be converted to int(&)[16]
I was posting the code to support your argument, that static arrays can
carry information, and array-types are different from pointer-types.
Hm I don't know why you did this, but you succeeded :)
int arr1[10];

If you access the array's elements via the "arr1" identifier, you can't
use a negative index because that would be UB because your access would
be
out of range. That's because "arr1" can only ever be converted to a
pointer to the *first* element (the one with the index zero) of the
array.
arr1 connot be assigned to point to something else, say the second
element, because it *is not* a pointer whose value can be changed. It
can
conly be *converted* to a pointer.

int *p =&arr1[1];

If you create a pointer variable, you can have it point anywhere you
want,
for example somewhere in the middle of arr1. You can then use positive
or
negative indices as offset to that pointer base, as long as you don't
try
to access something that is not backed up by some object's storage. Of
course, interpreting the data you read from that address as an int may
still be UB.

How is it undefined behaviour?
An array is guaranteed to be a contiguous block, its completely defined
in
C++ to create a non zero based array.
C++ arrays are *always* zero-based. If you access a one-dimensional array
directly via the array's identifier, then you can't use negative indices
without UB. I leave the case of multi-dimensional arrays open to
discussion. The only time you can use negative indices is with pointers or
with classes that implement operator[].
Nonsense in C++ arrays can be non zero based. You fail to understand that
dynamic arrays are arrays too.
You can only emulate a non-zero based array by having a pointer point the
logical origin and then use offsets from that.
int* arr= new int[16];
/*Assume allocation succeeded*/
++arr;
arr[-1]=64;

arr[-1] is guaranteed to yield the first element of the array. It's not
UB,
it's completely defined.

Right.

Yes I know its right , I've argued with bigger people than you about this 20
years ago, and I got it right then.
I don't have the standard, as it costs money. I'm sure someone else can
help me out here...

No its free.
int x;
The actual integer object is just a a piece of memory, x is just an
identifier. So are we wrong to say x is an integer? Likewise:
int* arr = new int[16];
The actual array object is just a piece of memory, arr is just an
identifier. So are we wrong to say arr is an array?

I agree that in a programmer's everyday language, one could say "I
create
a dynamic array 'arr' of 16 integers". But that does not mean that you
can
close your eyes to the fact that formally, and in reality, "arr" is
just a
pointer to an integer that is initialized to point to the first integer
element of some unnamed array in dynamic storage.

Of course its wrong to close your eyes to this fact, but it is even more
wrong to close your eyes to the fact that it's primarily an array.
The biggest entity here is the array , the pointer is just an
intermediate
object used to identify the array. You seem to be trying to shift the
foucs
so as the pointer is the the main entity, when it's not.
It's just that the formal laguange is too verbose to use it all day long.
So we use the formally incorrect short forms, where everybody knows what
is
meant by it, but where also everybody knows that it is not completely
correct.

But most of the things we say is correct. You are interpreting
correctnesss
as meaning "used in the same context as the standards".
Yes the standard is a refernece which defines the language and is
therefore
the rules, but it is written in a context that must be interpeted
correctly.

If I say, with:
int x =5;
x is an integer.
If someone "corrected" me by saying no that not strictly true because its
actually a sequence of characters, they are the ones who are incorrect
for
misinterpreting(deliberately or otherwise) the context of the statement,
IMO.
I trust you will agree with the above, as it seems preety much common
sense.

Now if I say an array can have a non zero based index as per:
int* arr = new arr[16];
arr++;

If someone says that's not an array it's a pointer they are incorrect
because it's both a pointer and an array.
It can't be both at the same time.
The C++ language is defined in such a way that it has the flexibility to
do
this, if not I think its userbase would be a fraction of it's size. Can
you
imagine what a shitty language it would be if we couldn't even create a
non
zero based array, I would drop it like a brick.
You can only emulate non-zero based arrays via pointers or operator[].
It's not like ada or pascal where you can declare your array with start
index and end index. C++ only allows you to specify a number of elements,
because that's all that is needed, because the starting index is always
implicitly at zero.
You don't understand C++ arrays. If you don't understand I cant explain it
anymore.

I only wrote it that way so I can refer to 'foo' later in the sentence.


Believe me I'm with you. You can indeed see them as members of the object.
After all they appear in the list that pops up when you type in the dot...
But it really depends on the context and in the context of the C++
standard's terminology it is clearly wrong because the standard says they
are members of the class. This POV thing is what SG kept trying to get
across to you.
You're not "with me " at all . You are a million miles behind me LOL You
seem brainwashed to have tthis single track narrow mind view of everything..

My television has two wires coming out of the back. A signal cable and a
power cable, both cables carry electricity, and both cables can be called
electric cables.
One cable however carries analogue or digital signals and is more
specifically a frequency carrier. You don't uderstand the complexities
because in your mind both are simply eletricity cables and not signal
cables.
You have lost all sense of connection between electriicty and signal.
Same as you lost connection between class and object
Same as you lost connection between pointer and array

I don't know if you are brainwashed or what but I certainly don't like the
way you think about C++, I think you do not fully understand the language.

GL.
 
P

Paul

Leigh Johnston said:
You are too dim to see the pattern that *everybody* who replies to your
posts disagrees with you; and the number of people that make up
*everybody* is growing daily. Occam's Razor tells us that the reason for
this is probably due to *you* being incorrect rather than everybody else.
No its just that nobody else can be bothered arguing with you about this
again. Because we argued about it already a few week ago, where most of the
experts disagree with you.
WHich is why I cant be bothered arguin with you anymore either.

In C++ a pointer is not an array; an array is not a pointer (an array can
be converted to a pointer).
In C++ negative array indices are UB.
In C++ a member function is a member of a class not a member of an object.

HTH.
So you seem to think :)
 
S

SG

Of course you need an identifier to use [the array].

*An* identifier. For example, an identifier that denotes the pointer
variable that stores the address of some of the array's element.
Show me how to use an array without an identifier...

You alreadey provided an example for this.
[...] its pretty simple really 1 name refers to 2 entitites

It's pretty simple really. One name within some scope either denotes
exactly one object (for example: a pointer variable), exactly one
type, exactly one class template, ..., or one *or more* functions or
function templates (since C++ allows overloading of functions).
[...]
the array itself is the bigger entity.

The array itself is *another* entity which doesn't have to have a
name.

int arr[] = {70,85,80,33,0};
int *p = arr;

p arr
+---+ +---+---+---+---+---+
| *------>| 70| 85| 80| 33| 0 |
+---+ +---+---+---+---+---+


'arr' is the name of the array. 'p' is the name of the pointer. That's
about it. If you write

int* p = new int[5];

p
+---+ +---+---+---+---+---+
| *------>| ? | ? | ? | ? | ? |
+---+ +---+---+---+---+---+

The array "p points to" has no name. You can refer to array elements
with an *expression* like p[3] (indirection). But this expression is
not an identifier since [ and ] are not valid identifier characters
and p is still an identifier that denotes a pointer variable.

SG
 
P

Paul

Leigh Johnston said:
There are only two possible conclusions that one can reach based on your
response:

1) You are a liar (and therefore a troll).
2) You are deluded.

Please choose one and tell us what it is.

If it is (2) you should either see your doctor or if you lack the insight
to accept that you are deluded (probably the case) then you should
probably be sectioned so you can receive the appropriate medical care.
int* arr = new int[16];

int[0] = 1;
This is an array expression whether you like it or not , you cannot
understand this simple fact because you are an idiot.

|Now goodbye and please stop responding to my posts as I don't like speaking
with idiots
 
P

Paul

SG said:
Of course you need an identifier to use [the array].

*An* identifier. For example, an identifier that denotes the pointer
variable that stores the address of some of the array's element.
Show me how to use an array without an identifier...

You alreadey provided an example for this.
[...] its pretty simple really 1 name refers to 2 entitites

It's pretty simple really. One name within some scope either denotes
exactly one object (for example: a pointer variable), exactly one
type, exactly one class template, ..., or one *or more* functions or
function templates (since C++ allows overloading of functions).
[...]
the array itself is the bigger entity.

The array itself is *another* entity which doesn't have to have a
name.

int arr[] = {70,85,80,33,0};
int *p = arr;

p arr
+---+ +---+---+---+---+---+
| *------>| 70| 85| 80| 33| 0 |
+---+ +---+---+---+---+---+


'arr' is the name of the array. 'p' is the name of the pointer. That's
about it. If you write

int* p = new int[5];

p
+---+ +---+---+---+---+---+
| *------>| ? | ? | ? | ? | ? |
+---+ +---+---+---+---+---+

The array "p points to" has no name. You can refer to array elements
with an *expression* like p[3] (indirection). But this expression is
not an identifier since [ and ] are not valid identifier characters
and p is still an identifier that denotes a pointer variable.
int* arr = new int[16];

int[0] = 1;
This is an array expression, if you can't understand the basics you are
obviously an idiot and i do not wish to converse with idiots .
Goodbye and do not respond to my posts until you understand the basics.
 
P

Paul

Leigh Johnston said:
Leigh Johnston said:
Please choose one and tell us what it is.

If it is (2) you should either see your doctor or if you lack the
insight to accept that you are deluded (probably the case) then you
should probably be sectioned so you can receive the appropriate
medical care.
int* arr = new int[16];

int[0] = 1;
This is an array expression whether you like it or not , you cannot
understand this simple fact because you are an idiot.

No it is a syntax error. If you meant:

arr[0] = 1;

then arr[0] is pointer arithmetic as arr is a pointer not an array; see
SG's reply else thread where he helpfully includes diagrams to explain the
fundamental concepts to you.
Like i really give a fuc what I am typiong to you? I just batter the keypad
and deny anything you say now because I dislike you sso much.
You are an idiot and not even a very nice idiot.
 
M

MikeP

Paul said:
<prune>
Just to add my tuppence worth :

Some of the arguments for unsigned are not valid arguments, such as
the "array index can never be negative" argument.
As has been proven else-thread an array index can be negative.
This leads me to believe that the people who suggest this do not have
a very good understanding of the language, and are therefore not
ideally suited to always make the best judgment .

Solution-focused programmer says:

An array is a container. A container can be either empty or have
elements. Hence, an unsigned integer type would be the best
representation of the count of objects in the array and for the index
value to retrieve a specific object.

Language-focused programmer says:

An "array" in C++ is <definition of "array" from C++ standard here>...
Because arrays and pointers.... but not if with GCC option -job_security
set or on a 2s-complement machine with 1 bit removed from your left
fingernail (unless of course cross-compiling on an ACME 5000, using the
popular stack-hack with instruction patch applied to the unoptimized
executable). Hence, signed is the best representation of the count of
objects in the array and for the index value to retrieve a specific
object.

:)
 
S

SG

SG said:
[...]

 int arr[] = {70,85,80,33,0};
 int *p = arr;

   p        arr
 +---+     +---+---+---+---+---+
 | *------>| 70| 85| 80| 33| 0 |
 +---+     +---+---+---+---+---+

'arr' is the name of the array. 'p' is the name of the pointer. That's
about it. If you write

 int* p = new int[5];

   p
  +---+     +---+---+---+---+---+
  | *------>| ? | ? | ? | ? | ? |
  +---+     +---+---+---+---+---+

The array "p points to" has no name. You can refer to array elements
with an *expression* like p[3] (indirection). But this expression is
not an identifier since [ and ] are not valid identifier characters
and p is still an identifier that denotes a pointer variable.

int* arr = new int[16];

int[0] = 1;

you mean arr[0].
This is an array expression,

I see you shifted from "array identifier" to "array expression" this
time. Keep in mind that in the context of the C++ ISO standard, these
terms are not interchangable.

I think we can agree on

'arr[0] = 1' is

- an assignment expression
(the top level node in the syntax tree would be an assignment)
- an expression that refers to some int object
(an lvalue expression of type int, to be precise)
- an expression involving pointer arithmetics
(hidden behind the [] operator)
- an expression that assigns the value 1 to the object the
pointer called 'arr' is pointing to.

I would not say that it's "an array expression" because "array
expression" is somewhat open to interpretation. I see how you would
say "array expression" in a *different context* given that the
expression makes use of [] which is typically used in combination with
arrays. But "array expression" in the C++ ISO standard context would
probably be understood as a shortcut for "expression referring to an
array". But the expression does not refer to an array. The expression
refers to a single int object in this case. This int object is a
subobject of the array, though.
if you can't understand the basics
you are [...] an idiot [...]

That's a reasonable statement. Although, there might be other
explanations for why someone does not understand something. For
example, maybe this someone just read a bad C++ book, invented his/her
own terminology/mental model and just has trouble of letting go.

Anyhow, this statement of yours is a logical implication:

X is true ==> Y is true

with
X = SG cannot understand the basics
Y = SG is an idiot.

Now, consider the possibility that Y is false and solve for X.

SG
 
J

Joel C. Salomon

Christian said:
William Ahern ha scritto:

Using a type that can produce negative numbers is the easiest and least
error-prone way to catch such bugs when clients of your code pass signed
numbers to your functions expecting positive numbers.

void libraryFunction(unsigned number)
{
assert(number >= 0); // always true, does not check precondition
}

void libraryFunction(int number)
{
assert(number >= 0); // OK
}

Is libraryFunction() meaningful for number > INT_MAX?

If yes, why restrict it to signed?

If no, then

void libraryFunction(unsigned number) {
assert(number >= 0); // always true, does not check precondition
assert(number <= MAX_MEANINGFUL_VALUE); // negative values caught en passant
}

should be fine.

--Joel
 
N

Noah Roberts

<prune>
Just to add my tuppence worth :

It seems to me that you might be putting too much value on your
misinformed opinions. I know I wouldn't give you a tuppence for it. A
tuppence for you to keep it to yourself maybe...
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads


Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,055
Latest member
SlimSparkKetoACVReview

Latest Threads

Top