Сложность в концепции NULL в C? - PullRequest
5 голосов
/ 12 сентября 2010

NULL в программировании на C Может кто-нибудь сказать мне, как NULL обрабатывается в C?И вывод этой программы 3, как с концепцией NULL?

#include <stdio.h>

int main(void) {
    int i;
    static int count;
    for(i = NULL; i <= 5;) {
        count++;
        i += 2;
    }

    printf("%d\n",count);
    return 0;
}

Ответы [ 8 ]

21 голосов
/ 12 сентября 2010

Для C "NULL" традиционно определяется как (void *) 0 - другими словами, это псевдоним указателя на адрес 0. Для C ++ "NULL" обычно определяется как "0". Проблема с NULL в C ++ и C заключается в том, что это небезопасно - вы можете создавать причудливые конструкции, подобные той, которую вы включили в пример кода.

Для C ++ разработчики языка исправили это в C ++ 0x, добавив новый тип "nullptr", который неявно конвертируется в любой тип указателя, но который не может быть преобразован в целочисленный тип.

3 голосов
/ 13 апреля 2011

В C FAQ есть целая глава, посвященная нулевому указателю, которая должна ответить на все ваши вопросы.

  • 5.1 В любом случае, что это за печально известный нулевой указатель?
  • 5.2 Как получить нулевой указатель в моих программах?
  • 5.3 Допустимо ли сокращенное сравнение указателей if(p) для проверки ненулевых указателей? Что если внутреннее представление для нулевых указателей отлично от нуля?
  • 5.4 Что такое NULL и как оно определяется?
  • 5.5 Как определить NULL на машине, которая использует ненулевой битовый шаблон как внутреннее представление нулевого указателя?
  • 5.6 Если NULL были определены следующим образом: #define NULL ((char *)0). Разве это не заставит работать вызовы функций, которые передают uncast NULL?
  • 5.7 Мой поставщик предоставляет заголовочные файлы, которые #define NULL равны 0L. Почему?
  • 5.8 Допустимо ли NULL для указателей на функции?
  • 5.9 Если NULL и 0 эквивалентны как константы нулевого указателя, что мне следует использовать?
  • 5.10 Но не лучше ли использовать NULL (а не 0), если значение NULL изменится, возможно, на машине с ненулевыми внутренними нулевыми указателями?
  • 5.11 Однажды я использовал компилятор, который не работал бы, если бы не использовался NULL.
  • 5.12 Я использую макрос препроцессора #define Nullptr(type) (type *)0, чтобы помочь мне создать нулевые указатели правильного типа.
  • 5.13 Это странно. NULL гарантированно равно 0, но нулевой указатель - нет?
  • 5.14 Почему так много путаницы вокруг нулевых указателей? Почему эти вопросы возникают так часто?
  • 5.15 Я в замешательстве. Я просто не могу понять все эти вещи с нулевым указателем.
  • 5.16 Учитывая всю путаницу, связанную с нулевыми указателями, не проще ли будет просто потребовать, чтобы они были представлены внутри нулями?
  • 5.17 Серьезно, есть ли на реальных машинах действительно ненулевые нулевые указатели или разные представления для указателей на разные типы?
  • 5.18 Является ли целое значение времени выполнения 0, приведенное к указателю, гарантированно нулевым?
  • 5.19 Как получить доступ к вектору прерываний, расположенному в местоположении машины 0? Если я установлю указатель на 0, компилятор может преобразовать его в ненулевое значение внутреннего нулевого указателя.
  • 5.20 Что означает ошибка `` присвоения нулевого указателя '' во время выполнения? Как я могу отследить это?
3 голосов
/ 12 сентября 2010

NULL - это просто макрос, определенный в stdio.h, или файл, включенный в stdio.Он может быть по-разному определен как некоторое изменение нуля.

Если вы запустите свой код через препроцессор C (обычно cc -E), вы можете увидеть, что он переводит в вашей реализации:

void main(){
    int i;
    static int count;
    for(i=((void *)0); i<=5 ;){
       count++;
       i+=2;
    }
    printf("%d",count);
}

, который является не только ненужным использованием NULL, но и дико не идиоматическим кодом C, более обычным будет:

int main(){
    int i;
    int count = 0;
    for(i = 0; i <= 5; i += 2){
       count++;
    }
    printf("%d\n",count);
    return 0;
}
2 голосов
/ 12 сентября 2010

NULL имеет наибольшее значение при работе с указателями. Имея дело с целыми числами, вам лучше использовать просто ноль.

Строго говоря, NULL - это просто нулевое значение с причудливым именем, но самая важная часть в нем - это действительно причудливое имя. Он существует потому, что писать int* p = NULL; менее двусмысленно, чем int* p = 0;. Поскольку мы знаем, что NULL является указателем, мы уверены, что я действительно имел в виду p как указатель.

Итак, когда вы имеете дело с указателями и хотите представить адрес 0, используйте NULL. И когда вы имеете дело с числами и хотите представить число 0, используйте 0. (В вашем примере вы должны использовать 0 вместо NULL.)

1 голос
/ 12 сентября 2010

NULL должно быть синонимом 0.Правильнее использовать его для указания нулевого указателя.

В этом случае код на самом деле будет:

for (i = 0; i <= 5)
{
    count++;
    i += 2;
}
0 голосов
/ 12 сентября 2010

Не путайте идею указателя NULL в c с представлением обнуляемого типа или величин в некоторых динамических языках.Существуют аналогичные, но имеют различные применения и значения.

В c концепция NULL используется только изначально в контексте указателя, где он является указателем на известное неверное расположение в памяти (часто, но не всегда, представлен нолем).

Это не совсем то же самое, что тип или переменная, которая может представлять не-множественность.Обратите внимание, что такие типы могут определяться и управляться пользователем в c, но они не предоставляются языком.

0 голосов
/ 12 сентября 2010

Тип NULL и тип i различны, но C прощает вас:)

C (в основном) не является "безопасным для типов" языком.Я имею в виду: он позволяет вам смешивать типы, на которые жаловались бы другие языки.

С C вы можете добавить chars к doubles, вы можете умножить chars и ints, ...

Что вы делаете, так это присваиваете null pointer constant (типа void *) int.C позволяет это, но вам нужно быть очень осторожным при смешивании типов , как это.

Результат присвоения константы нулевого указателя для типа int аналогичен присваиванию 0к этому.Таким образом, вы начинаете цикл с i, равным 0.

Статическая автоматическая переменная в отсутствие инициализатора инициализируется равной 0.Это происходит с переменной count в вашей программе.

Итак, цикл идет первым (count становится 1) с i равным 0, затем i становится 2.
Теперьцикл идет (count становится 2) с i равным 2, затем i становится 4.
Теперь цикл идет (count становится 3) с i равным 4, затем i становится 6.
И цикл завершается ... и вы печатаете значение count.


Примечания

  • для соответствия стандартуmain должно быть объявлено int main(void)
  • вы должны выводить новую строку после каждой завершенной строки (printf("%d\n", count);)
  • , и вы должны return 0;, чтобы указать успешное завершение вашей программы дляОперационная система
0 голосов
/ 12 сентября 2010

NULL определяется как 0 на C. В вашей программе он считается от 0 до 5 (считая каждого второго числа) Вот почему счетчик равен 3 (i = 0, 2, 4).

NULL не должен использоваться таким образом. NULL следует использовать с указателями.

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