2015-04-01 6 views
0

я знаю, что объявить ststic переменную и инициализировать ее, таким образом, static int *st_ptr = malloc(sizeof(int)); будет генерировать сообщение об ошибке компиляции (тип инициализатора элемент не является постоянной), и решение это, используя отдельные заявления таким образом static int *st_ptr; st_ptr = malloc(5*sizeof(int));Использование таНос со статическими указателями


Мне нужно понять разницу между оператором инициализации и оператором присваивания в этом случае? И почему этот способ решил проблему?

+0

Оба они очень опасны и в стороне от обучения, их следует избегать. –

+1

Ваш второй пример будет скомпилирован, но он все еще не прав: он будет выделять новое хранилище каждый раз при вызове функции, протекая старое. Инициализируйте переменную до NULL и проверьте NULL перед вызовом 'malloc', чтобы он вызывался только один раз. – Wyzard

+0

@DavidHaim: О чем именно вы говорите? – dhein

ответ

3

Прежде всего, давайте кратко о initialization против assignment.

  • Инициализация:

Это используется для указания начального значения объекта.Обычно это означает, что только во время определения переменной происходит инициализация. Значение для инициализации объекта называется initalizer. Из C11, глава 6.7.9,

Инициализатор определяет начальное значение, хранящееся в объекте.

  • Назначение:

Назначение является назначение (или установка) значение переменной, в любой (действительной) данный момент времени исполнения. Цитирование стандарта, глава 6.5.16,

Оператор присваивания сохраняет значение в объекте, обозначенном левым операндом.

В случае простого присваивания (= оператора),

В простом присвоении (=), значение правого операнда преобразуется к типу выражения в назначения и заменяет значение, хранящееся в объекте, обозначенном левым операндом.


То есть, я думаю, ваш запрос должен делать с инициализацией static объекта.

Для первого случая,

static int *st_ptr = malloc(sizeof(int)); 

Цитируя C11 стандартного документа, глава §6.7.9, инициализация, пункт 4,

Всех выражения в инициализаторе для объекта, который имеет статический или длительность хранения потоков должны быть постоянными выражениями или строковыми литералами.

и относительно постоянное выражение, из главы 6.6 того же документа (курсив мой)

Постоянные выражения не должны содержать назначение, увеличение, уменьшение, вызова функции , или операторы запятой, за исключением случаев, когда они содержатся в подвыражении, которое не равно .

ясно, malloc(sizeof(int)); не константа, поэтому мы не можем использовать его для инициализации static объекта.

Для второго случая,

static int *st_ptr; 
st_ptr = malloc(5*sizeof(int)); 

вы не инициализацииstatic объекта. Вы оставляете его неинициализированным. Следующая инструкция: присваивает возвращаемое значение malloc(). Поэтому ваш компилятор не вызывает никаких жалоб.

+1

У меня создалось впечатление, что вы мой конкурент .... второй раз сегодня вы публикуете именно то, что я пытался процитировать из стандарта чуть быстрее, чем я. +1 для контента в любом случае (вы можете отметить это, если хотите ^^) – dhein

+1

@Zaibis Не волнуйтесь, в следующий раз, возможно, я стану одним комментарием этого комментария. :-) –

-1

Грубо инициализация на языке C происходит, когда компилятор выводит двоичные данные в исполняемый файл; назначение - операция, выполняемая фактическим исполняемым кодом.

Итак, static int i = 5 делает компилятор для вывода данных word 5 в раздел данных исполняемого файла; в то время как int i = func() заставляет компилятор генерировать несколько инструкций CPU как call для вызова подпрограммы и mov для сохранения результата.

Таким образом, выражение static int i = func() требует, чтобы: 1) было рассчитано ранее main() (так как это инициализация), 2) часть исполняемого кода пользователя (что может иметь смысл только в контексте нового экземпляра программы) , Эту проблему можно решить, создав скрытую инициализацию, которая выполняется до main(). Фактически, C++ делает это. Но C не имеет такой функции, поэтому статические переменные могут быть инициализированы только с помощью констант.

+1

'int i = func()' было бы в порядке, в то время как случай, указанный OP, недействителен. Таким образом, -1 для не очень связанных с вопросом OP. (Исправьте меня, если я ошибаюсь) – dhein

+0

@Zaibis Из сказанного выше очевидно (я надеюсь), почему 'static int i = func()' недействителен - ему нужен код для выполнения, в то время как он должен быть рассчитан перед чем-либо else (как требует инициализация). 'C++' решает эту проблему с помощью скрытых инициализационных подпрограмм, но чистая' C' не имеет такой функции - код пользователя не может быть выполнен до 'main()'. Вот почему 'C' разрешает только константы в качестве инициализации. – Matt

+0

А, ок. В любом случае, вы должны перефразировать его. – dhein

1

, когда переменная объявлена ​​статичной внутри функции, она создается либо в «сегменте данных», либо в «сегменте bss», зависит от того, была ли она инициализирована или нет.
эта переменная создается в двоичных файлах и должна иметь постоянное значение - помнить - статические переменные внутри функции создаются, когда программа продолжается даже до запуска main(), она не может быть инициализирована какой-либо функцией, поскольку программа еще не «запустить» (нет никаких оценок или вызовов функций)
, поэтому инициализатор должен быть постоянным или не инициализироваться на первом месте.

static int *st_ptr = malloc(sizeof(int)); 

здесь, вы связываете создание st_ptr с таНос, но так как таНос это функция, которая должна работать и st_ptr должны быть созданы перед выполнением любой другой функции - это создает невозможное состояние

static int *st_ptr; 
st_ptr = malloc(5*sizeof(int)); 

здесь st_ptr создается и остается неинициализированным, его создание не привязано к какой-либо функции. каждый раз, когда функция запускается - malloc имеет место. поэтому активация malloc и создание st_ptr не зависит.

, но, как я заявил в комментарии, это чрезвычайно опасная практика. вы выделяете все больше и больше памяти на одну и ту же переменную. единственный способ избежать этого - free(st_ptr) в конце каждой функции. это сказало - вам не нужно статично на первом месте

Смежные вопросы