Аватар для orcali
0 / 0 / 0
Регистрация: 26.12.2023
Сообщений: 14

Компилятор, препроцессор, язык Си

26.12.2023, 21:49. Показов 2764. Ответов 22

Студворк — интернет-сервис помощи студентам
Всем привет. Стал изучать указатели и возник вопрос, связанный с инициализацией переменных и адресов. Что происходит с компилятором? Решил провести и программу для теста.
Алгоритм такой
1. Создать переменную
2. Выйти из области видимости
3. Создать переменную
4. Вернуться в область видимости
5. Проверить адрес
Программа работает как и ожидалось, смещение в стеке 4 байта, но если повторить итерацию,
то адреса дадут неожиданный результат, что сломало мне мозг. Для объяснении проблемы выведу адресацию
в таком стиле X+0.

Алгоритм выглядит так:
инициализация X+0(имя переменной = i)
выход из {}
инициализация другой переменной, где ей дают X+4(потому что int занимает в стэке 4 байта, если я правильно понимаю)
вход в {}, где снова инициализируется i, и ей снова дается адрес X+0
инициализация переменной i в другой области видимости{}, где ей даётся адрес X+8
но прикол в том, что на этот раз, программа выдала адреса другим образом.
Ожидалось адресация X+0, X+4, X+8 и т.д.,
но она выдала X+0, X+8, X+4. Вопрос почему?
Второй вопрос, как компилятор хранит переменные. Почему он понимает, что в одном месте к переменной X я обращаюсь по адресу X+0, а в другом месте к переменной Х, я обращаюсь по адресу X+N?
Программа написана таким алгоритмом:
C
1
2
3
4
5
for(int fori = 0; fori < 3; fori++){
    if(fori == 1){инициализация j}
    if(fori == 2 {инициализация i}
    for(инициализация i){}
}
Добавлено через 1 минуту
Вот полный код
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#include <stdio.h>
#define GETTABLE(DATA)\
    printf("\naddress("#DATA")\t\t%d\
        \nvariable("#DATA")\t\t%d\
        \ndata("#DATA")\t\t%d", &DATA, DATA, *DATA);
 
int main(void){
 
    int *p1, *p2;
    printf("int=%d", sizeof(int));
    for(int fori = 0; fori < 3; fori++){
        if(fori == 1){
            int j = 51;
            p2 = &j;
            GETTABLE(p2);
        }
        if(fori == 2){
            int i = 3333;
            p2 = &i;
            GETTABLE(p2);
        }
 
        for(int i = fori; i < 10; i++){
            if(i == fori){
                p1 = &i;
                GETTABLE(p1);
            }
        }
        GETTABLE(p1);
    }
    
    return 0;
}
Добавлено через 1 час 1 минуту
Решил дописать код только что. У меня появилась теория, что инициализация переменных идет либо в порядке исполнения, либо с конца кода программы. Добавил 3 и 4ый указатель.
Алгоритм инициализации:
p2 p3 p4 p1 если рассматривать с точки зрения кода
p1 p2 p4 p3 если рассматривать с точки зрения исполнения программы. Адресация не соответствует ожиданиям
x+0 x+12 x+4 x+8
если рассматривать адресацию слева-направо и справа-налево с точки зрения кода и исполнения, это невозможно ни при каких обстоятельствах.
Как и нелогичное поведение программы
C
1
printf("%d %d %d %d" i, i++, ++i, i)
, где результат программы зависит от компилятора.

Добавлено через 9 минут
Всё. Я разобрался в теме. Инициализация переменных идет снизу вверх, не по алгоритму, а снизу вверх по коду. Просчитался.
C
1
2
3
4
if(p2=вторая инициализация по алгоритму)
if(p3=четвертая инициализация)
if(p4=третья инициализация)
for(p1=первая инициализация)
адресация выстроилась таким образом
p1, p4, p3, p2
0
Лучшие ответы (1)
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
26.12.2023, 21:49
Ответы с готовыми решениями:

Как настроить компилятор Visual Studio 2017 на язык Си?
В свойствах проекта меняю на компилировать на си, после запуска отладки выходит ошибка и открывается новый проект corecrt_wconio.h и т. д....

Русский язык в консоли Windows 10. IDE: CodeLite. Компилятор: TDM-GCC-32
Здравствуйте. Windows 10. IDE: CodeLite. Компилятор: TDM-GCC-32 В файле main.cpp такой код: #include &lt;iostream&gt; #include...

Ассемблер - это макропроцессор, транслятор, препроцессор, интерпретатор, компилятор, кросскомпилятор или транслитератор?
макропроцессор транслятор препроцессор интерпретатор компилятор кроскомпилятор транслитератор ??

22
Просто Лис
Эксперт Python
 Аватар для Рыжий Лис
5973 / 3735 / 1099
Регистрация: 17.05.2012
Сообщений: 10,791
Записей в блоге: 9
31.12.2023, 15:29
Студворк — интернет-сервис помощи студентам
Цитата Сообщение от assemberist Посмотреть сообщение
Кроме того можно видеть что i6 = i7. Это похоже на оптимизацию, (создание-удаление переменных на стеке выполняется с помощью push-pop команд).
Про push-pop сомневаюсь, всегда считал, что компилятор высчитывает в compile time количество памяти под локальные переменные, а уже в run time в прологе функции выделяется память на стеке. Единожды.

А так похоже на оптимизацию, область видимости одной переменной кончилась (и её lifetime), значит место свободное, можно переиспользовать.
0
913 / 339 / 135
Регистрация: 18.07.2017
Сообщений: 1,485
31.12.2023, 18:34
Цитата Сообщение от Рыжий Лис Посмотреть сообщение
Про push-pop сомневаюсь
Может и так, я больше с микроконтроллерами на уровне ассемблера работал, там встречал подобное.
0
Просто Лис
Эксперт Python
 Аватар для Рыжий Лис
5973 / 3735 / 1099
Регистрация: 17.05.2012
Сообщений: 10,791
Записей в блоге: 9
31.12.2023, 18:51
В x86_64 в прологе функции сохраняется указатель на вершину стека, потом выделяется кадр функции. В эпилоге функции кадр функции "схлопывается".

Assembler
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
; сохранить регистр, плюс выравнивание стека по границе 16 бит
push rbp
; push остальные регистры, которые может испортить функция
; сохранить указатель на вершину стека
mov rbp, rsp
; к переменным можно будет обратиться как [rbp-0], [rbp-4]...
; 56 байт для локальных переменных
sub rsp, 56
; ...
; тело функции
; ...
; восстанавливается указатель на вершину стека
mov rsp, rbp
; pop восстанавливаются регистры
pop rbp
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
31.12.2023, 18:51

Компилятор с языка PL/1 на язык Ассемблер
Подскажите как написать компилятор на языке Си. Может быть есть примеры какие-нибудь, книги понятные. Начинала читать Ахо, Ульмана, как то...

Можно ли сделать язык(компилятор к нему тоже), который бы не зависел от ОС и програмного обеспечения?
Можно ли сделать язык(компилятор к нему тоже), который бы не зависел от ОС и програмного обеспечения? Может работать, как PHP, или ASP

Препроцессор
Профессионалы, ответте вот на какой вопрос: Мне необходимо получить файл, который образуется после обработки препроцессором, т.е....

Препроцессор
Можно ли как-нибудь исходный файл .с пропустить только через препроцесоор и получить результат?

Препроцессор
Задание: В function.cpp описать функции Вfunction.h описать прототипы, создать проверку(#ifndef) и определить имена...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
23
Ответ Создать тему
Опции темы

Новые блоги и статьи
Hyper-V: Компьютер должен поддерживать доверенный платформенный модуль 2.0.
Maks 31.08.2026
При установке Windows 11 на виртуальную машину Hyper-V 2-го поколения вылезла такая ошибка: Решение: в параметрах виртуальной машины, в разделе "Безопасность" (Security) активировать флаг. . .
Архитектура биовида Стива в Майнкрафте: Зачем бонобо кубический каннибализм
anaschu 30.08.2026
Кубический Вагинокапитализм в Minecraft: Математический инвариант ОДУ и рок Стивов-бонобо Главная задача разработанной «Модели Всего» — наглядно продемонстрировать наличие системной «судьбы». . .
Оттачиваю умение писать js программы.
russiannick 30.08.2026
Проектом выходного дня стало написание Книги шифров Виженера. Итогом стала версия 200, синий туман. Синий туман назван так, потому что замораживает текст под собой. Нажатие синих кнопок управляют. . .
мат медиц модель 30. презентация проекта
anaschu 27.08.2026
хоп хоп хоп хидахоп, а я кладую))
Как у меня протекала болезнь
zorxor 27.08.2026
Здравствуйте, друзья! Эта запись блога предназначена именно для вас - для моих дорогих друзей, которые знали меня лично. Чтобы ответить на вопрос - а что же со мной произошло на самом деле? Я учился. . .
Нашел вот забавное видео о измерениях. Лучшее что я видел на эту тему
kumehtar 26.08.2026
ILETXiw9bMQ Основная суть и тезисы по измерениям: 0D (Нулевое измерение): точка, не имеющая длины, ширины, высоты или объема. Объект не может перемещаться в 0D. 1D (Первое измерение):. . .
[EasyBuilder Pro] Памятка по разработке для панелей Weintek
ФедосеевПавел 26.08.2026
Памятка по разработке для панелей Weintek ВВЕДЕНИЕ Ранее, при реализации проектов основное внимание уделял разработке управляющей программы для контроллера, а панели оператора доставалось время. . .
Модель по догадкам
anaschu 25.08.2026
Прошло две недели. Я уже рассказывал, как разговаривал с сотрудниками у сортировки и как понял, что главная ветка — не про приёмку, а про отбор. Но тогда я думал, что понял механику. На этой неделе я. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru