2014 dxdy logo

Научный форум dxdy

Математика, Физика, Computer Science, Machine Learning, LaTeX, Механика и Техника, Химия,
Биология и Медицина, Экономика и Финансовая Математика, Гуманитарные науки




Начать новую тему Ответить на тему На страницу Пред.  1, 2, 3  След.
 
 Re: Язык Си. Парсер для подсветки Си-кода, глобальные переменные
Сообщение15.01.2023, 15:48 
Заслуженный участник


02/08/11
6931
oleg_2 в сообщении #1577199 писал(а):
почему глобальные переменные не могут лежать там же, где и локальные, т. е. в стеке?
По множеству причин. Например у них не будет фиксированного адреса, и как функция узнает где в памяти расположена эта переменная?

 Профиль  
                  
 
 Re: Язык Си. Парсер для подсветки Си-кода, глобальные переменные
Сообщение15.01.2023, 16:13 


02/10/12
303
Этот g++ всё кушает, вот:
код: [ скачать ] [ спрятать ]
Используется синтаксис C
// глобальный массив
const char *kodirovka[] = {
    "windows-1251", // (0)
    "utf-8",        // (1)
};


/*
// глобальный массив
const char **kodirovka = {
    "windows-1251", // (0)
    "utf-8",        // (1)
};
*/

/*
//--------------------
const char * const kodirovka[] = {
    "windows-1251", // (0)
    "utf-8",        // (1)
};


const char* kod() {
    static const char * const kod = kodirovka[KODIROVKA];
    return kod;
}
*/

//-------------------------------

const char *kod = kodirovka[KODIROVKA]; // глобальная, METKA-1 =====


Исходный мой вариант, без дополнительных const, компилирует чисто. Говорили, что с++ это усовершенствованный Си, и такая разница компиляторов. Попробую ещё попридумывать примеров, чтобы проверить Ваши слова о времени компиляции. Если такое правило, если с++ более совершеный, то придётся смириться. Всё-таки gcc наш, сишный компилятор, а g++ неведомо что.

 Профиль  
                  
 
 Re: Язык Си. Парсер для подсветки Си-кода, глобальные переменные
Сообщение15.01.2023, 16:20 
Заслуженный участник


31/12/05
1509
oleg_2 в сообщении #1577199 писал(а):
Но пока не понял, а почему глобальные переменные не могут лежать там же, где и локальные, т. е. в стеке? Ведь, как я понимаю, отличие глобальной от локальной в том только, что её видно отовсюду.
Потому что при выходе из функции локальные переменные уничтожаются (указатель стека сдвигается, и локальные переменные следующей функции их затирают).

 Профиль  
                  
 
 Re: Язык Си. Парсер для подсветки Си-кода, глобальные переменные
Сообщение15.01.2023, 16:23 


02/10/12
303
warlock66613 в сообщении #1577205 писал(а):
По множеству причин. Например у них не будет фиксированного адреса, и как функция узнает где в памяти расположена эта переменная?

Почему это? выделить в стеке место для глобальных, поделить стек на две части, одна для глобальных, другая собственно стек - первым зашёл последним вышел, для локальных. g++ ведь как-то делает. Ну хорошо-хорошо, я согласен, а то я тут на пустом месте хорохорюсь, если так сделано, то пусть, главное это знать, что не всё гладко с глобальными, на всякий случай.
Благодарю Вас.

 Профиль  
                  
 
 Re: Язык Си. Парсер для подсветки Си-кода, глобальные переменные
Сообщение15.01.2023, 16:26 
Заслуженный участник


31/12/05
1509
oleg_2 в сообщении #1577206 писал(а):
Исходный мой вариант, без дополнительных const, компилирует чисто.
Компилятор не может вычислить неконстантные выражения, ему приходится создавать скрытый код инициализации, выполняющийся до main. Идеология языка C такого не позволяет, поэтому там такое не работает.

 Профиль  
                  
 
 Re: Язык Си. Парсер для подсветки Си-кода, глобальные переменные
Сообщение15.01.2023, 16:35 


