Unsigned types are DANGEROUS??

P

Paul

Leigh Johnston said:
Noah Roberts said:
On 3/14/2011 5:39 PM, Paul wrote:

An array identifier *is* a pointer.

This is false.

int x[] = {1,2,3};

^^ x is an identifier, it identifies an array, but x is not a pointer.
Not much more to say there; it simply is not so. The type of x is
int[3], not int*.
You are confused between an array and an array-type.
int* p_x = new int[32];
An array identifier is a pointer.

A pointer can point to an array; a pointer is not an array; pretty simple
idea IMO, shame you are unable to grasp it.
This word is not that word. shame you cannot understand that.
 
P

Paul

Leigh Johnston said:
Leigh Johnston said:
On 15/03/2011 08:29, Paul wrote:

On 15/03/2011 00:49, Paul wrote:

On 14/03/2011 23:26, Paul wrote:

On 14/03/2011 19:30, Alf P. Steinbach /Usenet wrote:
* MikeP, on 14.03.2011 18:49:
MikeP wrote:
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?

Well that's a relief. Now that I've read the thread posts and
the
links
to other threads, I see I have not been doing anything wrong by
preferring unsigned where it seems natural to do so. The biggie
points
(for me) are:

1. C++ conversion rules are at the core of the problem.

Yes, right.

Another core issue is monkey-see-monkey-do habits & ideas, that
is,
habits & ideas that are not founded in real understanding but are
just
mindlessly adopted from some other context where they *are*
meaningful.

I.e., that what's meaningful in e.g. Pascal (guaranteed range
checking,
advantage) isn't meaningful in C++ (guaranteed lack of range
checking,
disadvantage of adopting Pascal habits & ideas).


2.Mixing signed/unsigned inadvertently is not that big of a
problem
given
that most compilers emit a warning upon such.

This is, however, wrong.

Particularly so since the Google coder's note speaks of
"arithmetical
places".

Compilers generally warn about comparisions between signed and
unsigned,
but can't warn you of equally-or-more dangerous arithmetic
constructs.


3. Using signed where unsigned is a better fit, loses semantic
value.

Yes, right.

And it's even worse: using signed where unsigned is a better fit
(namely
for bit-level operations), can easily yield Undefined Behavor.

And vice versa, using unsigned where signed is a better fit
(namely
for
numerical stuff) loses semantic value and can far too easily
introduce
bugs.

Bullshit. The concept of a value which is never negative is not
orthogonal to "numerical stuff"; unsigned integral types are not
just
for bitwise operations: std::size_t is not normally used in
bitwise
operations but it is nevertheless an unsigned integral type.

It's not bullshit, it's a valid opinion that many people agree
with.
Your concept of a value which is never negative is not
necessarily the
same as everyone elses, for example you think an array can never be
negative but it can be.

double* arr = new double[3];
++arr;
arr is the name/identifier that is used to access the array object.
It's perfectly acceptable to offset the pointer to access the array
with
non-zero based indexing. Many algorithms and mathematical functions
benefit from this type of functionality.
You attempt to say the C++ standards disallows this is an attempt
to
twist the wording to support your own argument.

If you cannot understand the benefits of non-based array indexing,
then
I suggest you are a complete idiot because I'm pretty sure you
unreasonably trying to twist things to suit your argument. And if
you
really do think an array cannot be non-zero based then you are a
complete idiot.


Keep up: we have already come to the conclusion that negative C++
array indices are UB; C++ array indexing and pointer arithmetic
*within* an array are not necessarily semantically identical as a
pointer to an array element is not equivalent to an array unless
it is
pointing to the first array element and as evidenced by the
behaviour
exhibited by various versions of g++.

From the C++ standard:
"The expression E1[E2] is identical (by definition) to *((E1)+(E2))."

Give up , you've failed.


From the C++ standard:

"if E1 is an array and E2 an integer, then E1[E2] refers to the E2-th
member of E1"

I've failed? Obviously not. You've failed? Of course.

You obviously seem to think that says something other than it does. It
has already been proved by others that your quote is inaccurrate. Yes
you failed go back to bed.

What has been proven by others exactly? How can a verbatim quote be
inaccurate? It is either a quote or it isn't. Fool.

Others agree with me that negative C++ array indices are UB.
I think you mean "other" singular. If he thinks this then he is also
wrong , it's not UB to offset a pointer to an array:
"The expression E1[E2] is identical (by definition) to *((E1)+(E2))."
The C++ standard defines array indexing as pointer offsetting. I guess
the C++ standard itself is producing UB in your mind. Get a grip you
idiot.

From the C++ standard:

"if E1 is an array and E2 an integer, then E1[E2] refers to the E2-th
member of E1"

E1[-1] can not be a member of E1.
Yes it can:
int* E1 = new int[16];
++E1;
E1[-1] = 1;
An array is not a pointer; an array is an array and a pointer is a
pointer; pretty simple eh?
Yes it is simple , see above code.

You are obviously trying to twist the context of the C++ standard to suit
your argument. The whole paragrpah says this:

"Except where it has been declared for a class (13.5.5), the subscript
operator [] is interpreted in such a way
that E1[E2] is identical to *((E1)+(E2)). Because of the conversion rules
that apply to +, if E1 is an
array and E2 an integer, then E1[E2] refers to the E2th
member of E1. Therefore, despite its asymmetric
appearance, subscripting is a commutative operation."

Your definition that an array is not a pointer seems to be in direct
conflict to the C++ standard, which clearly says its identical.

Also your interpretation makes no sense because according to your
interpetation the following would be the first element in an array, which is
clearly wrong:
int* E1 = new int[16];
E1[1]; /*This is the 2nd element not the 1st.*/
 
M

Michael Doubez

On 14 mar, 15:20, SG wrote:
Yes, I think this is a bit of a gray area. Avoid it if you can. If I
recall correctly, pointer arithmetic is restricted to stay inside some
array (including "one element past the end"). Here, n is an array of
arrays. n[1] selects the second array and the additional [-1] steps
out of that 2nd array. If I recall correctly, James Kanze talked about
a possible debugging implementation which would augment pointers to
store additional information to enable runtime checking of index-out-
of-bounds conditions w.r.t. pointer arithmetic and op[]. IIRC, he
claimed this implementation to be conforming. But it would obviously
"break" your example.
An implementation storing data before or after each array would be
problematic indeed.
It would also break n[1][1] == (&n[0][0])[3] which would be
surprising.

I think you misunderstood. I was talking about the possibility of an
implementation that makes raw pointers more intelligent for debugging
purposes.

OK. I am not sure it would be a problem. The complete object can be
taken into account for the computation of the bounds (depending on the
interpretation of the standard conforming bounds).

[snip]
I could not find a guarantee of continuity of the layout in the
standard to back up that claim and, to my untrained eye, it carefully
steps around the issue.

Well, it would surprize me if sizeof(T[N])==N*sizeof(T) was not
satisfied. But I am not aware of any such guarantee, either.
[...]
Which tends to hint that E1 is however converted into a pointer and no
special treatment is performed because E1 is of array type. In this
case, I expect normal pointer arithmetic applies and a negative
integral part of the subscript operator is acceptable provided you
stay within the underlying object.

As I said, IIRC James Kanze claimed this to be "formally U.B.".

Yes, it seems the standard relies on recursion which would makes
negative integral part of array, formally UB.

But is this also UB ?
(&(n[1][0]))[-1]

In this case, (&(n[1][0])) has type pointer to T and is no longer an
array.
 
M

MikeP

Leigh said:
Hint: use typedef just like the standard library does (e.g.
container::size_type). typedef is ideal for creating abstractions
based on particular built-in types.

It takes a wrapper though, to get a behavioral change.
 
M

MikeP

Paul said:
I notice you did not respond to this. I wonder if you have a reason
why you think unsigned is better in loop counter, or you just like it
better.
Nor to this. I cannot help notice you give no reasoning, I wonder why
this is.

3. Indices.
Indices can be negative, unless a container class has defined it
otherwise. What advantage comes with using unsigned for indices?

