0

Does this code do anything?

int *n;
while (n!=0)
    {
        n = &n;
    }
Trott
  • 66,479
  • 23
  • 173
  • 212
Syntax_Error
  • 5,964
  • 15
  • 53
  • 73
  • 2
    Try it and find out. Even better, try reading the standard and figure it out. – Stephen Canon Mar 29 '11 at 21:14
  • My compilers refuses to compile it, even if I add the missing stuff. – pmg Mar 29 '11 at 21:17
  • 1
    @pmg:: Bad Compiler you got... – Sadique Mar 29 '11 at 21:17
  • @Stephan: i got it as a question, and I should really answer it without abiding by standards and executing...by the looks it seems to search alternating places in memory for a value of zero, just wanted to get ur input! – Syntax_Error Mar 29 '11 at 21:17
  • @Syntax, you *can't* answer it by analyzing, since the very nature of undefined behavior means different compilers behave differently. – Matthew Flaschen Mar 29 '11 at 21:19
  • 1
    @Syntax_Error "by the looks it seems to search alternating places in memory for a value of zero" No, it doesn't seem to be doing any such thing. Look harder, and try to grasp the difference between `&n`, which is a constant, and `*n`, which accesses memory. – Jim Balter Mar 30 '11 at 00:41
  • @Matthew That's utter nonsense that confuses language lawyering with reality. UB simply means that the C standard does not define what a conforming implementation will do; *as far as the standard is concerned*, a conforming implementation can do anything. That doesn't mean that actual implementations might do anything. I served on X3J11 and I find it appalling how the standards language that we carefully crafted has been abused and misinterpreted. – Jim Balter Mar 30 '11 at 00:50
  • @Jim, I stand by my comment. You can't decide what it will do in the abstract. It *will* be completely different depending on, for instance, whether the compiler chooses to 0-initialize n. At most you can enumerate certain possibilities like Jared did in his answer. – Matthew Flaschen Mar 30 '11 at 01:38
  • @Matthew "enumerate certain possibilities" IS "analyzing". Your "stand by my answer" is what Quine criticizes at http://courseware.ee.calpoly.edu/~jbreiten/quotes.html – Jim Balter Apr 03 '11 at 02:49

7 Answers7

6

It's undefined behavior for several reasons, so who knows.

  1. It uses n before initialization.
  2. It repeatedly assigns a int ** value to a int * variable.

So it might trigger the Singularity... but only on your machine.

