Модераторы: Daevaorn

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> static & extern & volitale, помогите понять 
:(
    Опции темы
slater
Дата 16.2.2010, 13:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 168
Регистрация: 20.11.2009

Репутация: -2
Всего: -4



помогите разобраться с static & extern & volitale (чистый язык Си)
где и когда  используется(все случаи использования) и зачем и почему
привидите пример с хидером и сишным файлом
PM MAIL   Вверх
17dufa
Дата 16.2.2010, 13:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 324
Регистрация: 2.3.2006

Репутация: 3
Всего: 5



вот тут вроде неплохо расписано:
http://www.quizful.net/post/cpp-keywords-usage
PM MAIL   Вверх
slater
Дата 16.2.2010, 13:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 168
Регистрация: 20.11.2009

Репутация: -2
Всего: -4



читал, хотелось бы примеров, глубже  понять отличие статики(и функций и переменных) от глобальных и пример хидера и сишника
PM MAIL   Вверх
MAKCim
Дата 16.2.2010, 14:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Воін дZэна
****


Профиль
Группа: Экс. модератор
Сообщений: 5644
Регистрация: 10.12.2005
Где: Менск, РБ

Репутация: 52
Всего: 207



extern - в прототипах функций в интерфейсных *.h файлах
static - для ограничения области использования границами *.c файла (или функции в рамках *.c файла) или для защиты от double definition при использовании inline (c99)
volatile - для доступа к совместно используемым данным




--------------------
Ах, у елі, ах, у ёлкі, ах, у елі злыя волкі ©

PM MAIL   Вверх
slater
Дата 16.2.2010, 14:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 168
Регистрация: 20.11.2009

Репутация: -2
Всего: -4



MAKCim,  smile 

не до конца понятно, extern применяется и в прототипах функций в интерфейсных *.h файлах и для переменных?

static в прототипах не используется? только при определении перменных и функций?

что значит совместно совместно используемые данные? между кем используются?
PM MAIL   Вверх
17dufa
Дата 16.2.2010, 15:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 324
Регистрация: 2.3.2006

Репутация: 3
Всего: 5



slater, extern и для переменных
1.cpp:
Код

int i;

1.h:
Код

extern int i;

2.cpp:
Код

#include "1.h"
void f()
{
i++;
}

PM MAIL   Вверх
slater
Дата 16.2.2010, 15:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 168
Регистрация: 20.11.2009

Репутация: -2
Всего: -4



да, с extern я разобрался, осталось со статикой и валитейлом
PM MAIL   Вверх
Alca
Дата 16.2.2010, 15:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3993
Регистрация: 14.6.2006

Репутация: 7
Всего: 50





--------------------
PM WWW ICQ Skype Jabber   Вверх
MAKCim
Дата 16.2.2010, 16:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Воін дZэна
****


Профиль
Группа: Экс. модератор
Сообщений: 5644
Регистрация: 10.12.2005
Где: Менск, РБ

Репутация: 52
Всего: 207



Цитата(slater @  16.2.2010,  14:48 Найти цитируемый пост)
что значит совместно совместно используемые данные? между кем используются? 

классический пример
Код

static int value;

static void thread1()
{
    for (;;)
    {
        /* периодически как-нибудь изменяем значение value */
    }
}

static void thread2()
{
    int i;
    for (;;)
    {
        for (i = 0; i < value; )
        {
            ...
        }
        ...
    }
}

из-за возможных оптимизаций thread2 на k-ой итерации может не "увидеть" изменений value из thread1

Добавлено через 37 секунд
Цитата(slater @  16.2.2010,  14:48 Найти цитируемый пост)
и для переменных?

да, естественно


--------------------
Ах, у елі, ах, у ёлкі, ах, у елі злыя волкі ©

PM MAIL   Вверх
baldina
Дата 16.2.2010, 16:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3433
Регистрация: 5.12.2007
Где: Москва

Репутация: 32
Всего: 101



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

переменная, объявленная как static внутри функции имеет, в отличие от прочих локальных переменных, глобальное время жизни (т.е. ее значение сохраняется между вызовами функции. например
Код

void foo ()
{
  static int a = 0;
  printf ("%ld ", a);
  ++a;
}

void bar ()
{
  int a = 0;
  printf ("%ld ", a);
  ++a;
}

int main ()
{
   for (int i=0; i < 10; ++i)
     foo ();
   printf ("\n");
   for (int i=0; i < 10; ++i)
     bar ();
}

выведет 
Код

0 1 2 3 4 5 6 7 8 9
0 0 0 0 0 0 0 0 0 0 


объявляя переменную, как volatile, мы сообщаем компилятору, что её значение может измениться в произвольный момент времени. это значит, что компилятор не будет применять к этой переменной оптимизацию и вообще делать каких-либо выводов о её возможном текущем значении. т.е. компилятор не будет размещать переменную в регистре и т.п., а будет добросовестно читать/писать её значение из/в ячейку памяти при каждом обращении.
обычно используется в многопоточных приложениях, когда два потока работают с одними данными.
PM MAIL   Вверх
slater
Дата 16.2.2010, 16:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 168
Регистрация: 20.11.2009

Репутация: -2
Всего: -4



т.е. нада:

static volitale  int value; ???????

а кроме области видимости у статики есть еще какой смысл?
PM MAIL   Вверх
baldina
Дата 16.2.2010, 16:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3433
Регистрация: 5.12.2007
Где: Москва

Репутация: 32
Всего: 101



Цитата(slater @  16.2.2010,  16:10 Найти цитируемый пост)
т.е. нада:

static volitale  int value; ???????

ну если нада, то нада  smile 
только 
Код

static volatile int value;

volitale vs volatile

Добавлено через 1 минуту и 35 секунд
volatile - непостоянный, изменчивый; неуловимый, переменный

Добавлено через 5 минут и 42 секунды
Цитата(slater @  16.2.2010,  16:10 Найти цитируемый пост)
а кроме области видимости у статики есть еще какой смысл? 

время жизни глобальное. статические переменные размещаются в сегменте данных. если статическая переменная объявлена внутри функции, гарантируется, что она будет проинициализирована начальным значением до первого использования.
PM MAIL   Вверх
MAKCim
Дата 16.2.2010, 17:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Воін дZэна
****


Профиль
Группа: Экс. модератор
Сообщений: 5644
Регистрация: 10.12.2005
Где: Менск, РБ

Репутация: 52
Всего: 207



Цитата(slater @  16.2.2010,  16:10 Найти цитируемый пост)
а кроме области видимости у статики есть еще какой смысл? 

предотвращает double definition inline функций, определенных в *.h файлах


--------------------
Ах, у елі, ах, у ёлкі, ах, у елі злыя волкі ©

PM MAIL   Вверх
Леопольд
Дата 16.2.2010, 17:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 943
Регистрация: 17.6.2009

Репутация: 10
Всего: 13



Alca, очень полезная статья, спасибо за ссылку!


--------------------
вопросов больше чем ответов
PM MAIL   Вверх
slater
Дата 16.2.2010, 18:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 168
Регистрация: 20.11.2009

Репутация: -2
Всего: -4



MAKCim,baldina,Alca,17dufa  , спасибо вам, ребята
тему пока не помечаю как закрытую
PM MAIL   Вверх
slater
Дата 16.2.2010, 21:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 168
Регистрация: 20.11.2009

Репутация: -2
Всего: -4



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

например, в вики http://en.wikipedia.org/wiki/Static_variab...Class_Variables написано

In the C programming language and its descendants, the term static variable has at least three separate meanings, each related to the semantics of C's static keyword:
1)Static global variables are declared as "static" at the top level of a source file. Such variables are not visible outside the source file ("file scope"), unlike variables declared as "extern".

2)Static local variables are declared inside a function, just like automatic local variables. They have the same scope as normal local variables, differing only in "storage duration": whatever values the function puts into static local variables during one call will still be present when the function is called again.

