Указатель на нулевой указатель определен в ANSI C? - PullRequest
1 голос
/ 07 июня 2011

Правильно ли этот код (упрощенный из реального проекта)? Будет ли сообщение всегда печататься?

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

Спасибо! * * 1004

Ответы [ 3 ]

6 голосов
/ 07 июня 2011

Нет ничего плохого в коде, который вы показали.Ваш указатель char ** указывает на допустимую переменную, поэтому всегда следует разыменовывать ее.

PS Да, он всегда будет печататься.

4 голосов
/ 07 июня 2011

Да, он всегда будет печататься.

Вы можете смело предположить, что ваш базовый указатель стека никогда не указывает на 0x0, поэтому & cp всегда не будет равен NULL.

Фактически, компилятор исключит проверку во время компиляции, потому что он знает &cp != NULL.

Убедитесь сами:

Скомпилировано с -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

-O0 будет тест, хотя:)

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
0 голосов
/ 07 июня 2011

Конечно, это всегда печатает, почему бы и нет?

Указатель, который вы разыменовываете в своем выражении if(), равен cpp. Вы только разыменовываете один уровень, используя одну * звездочку. cpp может указывать на NULL указатель, но cpp не сам по себе NULL.

С другой стороны, написание char k = **cpp должно привести к некоторому сбою.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...