02/10/12
303
tolstopuz в сообщении #1577209 писал(а):
Компилятор не может вычислить неконстантные выражения, ему приходится создавать скрытый код инициализации, выполняющийся до main. Идеология языка C такого не позволяет, поэтому там такое не работает.

Спасибо. Сегодня я узнал то, о чём и не подозревал. Надо ещё подумать и примеры попробовать прокрутить.

 Профиль  
                  
 
 Re: Язык Си. Парсер для подсветки Си-кода, глобальные переменные
Сообщение15.01.2023, 22:31 
Аватара пользователя


28/10/21
99
oleg_2 в сообщении #1577147 писал(а):
Почему так? Казалось бы, две строки об одном и том же
const char *kodirovka[] = ... -работает.
const char **kodirovka = ... -не работает.


Это как это "об одном и том же"? Ничего общего эти варианты не имеют. Первый вариант объявляет массив указателей. Каждый указатель в этом массиве инициализируется указателем на свой строковый литерал - все в порядке. Второй вариант объявляет некий указатель. Чем он инициализируется? На что должен указывать этот указатель???

"Спасти" второй вариант можно так

Используется синтаксис C
const char **kodirovka = (const char *[]) {
    "windows-1251", // (0)
    "utf-8",        // (1)
};
 


Это уже будет компилироваться. Но это будет полностью эквивалентно первому варианту. То есть нет смысла заменять первый вариант на этот.

oleg_2 в сообщении #1577147 писал(а):
И в аргументах функции
const char *set_kod(const char **kodirovka);
массив определён по второму варианту, нерабочему, но работает. Моё предположение: когда память под массив уже выделена, то можно без квадратных скобок, а если ещё не выделена, то нужны квадратные скобки.


Нет. Список параметров функции - это совсем другой контекст, в котором эта запись имеет совсем другой смысл, ничего общего не имеющий с исходным вариантом. В списке параметров функции const char **kodirovka полностью эквивалентно const char *kodirovka[]. За пределами списка параметров функции такой эквивалентности нет даже отдаленно. Поэтому сравнивать поведение при объявлении глобальных переменных с поведением в списке параметров функции смысла нет.

oleg_2 в сообщении #1577147 писал(а):
Переменная const char *kod в парсере и в серверной обёртке парсера используется в трёх функциях, и я хотел сделать её глобальной. Но не получилось. В программе выше есть 4 метки, ими помечены кусочки кода, причастные к вопросу. Пробовал активировать каждую из них по отдельности. Глобальные (METKA-1, METKA-2) не работают.


Проблема в инициализаторе.

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

oleg_2 в сообщении #1577147 писал(а):
А локальные (МЕТКА-3, МЕТКА-4) работают. Почему так? Подозреваю, что это баг компилятора.


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