3)C++ has static member variables: in classes, member variables declared as "static" are class variables (as opposed to instance variables).


и в чем будет отличие, например:

file1.c

int a;
static int b;

void foo1() {...}
static void foo2() {...}


file1.h
extern int a;
extern int b;
extern void foo1();
extern void foo290;


в чем будет разница при подключении этого хидера?
пока я понял только то, что под статику будет выделяться места ровно столько, сколько мы подключим этот хидер. а в остальном, глобальная статика и просто глобальные элементы одинаковы. и еще хотел спросить, память будет выделяться при использовании файла 1 без его подключения в другие сишные файлы????


Это сообщение отредактировал(а) slater - 16.2.2010, 21:20
PM MAIL   Вверх
baldina
Дата 16.2.2010, 22:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3433
Регистрация: 5.12.2007
Где: Москва

Репутация: 32
Всего: 101



slater, зачем читать на на заборах? есть специализированные ресурсы по C/C++
а еще лучше - купи книжку и читай, там все это просто, доступно и с примерами.
Цитата(slater @  16.2.2010,  21:01 Найти цитируемый пост)
ребята, с одной стороны, в сишном файле если определим функцию и глобальную переменную(область видимости - это сишный файл) с ключевым словом static, т.е. по сути, они будут только доступны в этом сишном файле.
вот, вопрос в том, могу ли я использовать это статические элементы в других сишных файлах