The language default for integer literals is signed, so if you code
arr[1];
The expression is implicitly converted to *((arr pointer)+(integer
with value of 1)).
If this is the case doesn't it seem better to stick to the same type
as the languages default?
Again you have not responded to this either, do you actually have any
*reasons* for prefferring unsinged integers in these specific cases,
other than you just like them better?

Well that's a start. Now about 200 more posts from a number of
people and we'd have a start to something workable. A thousand
tidbits spread all over the internet do not make a comprehensive or
objective document. Or maybe you want to compose one? And maybe
Leigh can compose another one and still another can combine the two.
Back-n-forth banter is unproductive. There is the option to avoid
"brain-damaged" language constructs
altogether, which no one has brought up.
What is a brain-damaged language construct? lol
I don't know what you mean by this, do you think it is brain-dead to
use array indices other than zero-based?
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 it seems no language is perfect.

Meaning, at this point I have begun wondering what I would want in a
low-level type system if it were made from scratch and good information
on the topic would be a nice to have. I suggested a comprehensive and
objective analysis of the issues that have only been touched on the
surface by this thread be created by anyone(s) so inclined. I have no
intention of getting into the catfight here.
 
P

Paul

Leigh Johnston said:
From the C++ standard:

"if E1 is an array and E2 an integer, then E1[E2] refers to the E2-th
member of E1"

E1[-1] can not be a member of E1.
Yes it can:
int* E1 = new int[16];
++E1;
E1[-1] = 1;

E1 is not an array; E1 is a pointer.
It is an array identifier , which is a pointer. And the behaviour is well
defined.

If you can't accept this is an array then obviously you're an idiot
plonk.
 
S

SG

Yes it can:
int* E1 = new int[16];
++E1;
E1[-1] = 1;
E1 is not an array; E1 is a pointer.

It is an array identifier, [...]

And what is the "context" in which this sentence makes sense to you
this time? It can't be ISO/IEC 14882, can it? Let's find out...

2.10/1:
"An identifier is arbitrarily long sequence of letters and
digits. [...]"

3/3:
"An entity is a value, object, subobject, base class subobject,
array element, variable, function, instance of a function,
enumerator, type, class member, template, or namespace."

3/4:
"A name is a use of an identifier (2.10) that denotes an entity
or label (6.6.4, 6.1). A variable is introduced by the
declaration of an object. The variable’s name denotes the
object."

So, E1 is an *identifier* that is *used* as *name* for a *pointer
variable*. Nobody denies the fact that a pointer can point to an
element of an array. But saying that E1 is an "array identifier" seems
like quite a stretch to me. It just invites the language lawyers to
disagree with you once more.

SG
 
P

Paul

Yes it can:
int* E1 = new int[16];
++E1;
E1[-1] = 1;
E1 is not an array; E1 is a pointer.

It is an array identifier, [...]

And what is the "context" in which this sentence makes sense to you
this time? It can't be ISO/IEC 14882, can it? Let's find out...

2.10/1:
"An identifier is arbitrarily long sequence of letters and
digits. [...]"

3/3:
"An entity is a value, object, subobject, base class subobject,
array element, variable, function, instance of a function,
enumerator, type, class member, template, or namespace."

3/4:
"A name is a use of an identifier (2.10) that denotes an entity
or label (6.6.4, 6.1). A variable is introduced by the
declaration of an object. The variable’s name denotes the
object."

So, E1 is an *identifier* that is *used* as *name* for a *pointer
variable*. Nobody denies the fact that a pointer can point to an
element of an array. But saying that E1 is an "array identifier" seems
like quite a stretch to me. It just invites the language lawyers to
disagree with you once more.

SG

xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

What nonsense are you blabbing on about ?
 
S

SG

SG said:
Paul said:
Yes it can:
int* E1 = new int[16];
++E1;
E1[-1] = 1;
E1 is not an array; E1 is a pointer.
It is an array identifier, [...]

And what is the "context" in which this sentence makes sense to you
this time? It can't be ISO/IEC 14882, can it? Let's find out...

2.10/1:
"An identifier is arbitrarily long sequence of letters and
digits. [...]"