oleg_2 в сообщении #1577147 писал(а):
Вопрос-3.
Фрагмент Си-кода:
Используется синтаксис C
    printf("Content-type: text/html; charset=windows-1251\n\n");
    printf("<html>\n"
        "<head>\n"
        "<title>p_C_2</title>\n"
        "</head>\n"
        "<body>\n"

          ....
 

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


"Компьютерах"? При чем здесь "компьютерах"?

Вопрос о том, будет ли это работать во всех компиляторах языка С. Да, будет. Это требование стандарта языка.

-- 15.01.2023, 11:36 --

oleg_2 в сообщении #1577202 писал(а):
Вот так штука. Ваш вариант с функцией kod gcc бракует, а g++ не бракует. Вот так компилирует чисто:
g++ zprint.c -o zprint.cgi -Wall -Werror -O3


Потому что С++ и С - два разных языка программирования.

-- 15.01.2023, 11:41 --

tolstopuz в сообщении #1577209 писал(а):
oleg_2 в сообщении #1577206 писал(а):
Исходный мой вариант, без дополнительных const, компилирует чисто.
Компилятор не может вычислить неконстантные выражения, ему приходится создавать скрытый код инициализации, выполняющийся до main. Идеология языка C такого не позволяет, поэтому там такое не работает.


Это верно, но не совсем. "Идеология языка С" во многих случаях считает константными выражения, которые не являются константными в реальных окружениях, в реальных ОС. В частности, это относится к адресным константам, например адресам глобальных переменных в ОС семейства *nix. Эти адреса компилятору на стадии компиляции не известны. Такие адреса прописываются в программу "в последний момент" загрузчиком (а не скрытым кодом инициализации, выполняющимся до main). При этом загрузчик может даже выполнять некую базовую арифметику перед прописыванием адреса.

 Профиль  
                  
 
 Re: Язык Си. Парсер для подсветки Си-кода, глобальные переменные
Сообщение16.01.2023, 05:22 


02/10/12
303
TheRuinedMap в сообщении #1577269 писал(а):
Проблема в инициализаторе.

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


Заменил строку инициализации глобальной переменной:
Используется синтаксис C
 -const char *kod = kodirovka[KODIROVKA]; // глобальная, METKA-1 =====
 +const char *kod = "proba";


Это gcc компилирует чисто, и при запуске программа выводит на печать слово proba.
Константа kod инициализируется указателем на константную строку, которая строка лежит где-то в памяти. Но и глобальный массив kodirovka лежит где-то в памяти, и он инициализирован указателями на константные строки, которые тоже лежат где-то в памяти. И индекс глобального массива известен в момент компиляции. Казалось бы, взять по индексу глобального массива указатель на константную строку и присвоить, как в варианте со словом proba, вроде бы почти всё то же самое. Ну ещё массив указателей объявить константным, как написал выше warlock66613:
const char * const kodirovka[] = ...
Он ведь ещё написал, что его код скомпилился онлайн-компилятором.
warlock66613 в сообщении #1577201 писал(а):
oleg_2 в сообщении #1577199 писал(а):
А Вы сами пробовали компилировать?
Да, онлайн-компилятором. Хотя локальным системным сейчас попробовал тоже работают все варианты. А какой у вас компилятор?

 Профиль  
                  
 
 Re: Язык Си. Парсер для подсветки Си-кода, глобальные переменные
Сообщение16.01.2023, 06:14 
Аватара пользователя


28/10/21
99
oleg_2 в сообщении #1577311 писал(а):
TheRuinedMap в сообщении #1577269 писал(а):
Проблема в инициализаторе.

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


Заменил строку инициализации глобальной переменной:
Используется синтаксис C
 -const char *kod = kodirovka[KODIROVKA]; // глобальная, METKA-1 =====
 +const char *kod = "proba";


Это gcc компилирует чисто, и при запуске программа выводит на печать слово proba.
Константа kod инициализируется указателем на константную строку, которая строка лежит где-то в памяти. Но и глобальный массив kodirovka лежит где-то в памяти, и он инициализирован указателями на константные строки, которые тоже лежат где-то в памяти. И индекс глобального массива известен в момент компиляции. Казалось бы, взять по индексу глобального массива указатель на константную строку и присвоить, как в варианте со словом proba, вроде бы почти всё то же самое.


С формальной точки зрения в языке С не работает "казалось бы". Что является константным выражением, а что не является - оговаривается стандартом языка. И доступ к элементу массива не является константным выражением, даже если сам массив константен и индекс задан константой. Поэтому педантичный компилятор не допустит такой инициализации.

Аналогичный пример: язык С не допускает использования оператора "запятая" в константных выражениях. Поэтому

Используется синтаксис C
static int a = (0, 42);
 


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

С практической точки зрения, компиляторам дозволяется расширять их трактовку понятия "константного выражения". Поэтому если GCC не согласится компилировать вышеприведенный пример с "запятой", то Clang таки его спокойно примет. Это известное расширение Clang.

Однако ваш вариант - доступ к элементу массива - ваш компилятор С за константное выражение не признает. Имеет право не признавать.

oleg_2 в сообщении #1577311 писал(а):
Ну ещё массив указателей объявить константным, как написал выше warlock66613:
const char * const kodirovka[] = ...


В языке С (в отличие от С++) ключевое слово const не создает никакой "константности" и никакого отношения к константным выражениям не имеет. Поэтому с педантичной точки зрения пытаться добавлять сюда какие-то const бесполезно. Но тут опять же выходит на сцену самодеятельность компилятора. Теперь уже самодеятельность GCC, а не Clang. GCC позволяет вот такое начиная с версии 8

Используется синтаксис C
const char * const kodirovka[] = {
    "windows-1251", // (0)
    "utf-8",        // (1)
};

const char * const kod = kodirovka[1];
 


Еще раз: это не позволяется формальным портабельным С. Это - расширение понятия "константного выражения", придуманное GCC. Версии GCC до 8 этого расширения не поддерживают и компилировать этот код не будут. Попробуем на Godbolt

GCC 7.4: https://godbolt.org/z/hc7se6d95 - error: initializer element is not constant
GCC 8.1: https://godbolt.org/z/7srjf1MWc - все в порядке.

В качестве еще одного примера: и современный GCC, и современный Clang позволят вам сделать вот такое

Используется синтаксис C
static const int a = 42;
static const int b = a;
 


хотя это формально не позволяется в "педантичном" стандартном С. Для GCC опять же нужна версия 8 или выше, а Clang похоже позволял такое всегда.

oleg_2 в сообщении #1577311 писал(а):
Он ведь ещё написал, что его код скомпилился онлайн-компилятором.


См. выше про GCC начиная с версии 8

 Профиль  
                  
 
 Re: Язык Си. Парсер для подсветки Си-кода, глобальные переменные
Сообщение16.01.2023, 06:56 


02/10/12
303
TheRuinedMap в сообщении #1577316 писал(а):
И доступ к элементу массива не является константным выражением, даже если сам массив константен и индекс задан константой. Поэтому педантичный компилятор не допустит такой инициализации.


Вот теперь понятно. Правда, не очень понятно, зачем было вводить в Си такое ограничение: "И доступ к элементу массива не является константным выражением", но уж что есть то есть.

Проверил Ваши слова: "И доступ к элементу массива не является константным выражением", тест:
код: [ скачать ] [ спрятать ]
Используется синтаксис C
// stroka 1 (опорная строка нумерации строк)


//   /home/test/SI/SI/dxdy/tmp4.c
//   cd /home/test/SI/SI/dxdy/
//   gcc tmp4.c -o tmp4.cgi -Wall -Werror -O3
//   g++ tmp4.c -o tmp4.cgi -Wall -Werror -O3
//   ./tmp4.cgi


#include <stdio.h>
#include <string.h>
#include <stdlib.h>

const char *a = "proba";
const char b = a[3];

//------------ main ------------------

int main()
{
    const char c = b;

    printf("c=%c", c);

    return(0);
}
 

Выдча:
Код:
$ gcc tmp4.c -o tmp4.cgi -Wall -Werror -O3
tmp4.c:16:16: error: initializer element is not constant
const char b = a[3];
                ^
$

Соответствует Вашим словам. Спасибо.

Прошу Вас ответить на такой ещё вопрос. Про определение структур. Пример кода:
код: [ скачать ] [ спрятать ]
Используется синтаксис C
// stroka 1 (опорная строка нумерации строк)


//   /home/test/SI/SI/dxdy/tmp1.c
//   cd /home/test/SI/SI/dxdy/
//   gcc tmp1.c -o tmp1.cgi -Wall -Werror -O3
//   g++ tmp1.c -o tmp1.cgi -Wall -Werror -O3
//   ./tmp1.cgi


#include <stdio.h>
#include <string.h>
#include <stdlib.h>


#if 1  // 1 -вариант-1;  0 -вариант-2

//======== вариант-1   // толко для gcc. ======================
struct s1 {
    struct s2 {
        int a;
        int b;
    } s2;
    int c;
    int d;
};

#else

//======== вариант-2   // и для gcc, и для g++. ================
struct s2 {
    int a;
    int b;
};

struct s1 {
    struct s2 s2;
    int c;
    int d;
};

#endif

//-------------- fun1 ----------------

int fun1(struct s2 *s2)
{
    printf("a=%d\n", s2->a);
    return(0);
}

//-------------- fun2 ----------------

int fun2(struct s1 *s1)
{
    printf("b=%d\n", s1->s2.b);
    return(0);
}

//-------------- fun3 ----------------

int fun3(struct s1 *s1)
{
    printf("c=%d\n", s1->c);
    printf("d=%d\n", s1->d);
    return(0);
}

//------------ main ------------------

int main()
{
    struct s1  s1[1];

    s1->s2.a = 1;
    s1->s2.b = 2;
    s1->c = 3;
    s1->d = 4;

    fun1(&s1->s2);
    fun2(s1);
    fun3(s1);
    exit(0);
}

 

Два варианта определения структуры struct s2. В первом варианте определение struct s2 вложено в определение struct s1. GCC принимает оба варианта, компилирует чисто, выдача при запуске программы, скомпилированной GCC:
Код:
$ gcc tmp1.c -o tmp1.cgi -Wall -Werror -O3
$ ./tmp1.cgi
a=1
b=2
c=3
d=4
$


А G++ вариант-1 не принимает. Выдача G++:
Код:
$ g++ tmp1.c -o tmp1.cgi -Wall -Werror -O3
tmp1.c: In function ‘int fun1(s2*)’:
tmp1.c:48:24: error: invalid use of incomplete type ‘struct s2’
     printf("a=%d\n", s2->a);
                        ^
tmp1.c:46:17: note: forward declaration of ‘struct s2’
int fun1(struct s2 *s2)
                 ^
tmp1.c: In function ‘int main()’:
tmp1.c:80:17: error: cannot convert ‘s1::s2*’ to ‘s2*’ for argument ‘1’ to ‘int fun1(s2*)’
     fun1(&s1->s2);
                 ^
$

Т. е. G++ не видит вложенное определение структуры.

Вопрос: вариант-1 для языка Си соответствует ли правилам языка Си, или это плюшка компилятора GCC и лучше так не делать для верности?

 Профиль  
                  
 
 Re: Язык Си. Парсер для подсветки Си-кода, глобальные переменные
Сообщение16.01.2023, 07:24 
Аватара пользователя


28/10/21
99
oleg_2 в сообщении #1577318 писал(а):
Прошу Вас ответить на такой ещё вопрос. Про определение структур. Пример кода:
код: [ скачать ] [ спрятать ]
Используется синтаксис C
// stroka 1 (опорная строка нумерации строк)


//   /home/test/SI/SI/dxdy/tmp1.c
//   cd /home/test/SI/SI/dxdy/
//   gcc tmp1.c -o tmp1.cgi -Wall -Werror -O3
//   g++ tmp1.c -o tmp1.cgi -Wall -Werror -O3
//   ./tmp1.cgi


#include <stdio.h>
#include <string.h>
#include <stdlib.h>


#if 1  // 1 -вариант-1;  0 -вариант-2

//======== вариант-1   // толко для gcc. ======================
struct s1 {
    struct s2 {
        int a;
        int b;
    } s2;
    int c;
    int d;
};

#else

//======== вариант-2   // и для gcc, и для g++. ================
struct s2 {
    int a;
    int b;
};

struct s1 {
    struct s2 s2;
    int c;
    int d;
};

#endif

//-------------- fun1 ----------------

int fun1(struct s2 *s2)
{
    printf("a=%d\n", s2->a);
    return(0);
}

//-------------- fun2 ----------------

int fun2(struct s1 *s1)
{
    printf("b=%d\n", s1->s2.b);
    return(0);
}

//-------------- fun3 ----------------

int fun3(struct s1 *s1)
{
    printf("c=%d\n", s1->c);
    printf("d=%d\n", s1->d);
    return(0);
}

//------------ main ------------------

int main()
{
    struct s1  s1[1];

    s1->s2.a = 1;
    s1->s2.b = 2;
    s1->c = 3;
    s1->d = 4;

    fun1(&s1->s2);
    fun2(s1);
    fun3(s1);
    exit(0);
}

 

Два варианта определения структуры struct s2. В первом варианте определение struct s2 вложено в определение struct s1. GCC принимает оба варианта, компилирует чисто, выдача при запуске программы, скомпилированной GCC:


В языке С нет понятия "области видимости класса" (class scope). Ваше вложенное объявление типа struct s2 по-прежнему объявляет тип struct s2 на уровне файла. То есть с точки зрения языка С нет никакой разницы между вариантом 1 и вариантом 2. И по всей программе struct s2 ссылается на один и тот же тип.

oleg_2 в сообщении #1577318 писал(а):
Вопрос: вариант-1 для языка Си соответствует ли правилам языка Си, или это плюшка компилятора GCC и лучше так не делать для верности?


Да, вариант 1 совершенно стандартен и никаких "плюшек" GCC в нем не замешано.

oleg_2 в сообщении #1577318 писал(а):
А G++ вариант-1 не принимает. Выдача G++:


C++ - совсем другой язык программирования. В С++ есть понятие "области видимости класса". В первом варианте определение struct s2 определяет вложенный тип s1::s2. А ваши объявления функций ссылаются на некий доселе неизвестный глобальный тип s2, который никакого отношения к вложенному s1::s2 не имеет. Полного определения этого глобального типа s2 вы так никогда и не предоставляете. Отсюда и ошибки, жалующиеся на неполноту типа s2.

А даже если вы бы и предоставили отдельное определение для глобального типа s2, вызвать fun1(&s1->s2); вы все равно не смогли бы из-за несоответствия типов.

 Профиль  
                  
 
 Re: Язык Си. Парсер для подсветки Си-кода, глобальные переменные
Сообщение16.01.2023, 07:55 


02/10/12
303
TheRuinedMap в сообщении #1577322 писал(а):
Да, вариант 1 совершенно стандартен и никаких "плюшек" GCC в нем не замешано.


Большое пасибо.

Прошу Вас или кого-нибудь ответить на такой ещё вопрос по битовым сдвигам. Битовые сдвиги считаются быстрой операцией, но так ли уж быстры сдвиги на много бит, вроде такого:
k = ((buf[3]&255) << 24)
Если сдвиги аппаратно одно-битные, то это 24 сдвига, долго.

И прошу ещё ответить на вопрос: повсеместно распространены 32-битные компьютеры, но то тут то там попадаются упоминания о каких-то мифических 16-битных компьютерах, которые никто никогда не видывал, существуют ли они? Это я спросил потому, что 32 бита хватает для всего или почти для всего, а 16 бит мало.

 Профиль  
                  
 
 Re: Язык Си. Парсер для подсветки Си-кода, глобальные переменные
Сообщение16.01.2023, 08:07 
Аватара пользователя


28/10/21
99
oleg_2 в сообщении #1577326 писал(а):
Прошу Вас или кого-нибудь ответить на такой ещё вопрос по битовым сдвигам. Битовые сдвиги считаются быстрой операцией, но так ли уж быстры сдвиги на много бит, вроде такого:
k = ((buf[3]&255) << 24)
Если сдвиги аппаратно одно-битные, то это 24 сдвига, долго.


Смотрите документацию на свою аппаратную платформу. На современных платформах десктопного уровня время выполнения сдвига обычно не зависит от величины сдвига. То есть это совсем не цикл из сдвигов "по одному биту".

oleg_2 в сообщении #1577326 писал(а):
И прошу ещё ответить на вопрос: повсеместно распространены 32-битные компьютеры, но то тут то там попадаются упоминания о каких-то мифических 16-битных компьютерах, которые никто никогда не видывал, существуют ли они? Это я спросил потому, что 32 бита хватает для всего или почти для всего, а 16 бит мало.


Мало для чего?

"Битность" платформы - это в первую очередь именно размер указателя, то есть размер тривиально непрерывно адресуемого блока памяти. Однако глобальное адресное пространство может быть расширено за счет применения таких трюков как сегментная адресация памяти. Именно так это делалось, например, на x86 во времена DOS и первых версий Windows. Ничего "мифического" в этом нет: это были именно 16-битные платформы.

 Профиль  
                  
 
 Re: Язык Си. Парсер для подсветки Си-кода, глобальные переменные
Сообщение16.01.2023, 08:40 


02/10/12
303
TheRuinedMap в сообщении #1577327 писал(а):
На современных платформах десктопного уровня время выполнения сдвига обычно не зависит от величины сдвига. То есть это совсем не цикл из сдвигов "по одному биту".


Вот спасибо, давно меня мучил этот вопрос.

TheRuinedMap в сообщении #1577327 писал(а):
"Битность" платформы - это в первую очередь именно размер указателя, то есть размер тривиально непрерывно адресуемого блока памяти.

Нет, я имел ввиду sizeof(int), если 32 бита, то даже длину большинства файлов можно записать, а также с битовыми операциями удобно из потока биты выковыривать, о переполнении можно не беспокоиться в большинстве случаев. Вроде бы есть типы int_32 и т. п., но они не подсвечиваются редактором, что ухудшает читаемость и повышает вероятность опечаток, с обычными типами сразу видно, если не подсвечен, значит опечатка.
На сегодня все мои насущные вопросы вроде бы исчерпаны, благодарю всех за просветление.

 Профиль  
                  
 
 Re: Язык Си. Парсер для подсветки Си-кода, глобальные переменные
Сообщение16.01.2023, 20:02 
Аватара пользователя


28/10/21
99
oleg_2 в сообщении #1577208 писал(а):
warlock66613 в сообщении #1577205 писал(а):
По множеству причин. Например у них не будет фиксированного адреса, и как функция узнает где в памяти расположена эта переменная?

Почему это? выделить в стеке место для глобальных, поделить стек на две части, одна для глобальных, другая собственно стек - первым зашёл последним вышел, для локальных.


Так а зачем тогда вообще назвать эту первую часть с глобальными переменными "стеком"?

Память в традиционной архитектуре униформна. В ней нет никакого "стека" или "кучи". Это не более чем заранее оговоренные диапазоны адресов, которым присвоены какие-то "полуслэнговые" названия на уровне джентльменских соглашений. "Стек" - чисто умозрительная концепция. И если вам так больше нравится, вы имеете полное право полагать, что глобальные переменные живут в некоей корневой и постоянной части "стека". От этого ничего не изменится.

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

Для локальных переменных ответ на этот вопрос очевиден и естественен, ибо объявления локальных переменных естественным образом "вплетены" в код функции. Выполняй инициализацию по мере достижения объявлений переменных - и всё. А константная это инициализация или какая-то нетривиальная - значения не имеет. Просто выполняй и все.

А с глобальными переменными как быть? Объявления переменных на уровне файла не "вплетены" ни в какой код. Когда выполнять их инициализацию, если эта инициализация нетривиальна? Язык С решает эту проблему радикально: никогда. Инициализация глобальных переменных (и вообще статических переменных) должна быть константной и тривиальной. То есть, выражаясь условно (и с определенной натяжкой), одна должна делаться "еще на стадии компиляции".

-- 16.01.2023, 09:05 --

oleg_2 в сообщении #1577330 писал(а):
TheRuinedMap в сообщении #1577327 писал(а):
"Битность" платформы - это в первую очередь именно размер указателя, то есть размер тривиально непрерывно адресуемого блока памяти.

Нет, я имел ввиду sizeof(int), если 32 бита, то даже длину большинства файлов можно записать, а также с битовыми операциями удобно из потока биты выковыривать, о переполнении можно не беспокоиться в большинстве случаев. Вроде бы есть типы int_32 и т. п., но они не подсвечиваются редактором, что ухудшает читаемость и повышает вероятность опечаток, с обычными типами сразу видно, если не подсвечен, значит опечатка.


Не вижу проблемы. Максимальная ширина поддерживаемых арифметических типов никак не зависит от разрядности платформы. Просто какие-то типы поддерживаются нативно, а какие-то придется поддерживать на уровне библиотеки времени выполнения. Любая С-платформа обязана поддерживать 32-битные (а после С99 - и 64-битные) целые типы, будь она даже 8-битной на уровне аппаратуры.

 Профиль  
                  
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 38 ]  На страницу Пред.  1, 2, 3  След.

Модераторы: Karan, Toucan, PAV, maxal, Супермодераторы



Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group