нет, не можешь. собственно для того и определяют, чтобы это было нельзя.
есть понятие связывания (linkage) - внешнее (external) и внутреннее (internal). почитай про это.
вообще, 
Код

int a;

это одновременно объявление и определение переменной. 
Код

extern int a;

это только объявление, что есть где-то такая переменная и мы ее здесь можем использовать. память выделяется только при определении.
глобальные переменные и функции имеют внешнее связывание, к ним можно получить доступ из других единиц компиляции. посредством объявления extern.
глобальные переменные и функции, объявленные с модификатором доступа static имеют внутреннее связывание, к ним нельзя получить доступ из других единиц компиляции, даже посредством объявления extern.

ищи в алфавитном указателе книжки выделенные слова, читай, и будет тебе счастье.

Добавлено через 9 минут и 31 секунду
Цитата(slater @  16.2.2010,  21:01 Найти цитируемый пост)
в чем будет разница при подключении этого хидера?

получим
Код

extern int a; // это объявление переменной. где-то есть int a, теперь она видна в текущем файле
extern int b; // это объявление переменной. где-то есть int b, теперь она видна в текущем файле
extern void foo1(); // это объявление функции. где-то есть void foo1(), теперь она видна в текущем файле
extern void foo2(); // это объявление функции. где-то есть void foo2(), теперь она видна в текущем файле

int a; // это определение переменной. той самой, объявление которой было выше.
static int b; // это определение новой переменной b. теперь переменная, объявленная выше недоступна для использование (перекрытие имен).

void foo1() {...}// это определение функции. той самой, что объявлена выше
static void foo2() {...} // это определение новой функции. та, что объявлена выше, теперь недоступна.



Это сообщение отредактировал(а) baldina - 16.2.2010, 22:07
PM MAIL   Вверх
slater
Дата 16.2.2010, 22:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 168
Регистрация: 20.11.2009

Репутация: -2
Всего: -4



baldina, спасибо за исчерпывающий ответ

посоветуйте книжечку пожалуйста, где про связывание хорошо расписано

в примере выше, т.е.

Код

extern int a; // это объявление переменной. где-то есть int a, теперь она видна в текущем файле
extern int b; // это объявление переменной. где-то есть int b, теперь она видна в текущем файле
extern void foo1(); // это объявление функции. где-то есть void foo1(), теперь она видна в текущем файле
extern void foo2(); // это объявление функции. где-то есть void foo2(), теперь она видна в текущем файле

int a; // это определение переменной. той самой, объявление которой было выше.
static int b; // это определение новой переменной b. теперь переменная, объявленная выше недоступна для использование (перекрытие имен).

void foo1() {...}// это определение функции. той самой, что объявлена выше
static void foo2() {...} // это определение новой функции. та, что объявлена выше, теперь недоступна.


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

Это сообщение отредактировал(а) slater - 16.2.2010, 22:33
PM MAIL   Вверх
baldina
Дата 16.2.2010, 22:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3433
Регистрация: 5.12.2007
Где: Москва

Репутация: 32
Всего: 101



перекрытие в данном случае термин. ели есть несколько идентификаторов с одним именем, в конкретной точке доступен лишь один.
Код

int a=0;

int main ()
{
   int a=1;
   {
      int a=2;
      printf ("%ld\n", a); // печатает 2
   }
}

PM MAIL   Вверх
slater
Дата 16.2.2010, 22:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 168
Регистрация: 20.11.2009

Репутация: -2
Всего: -4



baldina, СПАСИБО!!!
PM MAIL   Вверх
baldina
Дата 16.2.2010, 23:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3433
Регистрация: 5.12.2007
Где: Москва

Репутация: 32
Всего: 101