3/3:
"An entity is a value, object, subobject, base class subobject,
array element, variable, function, instance of a function,
enumerator, type, class member, template, or namespace."

3/4:
"A name is a use of an identifier (2.10) that denotes an entity
or label (6.6.4, 6.1). A variable is introduced by the
declaration of an object. The variable’s name denotes the
object."

So, E1 is an *identifier* that is *used* as *name* for a *pointer
variable*. Nobody denies the fact that a pointer can point to an
element of an array. But saying that E1 is an "array identifier" seems
like quite a stretch to me. It just invites the language lawyers to
disagree with you once more.

What nonsense are you blabbing on about?

In case you are interested in understanding what I said above, feel
free to ask questions that are more specific than that.

SG
 
N

Noah Roberts

Noah Roberts said:
An array identifier *is* a pointer.

This is false.

int x[] = {1,2,3};

^^ x is an identifier, it identifies an array, but x is not a pointer.
Not much more to say there; it simply is not so. The type of x is
int[3], not int*.
You are confused between an array and an array-type.
Nope.

int* p_x = new int[32];
An array identifier is a pointer.

p_x is indeed a pointer in your example. It is not an array identifier.
What your misconception is probably based upon is the way that arrays
*convert to* pointers implicitly.
"The expression E1[E2] is identical (by definition) to *((E1)+(E2))."
It can't be any clearer.

True. But it doesn't say what you want it to either. Array identifiers
are implicitly convertible to pointers of type T* where T is the element
type.
Type info is carried around with arrays , as you've just demonstrated,
arrays are passed around as pointers.

Interesting. You see the difference but won't admit the difference.
So nothing new there.



I don't know what you define an "important practical consequence" to be
but you obviously think you have shown one.

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
It doesn't? oh glad you told me then :)
It's just too bad you're not getting it. Then again, maybe you are and
just don't want to publicly admit to error. An understandable position.
 
N

Noah Roberts

Now I KNOW you're not trying or about to try to convince me to change my
programming style to the way YOU prefer it. Are you? I see no compelling
reason to change it having read the pertinent threads. Change languages
eventually? Maybe. But programming style? Nah. I'm more apt to wrap the
primitive types to get nicer semantics than I am to just grin and bear
the language's shortcomings.

"Who said it" surely does not affect how I evaluate technical
information. I assess it for its technical merit and how it applies to my
projects. "Who says it" never factors into the process (OK, maybe a
little bit, but I'm more likely to keep an eye out for who is "in the
box" saying something and who is "out of the box" so I know how much salt
to use with the information, rather than anything else). Qualification
via name-dropping raises a red flag to me.

Although I agree that Kanze far to often relies on argument by
authority, and can be more than a little arrogant (only those agreeing
are "experts", dismissing other experts like Alexandrescu as academics)
but I can't say I understand your distinction between "language lawyers"
and "application programmers". It seems to me that, for good or bad, a
C++ developer really needs to be both.
 
N

Noah Roberts

Yes it can:
int* E1 = new int[16];
++E1;
E1[-1] = 1;
E1 is not an array; E1 is a pointer.

It is an array identifier, [...]

And what is the "context" in which this sentence makes sense to you
this time? It can't be ISO/IEC 14882, can it? Let's find out...
[ ample primary source quotations ]
SG

xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

What nonsense are you blabbing on about ?

Wow. OK. This noob is obviously a complete loon.
 
M

MikeP

Noah said:
Although I agree that Kanze far to often relies on argument by
authority, and can be more than a little arrogant (only those agreeing
are "experts", dismissing other experts like Alexandrescu as
academics) but I can't say I understand your distinction between
"language lawyers" and "application programmers". It seems to me
that, for good or bad, a C++ developer really needs to be both.

Just pointing out that I think programmers tend to lean more one way or
the other. Fitting for this thread (or so I think) because one's
preferred programming style reflects which they are: more tool-focused or
more solution-focused. In this thread topic case, the latter type is apt
to choose a more solution-focused semantic style (unsigned) even at some
compromise while the former is likely to choose the opposite (signed)
style. I don't understand why some people see one way or the other as
inherently wrong and thereby want to persuade someone else to change to
their style. Maybe some of the above thoughts will help them.
 