Matthew Flaschen
  • 278,309
  • 50
  • 514
  • 539
  • 1
    @Martin, as you wish. C99 (with Corrigenda) §J. 2 (Undefined Behavior): "— The value of an object with automatic storage duration is used while it is indeterminate (6.2.4, 6.7.8, 6.8)." – Matthew Flaschen Mar 29 '11 at 21:26
  • 1
    @Martin - the C spec explicitly says "The value of an object with automatic storage duration is used while it is indeterminate" in its list of undefined behaviour. – Carl Norum Mar 29 '11 at 21:27
  • @Martin: See [this question](http://stackoverflow.com/questions/4259885/why-do-i-see-strange-values-when-i-print-uninitialized-variables), in which I give the technicalities in my answer for why it's UB in C++. – GManNickG Mar 29 '11 at 21:38
4

No this does nothing particularly useful. It program will execute in 1 of 2 ways that I can see

Case 1

The local n is initialized to a nonzero value by chance. It will then enter an infinite loop where the stack address of the local is assigned to the local. This won't terminate

Case 2

The local n is initialized to 0 by chance and the loop will not execute.

Carl Norum
  • 219,201
  • 40
  • 422
  • 469
JaredPar
  • 733,204
  • 149
  • 1,241
  • 1,454
  • The standard allows cases 3 through infinity. While most of them will never be the result of any actual implementation, there is a class that will be: interpreters or other checking implementations will produce a diagnostic and halt execution upon the first evaluation of `n`. BTW, it's odd that no one has recognized that the OP probably meant `n = *n`, which is considerably more interesting. – Jim Balter Mar 30 '11 at 00:59
3

That's not even a valid C program. From the spec, section 6.5.5 Cast operators, paragraph 3:

Conversions that involve pointers...shall be specified by means of an explicit cast.

Carl Norum
  • 219,201
  • 40
  • 422
  • 469
1

It will have an indeterminate behavior since the n variable is not initialized. If this is also corrected, it will either go in an infinite loop (if n is initialized to a non null value) or it will do nothing.

It doesn't compile. If you insert a cast to make it compile. BTW, you assign a int** to an int* and the compiler will probably emit a warning for such code.

Note: When n is initialized, clang is smart enough to optimize the code to either a nop if it is initialized to 0 or to an infinite loop otherwise.

Sylvain Defresne
  • 42,429
  • 12
  • 75
  • 85
1

It stores an constant if type int ** into a variable of type int*. Uhm... It will probably loop forever, since it's unlikely that &n == 0. And, oh, the first time the content of "n" is undefined!

Giuseppe Guerrini
  • 4,274
  • 17
  • 32
1

First of all, you have an assignment from incompatible pointer type (you're trying to assign an int ** to an int *); I don't remember exactly if it should trigger an error or just a warning (in C most probably a warning, in C++ it may be an error).

Then, even if you put there a cast (n=(int *)&n), that code exhibits undefined behavior, since at the very first iteration you're reading an uninitialized variable. Probably nothing very bad would happen (after all you're not dereferencing that pointer), but it's undefined whether the loop would be executed, as a rule of thumb, if that region of stack has already been used n will be nonzero, otherwise it will probably be zero.

If, correcting all mistakes/UB, it were:

int *n=NULL;
while (n!=0)
{
    n = (int *) &n;
}

it would perform an iteration, since it starts at NULL (which is guaranteed to be 0), and then it would exit from the loop, since no valid pointer compares equal to 0 (again, this is guaranteed by the standard).

As far as usefulness is concerned: as it is, for a "real" application it's completely useless.

Matteo Italia
  • 123,740
  • 17
  • 206
  • 299
  • `0` is a valid address on lots of systems. The fact that a `0` in a pointer context in your program gets automatically turned into a null pointer is unrelated to that. – Carl Norum Mar 29 '11 at 21:44
  • @Carl: what the standard mandates, both in C and C++ (with some small differences) is that a `NULL` pointer must evaluate to 0 and compare different from any valid pointer (`[conv.ptr]`, §4.10 ¶1). – Matteo Italia Mar 29 '11 at 21:45
  • @Matteo - only in the context of pointer operations in C. If I take an `int *` object and `memset()` it to `0`, it may very well not be a null pointer. http://c-faq.com/null/varieties.html – Carl Norum Mar 29 '11 at 21:48
  • @Carl: you have a valid point, although an implementation doing such a thing would probably have to go through hoops to keep everything working fine. However, this does not change the substance of my sentence in the answer, since in this snippet we're always in the domain of pointers. – Matteo Italia Mar 29 '11 at 21:50
  • @Matteo - you're absolutely right as far as this program is concerned. I just wanted to clarify that `0` is a perfectly valid address as far as the standards are concerned. – Carl Norum Mar 29 '11 at 21:51
  • @Carl: and you did well, it's always nice to learn new things. :) By the way, I fixed the answer, I think that now it should be correct also from the formal point of view. – Matteo Italia Mar 29 '11 at 21:54
0

Depends on the initial value of n, but most likely goes into an infinite loop.

  • n is a local (stack) variable that is a pointer to int.
  • while the point n contains a non-zero value (e.g., is not NULL)
    • set the value of n to the address of n (pretty much guaranteed to be non-zero)
Nicholas Carey
  • 71,308
  • 16
  • 93
  • 135