1

Is this code (simplified from a real project) correct? Will the message always print?

char *cp = NULL;
char **cpp = &cp;
if(*cpp == NULL) {
    printf("I believe this will this always print. Does it?\n");
}

Thanks!

3 Answers 3

6

There is nothing wrong with the code you have shown. Your char ** pointer is pointing to a valid variable, thus it's always proper to dereference it.

P.S. Yes, it will always print.

Sign up to request clarification or add additional context in comments.

5 Comments

@Heath Hunnicutt - Is there something wrong with the answer? I was reading between the lines of the question and guessing there was some confusion about how pointers to pointers actually work.
@Heath: I can't speak for Mark, of course ... but a) of course we want the points (how do you think we got to 40k or 20K or 6K); b) not really, points are overrated; c) I don't care for points: my answer wasn't suitable for a comment; d) if SO shuts down, I'll sell my points to the highest bidder
@pmg, thanks for the elaboration. Points aren't the end-all, but they're a good surrogate for measuring how helpful you've been. That's my primary motivation. As time goes on I find myself using comments as much or more than answers, even though comments don't affect your point scores.
P.S. I'll just say that some days it's hard to find a question you can answer! Not every song has to be a hit.
indeed; I also find myself doing more and more comments nowadays. I think @Heath was wondering why the community wiki check for answers is not used more :)
4

Yes, it will always print.

You can safely assume that your base stack pointer never points to 0x0, so &cp will always not equal NULL.

In fact the compiler will eliminate the check at compile time, because it knows &cp != NULL.

See for yourself:

Compiled with -O1:

$ objdump -dC a.out 
a.out:     file format elf64-x86-64
  ...
00000000004004f4 <main>:
  4004f4:       48 83 ec 08             sub    $0x8,%rsp
  4004f8:       bf 00 06 40 00          mov    $0x400600,%edi
  4004fd:       e8 ee fe ff ff          callq  4003f0 <puts@plt>
  400502:       b8 00 00 00 00          mov    $0x0,%eax
  400507:       48 83 c4 08             add    $0x8,%rsp
  40050b:       c3                      retq

(With -O0 there will be a test, though:)

00000000004004f4 <main>:
  4004f4:       55                      push   %rbp
  4004f5:       48 89 e5                mov    %rsp,%rbp
  4004f8:       48 83 ec 10             sub    $0x10,%rsp
  4004fc:       48 c7 45 f0 00 00 00    movq   $0x0,-0x10(%rbp)
  400503:       00 
  400504:       48 8d 45 f0             lea    -0x10(%rbp),%rax
  400508:       48 89 45 f8             mov    %rax,-0x8(%rbp)
  40050c:       48 8b 45 f8             mov    -0x8(%rbp),%rax
  400510:       48 8b 00                mov    (%rax),%rax
  400513:       48 85 c0                test   %rax,%rax
  400516:       75 0a                   jne    400522 <main+0x2e>
  400518:       bf 20 06 40 00          mov    $0x400620,%edi
  40051d:       e8 ce fe ff ff          callq  4003f0 <puts@plt>
  400522:       b8 00 00 00 00          mov    $0x0,%eax
  400527:       c9                      leaveq 
  400528:       c3                      retq

Comments

0

Of course that always prints, why would it not?

The pointer you are dereferencing in your if() statement is cpp. You only dereference one level, by using one * asterisk. cpp may point to a NULL pointer, but cpp is not itself NULL.

On the other hand writing char k = **cpp should result in a crash of some sort.

14 Comments

Undefined Behavior "should" not necessarily do anything. It might crash, it might "work", it might spew acid.
Blah, blah, undefined behavior. Seriously irrelevant IRL. Often used as a pretense for representing C as less predictable than it really is. Nothing will be spewing acid, as an example. I wager the OP is not coding on DOS, either.
@Heath: It's most definitely not irrelevant (well, acid probably is, but not the "might crash, might work").
UB is very relevant IRL here. If the compiler can determine statically that **cpp will always be a null pointer dereference, it can optimize out any code after it and any prior code paths that necessarily lead up to the dereference, on the assumption that they cannot happen.
@Heath: Not everyone's writing code for an x86 with optimizations disabled! Many embedded controllers/DSPs (for example) have no hardware trap for acessing 0x0000.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.