P

Paul

Noah Roberts said:
Noah Roberts said:
On 3/14/2011 5:39 PM, Paul wrote:

An array identifier *is* a pointer.

This is false.

int x[] = {1,2,3};

^^ x is an identifier, it identifies an array, but x is not a pointer.
Not much more to say there; it simply is not so. The type of x is
int[3], not int*.
You are confused between an array and an array-type.
Nope.

int* p_x = new int[32];
An array identifier is a pointer.

p_x is indeed a pointer in your example. It is not an array identifier.
What your misconception is probably based upon is the way that arrays
*convert to* pointers implicitly.
"The expression E1[E2] is identical (by definition) to *((E1)+(E2))."
It can't be any clearer.

True. But it doesn't say what you want it to either. Array identifiers
are implicitly convertible to pointers of type T* where T is the element
type.
Type info is carried around with arrays , as you've just demonstrated,
arrays are passed around as pointers.

Interesting. You see the difference but won't admit the difference.
So nothing new there.



I don't know what you define an "important practical consequence" to be
but you obviously think you have shown one.

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.
 
N

Noah Roberts

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.

Can't imagine why you think that since you aren't explaining yourself.
A dynamically allocated array is as much an array as an automatic or
static storage array. The standard text is quite specific about the
issue (see 5.3.4/5), including being quite specific about the fact that
the new-expression used to create one returns a **pointer**.
 
P

Paul

SG said:
Paul said:
Yes it can:
int* E1 = new int[16];
++E1;
E1[-1] = 1;
E1 is not an array; E1 is a pointer.
It is an array identifier, [...]

And what is the "context" in which this sentence makes sense to you
this time? It can't be ISO/IEC 14882, can it? Let's find out...

2.10/1:
"An identifier is arbitrarily long sequence of letters and
digits. [...]"

3/3:
"An entity is a value, object, subobject, base class subobject,
array element, variable, function, instance of a function,
enumerator, type, class member, template, or namespace."

3/4:
"A name is a use of an identifier (2.10) that denotes an entity
or label (6.6.4, 6.1). A variable is introduced by the
declaration of an object. The variable’s name denotes the
object."

So, E1 is an *identifier* that is *used* as *name* for a *pointer
variable*. Nobody denies the fact that a pointer can point to an
element of an array. But saying that E1 is an "array identifier" seems
like quite a stretch to me. It just invites the language lawyers to
disagree with you once more.

What nonsense are you blabbing on about?

--In case you are interested in understanding what I said above, feel
--free to ask questions that are more specific than that.

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?

Why do you suggest the buck stops at the pointer which is simply used an
array identifier. Or are you just trying to make this case to support
their/your argument?
The fact that the identifier is a pointer goes without saying , as does the
fact that its name is p_name. The entity is an array structure, you seem to
think otherwise, why I don't understand.
 
P

Paul

Noah Roberts said:
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.

Can't imagine why you think that since you aren't explaining yourself. A
dynamically allocated array is as much an array as an automatic or static
storage array. The standard text is quite specific about the issue (see
5.3.4/5), including being quite specific about the fact that the
new-expression used to create one returns a **pointer**.

So what don't you uderstand about that?
One post you say an array identifier is not a pointer and the next post you
say it is. ( Or you post a quote from the standard that states it is a
pointer). You are totally confused.

shrugg.
 
N

Noah Roberts

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 confusion is there. The entity that p_name identifies in this case
is a pointer, NOT the dynamically created array. Proof of point:

type * p_name = new type[16];
type name;
p_name = &name;

You can't do that with arrays.
The fact that the identifier is a pointer goes without saying ,

No, the *entity* is. Pointers are entities.
as does
the fact that its name is p_name.

And the name forms an identifier.
The entity is an array structure, you
seem to think otherwise, why I don't understand.

Because it's simply the case that it is true.
 
N

Noah Roberts

So what don't you uderstand about that?
One post you say an array identifier is not a pointer and the next post
you say it is. ( Or you post a quote from the standard that states it is
a pointer). You are totally confused.

Not as much as you are it seems.
 

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,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top