Допустим ли доступ к статическому значению с помощью глобальной переменной-указателя? - PullRequest
0 голосов
/ 13 января 2019

Могу ли я получить доступ к статической переменной, используя глобальный указатель?

//In main.c file
static int c = 20; #Static vairble 
int *ptr = &c; #Global pointer variable
int main(){
  fun();
  printf("%d\n", c);
}

//In sub.c file
extern int *ptr;
void fun(){
  ++*ptr;
}

Когда я попытался получить доступ к глобальной переменной * ptr с помощью ключевого слова extern в другом файле, я смог получить доступ к статической переменной c, и даже изменения, внесенные в * ptr, отражаются на c в файле main.c

  1. Почему «ptr» не теряет свое глобальное свойство даже после присвоения ему статическим адресом переменной?

  2. Хранятся ли статические и глобальные данные в двух разных сегментах памяти или они совместно используют один и тот же сегмент данных?

  3. Могут ли глобальные переменные хранить непостоянные значения?

Ответы [ 4 ]

0 голосов
/ 13 января 2019

Почему «ptr» не теряет свое глобальное свойство даже после присвоения ему по статическому адресу переменной?

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

Статические и глобальные хранятся в двух разных сегментах памяти или они оба используют один и тот же сегмент данных в памяти?

Как правило, они находятся в одном сегменте данных.

https://www.geeksforgeeks.org/memory-layout-of-c-program/

Могут ли глобальные переменные хранить непостоянные значения?

да, как и любая другая переменная, поэтому имя "переменная"

0 голосов
/ 13 января 2019

Вы путаете связь переменной-указателя и связь того, на что она указывает * на 1002 *.

Связывание указателя не изменяется независимо от того, на что он указывает.

Здесь связь из ptr равна global (она же external ), а связь c равна static (она же ) внутренний ). Ни один из них не меняет связи другого.

static означает, что c будет не будет видимым (т. Е. Доступно для прямой связи) в другом (например,) .c файле. То есть другой .c может не сделать:

int *ptr2 = &c;

Но, это может сделать:

int **ptr3 = &ptr;

Вы могли бы иметь обратное:

int c = 20;
static int ptr = &c;

Это static / внутренняя связь ptr, указывающая на глобальную / внешнюю связь c.

Программа имеет несколько областей памяти: .text для кода. .data для инициализированных переменных (таких как c) и .bss для унифицированных областей.

Поскольку вы инициализируете оба ptr и c, они оба заканчиваются в .data

Если вы сделали:

#include <stdio.h>

static int c = 20; // Static vairble
int *ptr;

int main(){
    ptr = &c;
    return 0;
}

Затем c инициализируется и входит в .data, но ptr не инициализируется , но назначается и входит в .bss сегмент

Все переменные [глобальные или нет] могут иметь непостоянные значения. Либо путем инициализации или назначения.

Все вышеперечисленные переменные имеют глобальный / файл scope .

Вот еще один тип области действия:

#include <stdio.h>

static int c = 20; // Static vairble

int main(){
    int *ptr = &c;
    return 0;
}

Здесь ptr имеет function scope. Он помещается в кадр стека main. Он не имеет связи, о которой можно говорить (то есть он никогда не будет отображаться в таблице символов исполняемого файла).

0 голосов
/ 13 января 2019

Почему «ptr» не теряет свое глобальное свойство даже после присвоения ему по статическому адресу переменной?

Переменная не может «потерять» свою область видимости или класс хранения, спецификатор класса связи static определяет видимость символа, а не где и как он хранится. Он предотвращает обращение к данным через этот символ , не препятствует ссылкам указателя на то же место. C - язык системного уровня - как таковой он не мешает вам делать практически все, что можно сделать на уровне архитектуры.

Статические и глобальные хранятся в двух разных сегментах памяти или они оба используют один и тот же сегмент данных в памяти?

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

При этом инициализированные данные статического хранилища помещаются в секцию компоновщика, отличную от нуля или неинициализированных данных. Это облегчает инициализацию при запуске.

Могут ли глобальные переменные хранить непостоянные значения?

Возможно, это заслуживает отдельного вопроса, чтобы объяснить, почему вы можете думать иначе - это кажется не связанным с вашими другими вопросами, но оставленным без внимания. В вашем собственном примере ptr хранит &c, но его можно изменить во время выполнения, чтобы указать в другом месте.

0 голосов
/ 13 января 2019

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

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

Итак, ваша конструкция верна.

Можно просто подчиниться «фиаско статического порядка инициализации», когда другие единицы перевода вытягивают копии вашего ptr (возможно, до того, как это было указано на c). Рассмотрим, например, что может произойти, если в области видимости файла содержится другой модуль перевода ...

extern int *ptr;
int *myPtr = ptr;
...
int main() {
   int x = *myPtr;
}
...