книг полно, но конкретно не скажу, давно не приобретал. по С++ можно С.Прата почитать.
вообще хороший ресурс http://www.intuit.ru/ тут и лекции, и ссылки на литературу
PM MAIL   Вверх
slater
Дата 18.2.2010, 18:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 168
Регистрация: 20.11.2009

Репутация: -2
Всего: -4



Цитата(baldina @ 16.2.2010,  16:09)
переменная, объявленная как static вне функции имеет внутреннее связывание. т.е. компилятор не создает для нее внешней ссылки и линкер ничего о ней не знает. таким образом область видимости такой переменной ограничена своей единицей компиляции, т.е. .cpp файлом, в котором она объявлена (от объявления и ниже).
если поместить объявление такой переменной в заголовок, включаемый в несколько файлов (единиц компиляции), то в результате получим несколько разных переменных.
....

ну никак что-то не получается включить статику в другие сишные файлы

Код

static.h

#ifndef __STATIC_H__
#define __STATIC_H__

extern void staticf(char* str);
extern char *string;

#endif


static.c

Код

#include <stdio.h>
#include "static.h"


static void staticf(char* str)
{
        printf("%s\n", str);
}

static char* string="Hello, World!!!";




main.c

Код

#include "static.h"

int main()
{
        staticf(string);
        staticf("OOOO\n");

        return 0;
}


Добавлено через 4 минуты и 17 секунд
извиняюсь, компилируется, только вот не понимаю почему?????? объясните пожалуйста, нигде не могу найти хорошее описание
PM MAIL   Вверх
baldina
Дата 18.2.2010, 23:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3433
Регистрация: 5.12.2007
Где: Москва

Репутация: 32
Всего: 101



включаемые (.h) файлы включаются буквально. имеем
static.с
Код

#ifndef __STATIC_H__
#define __STATIC_H__
extern void staticf(char* str);
extern char *string;
#endif

static void staticf(char* str)
{
        printf("%s\n", str);
}
static char* string="Hello, World!!!";

здесь объявлены внешние staticf и string, но определены и локальные (статические) staticf и string. которые нигде не используются.
синтаксически все верно. практически - наличие или отсутствие этого файла на программу никак не влияет (умный линкер вообще его в программу не включит, т.к. нет экспортируемых имен)

теперь main.c
Код

#ifndef __STATIC_H__
#define __STATIC_H__
extern void staticf(char* str);
extern char *string;
#endif
int main()
{
        staticf(string);
        staticf("OOOO\n");
        return 0;
}

тут тоже все синтаксически верно - объявлены внешние staticf и string, которые тут и используются. так что должно компилироваться. вот только линковаться не будет, т.к. в проекте нет определения глобальных staticf и string.
PM MAIL   Вверх
slater
Дата 19.2.2010, 08:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 168
Регистрация: 20.11.2009

Репутация: -2
Всего: -4



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

причем в майне string берется как раз из статики(из файла static.c)
PM MAIL   Вверх
baldina
Дата 19.2.2010, 12:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3433
Регистрация: 5.12.2007
Где: Москва

Репутация: 32
Всего: 101



Цитата

программа все равно линкуется и выполняется, можете сами глянуть

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


PM MAIL   Вверх
slater
Дата 19.2.2010, 12:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 168
Регистрация: 20.11.2009

Репутация: -2
Всего: -4



gnu gcc
выкинуть?!
)))))))))
PM MAIL   Вверх
baldina
Дата 19.2.2010, 13:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3433
Регистрация: 5.12.2007
Где: Москва

Репутация: 32
Всего: 101



gcc 4.1.2, естественно не линкует.
значит делаешь не то, что говоришь

Добавлено через 2 минуты и 43 секунды
Код

$ cc 1.cpp 2.cpp -o a.out
/tmp/cckNIeug.o: In function `main':
1.cpp:(.text+0x12): undefined reference to `string'
1.cpp:(.text+0x1a): undefined reference to `staticf(char*)'
1.cpp:(.text+0x26): undefined reference to `staticf(char*)'
/tmp/cckNIeug.o:(.eh_frame+0x11): undefined reference to `__gxx_personality_v0'
collect2: выполнение ld завершилось с кодом возврата 1
$ cc -v
gcc версия 4.1.2 20080704 (Red Hat 4.1.2-46)

то же самое при линковке говорят MSVC 7.1 и 9.0
PM MAIL   Вверх
Страницы: (2) [Все] 1 2 
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.1216 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.