1

At the end of the following code, is x always equal to 0 ? Or is it an example of undefined behaviour ?

unsigned long int x = 0;
--x;
++x;

Note: C++98 context. For some (good) reason, I can't use C++11.

Why this question ?

I have to go through a container, index by index, removing some elements. I would like to implement it with the following:

MyContainerWithoutIterators c;
//...
for(unsigned long int i = 0; i < c.size(); ++i)
{
  if(i_have_to_remove(c[i]))
  {
    c.removeAtIndex(i);
    --i; // counterbalance incrementation of the loop
  }
}

Note: I know I can do the following, I just want to know if I can use the previous implementation.

MyContainerWithoutIterators c;
//...
for(unsigned long int i = 0; i < c.size();)
{
  if(i_have_to_remove(c[i]))
    c.removeAtIndex(i);
  else
    ++i;
}
Caduchon
  • 4,574
  • 4
  • 26
  • 67
  • 1
    Unsigned overflow is well-defined. Signed overflow is not, but you don't have it in your example. – HolyBlackCat May 19 '17 at 13:24
  • 1
    why not just use a signed number? Do you actually need the extra space of unsigned? – twain249 May 19 '17 at 13:25
  • 1
    @twain249 I guess c.size() returns unsigned so index needs to be unsigned too to avoid warnings – user3528438 May 19 '17 at 13:26
  • 1
    @twain249 : maybe... `c.size()` is a `unsigned long int`. And also for consistency : I always use unsigned variables to be an index. – Caduchon May 19 '17 at 13:27
  • You better use iterators – Slava May 19 '17 at 13:27
  • Also since your question is about unsigned variable, you should edit your to reflect suh. – user3528438 May 19 '17 at 13:27
  • @Slava : Implement iterators able to support erasing on my own container is not easy. – Caduchon May 19 '17 at 13:29
  • Why do use your own container first of all – Slava May 19 '17 at 13:31
  • @Slava : is it really the question here ??? Yes, I have good reason to use my own container. – Caduchon May 19 '17 at 13:34
  • @HolyBlackCat There is no such thing as unsigned overflow. Unsigned integers implement arithmetic in Z mod 2^NumBit and can thus represent any integer by picking the representative of its equivalence class that lies in [0, 2^NumBit - 1]. – Baum mit Augen May 19 '17 at 13:36
  • For your usage, look at [erase remove idiom](https://en.wikipedia.org/wiki/Erase%E2%80%93remove_idiom) – Jarod42 May 19 '17 at 13:37
  • Putting underflow aside I would say that solution is unreadable and dangerous. This is subjective but anyway. – Slava May 19 '17 at 13:38
  • @Jarod42 he does not use standard container. – Slava May 19 '17 at 13:38
  • @BaummitAugen Do you have any reference for it? Wikipedia [says](https://en.wikipedia.org/wiki/Integer_overflow) that unsigned wrap-around is also an "overflow". – HolyBlackCat May 19 '17 at 13:51
  • 2
    @HolyBlackCat 3.9.1/4 in N4141: *"Unsigned integers shall obey the laws of arithmetic modulo 2^n where n is the number of bits in the value representation of that particular size of integer."*, and corresponding footnote 48: *"This implies that unsigned arithmetic does not overflow because a result that cannot be represented by the resulting unsigned integer type is reduced modulo the number that is one greater than the largest value that can be represented by the resulting unsigned integer type."* Tl;dr: Don't trust Wikipedia on C++ related stuff. – Baum mit Augen May 19 '17 at 13:55
  • @BaummitAugen Good to know, thanks. – HolyBlackCat May 19 '17 at 13:58
  • You hit upon the exact reason why -1u is equal to UINT_MAX--because unsigned subtraction is defined as the inverse of unsigned addition. It has nothing to do with two's-complement representation beyond the fact that the latter is conveniently defined as using the same bit patterns. – supercat May 19 '17 at 16:10

0 Answers0