Вчера вечером мне задали вопрос на языке C, и я не знал ответа, так как я не использовал язык C со времен колледжа, поэтому я подумал, что, может быть, я смогу найти ответ здесь, вместо того, чтобы просто забыть об этом.
Если у человека есть такое определение, как:
#define count 1
Может ли этот человек найти имя переменной count, используя 1 внутри него?
Я так не думал, так как думал, что счет будет указывать на 1, но не понимаю, как 1 может указывать обратно на счет.





Что вы имеете в виду под словом «поиск»?
Линия
#define count 1
определяет символ «счетчик», имеющий значение 1.
Первый шаг процесса компиляции (называемый предварительной обработкой) заменит каждое вхождение счетчика символов на 1, так что если у вас есть:
if (x > count) ...
он будет заменен на:
if (x > 1) ...
Если вы это поймете, вы поймете, почему «нахождение счета» бессмысленно.
#define - это директива препроцессора, поэтому она не является «переменной».
C определяет директиву препроцессора, а не переменную. Перед компиляцией препроцессор просмотрит ваш файл C и заменит место, где вы пишете count, на то, как вы его определили. Посмотрите на запутанные записи конкурса C для некоторых особенно просвещенных случаев использования этой и других директив препроцессора.
Дело в том, что нет «счетчика», указывающего на значение «1». Это просто простая операция / найти замену, которая происходит до, код даже действительно скомпилирован.
Я оставлю это редактируемым для того, кто действительно знает C.
Can that person find the variable name "count" using the 1 that is inside it?
Нет
Ответ прост: нет, они не могут. # Определения, подобные этому, обрабатываются препроцессором, и они указывают только в одном направлении. Конечно, другая проблема заключается в том, что даже компилятор не узнает - поскольку «1» может указывать на что угодно, - несколько переменных могут иметь одно и то же значение одновременно.
Я уверен, что кто-то более красноречивый и сведущий, чем я, укажет, что # define'd вещи не скомпилированы в исходный код, у вас есть макрос препроцессора, который будет проходить через исходный код и изменять все экземпляры 'count 'находит с' 1 '.
Однако, чтобы пролить больше света на вопрос, который вам задали, поскольку C - это скомпилированный язык вплоть до машинного кода, у вас никогда не будет отражения и самоанализа, которые есть в таких языках, как Java или C#. Все имена теряются после компиляции, если у вас нет фреймворка, построенного вокруг вашего источника / компилятора, чтобы делать какие-то изящные вещи.
Надеюсь, что это поможет. (извините за каламбур)
То, что у вас есть, на самом деле не переменная, это директива препроцессора. Когда вы скомпилируете код, препроцессор выполнит замену всех экземпляров слова count в этом файле на 1.
Вы можете спросить, знаю ли я, 1 могу ли я найти, что количество указывает на это? Нет. Поскольку связь между именами переменных и значениями не является взаимно однозначной, пути назад нет. Рассматривать
int count = 1;
int count2 = 1;
совершенно законно, но на что я должен решиться?
Основываясь на ответе @Cade Roux, если вы используете препроцессор #define для связывания значения с символом, код не будет иметь ссылки на символ после запуска препроцессора:
#define COUNT (1)
...
int myVar = COUNT;
...
После запуска препроцессора:
...
int myVar = (1);
...
Как отмечали другие, это в основном означает «нет» по вышеуказанной причине.
В общем нет.
Во-первых, #define - это не переменная, это макрос препроцессора компилятора.
К тому времени, как основная фаза компилятора приступит к работе, имя будет заменено значением, а имя «count» не будет существовать нигде в скомпилированном коде.
Для переменных невозможно узнать имена переменных в коде C во время выполнения. Эта информация не сохраняется. В отличие от таких языков, как Java или C#, C вообще не хранит много метаданных при компиляции до языка ассемблера.
Директивы, начинающиеся с "#", обрабатываются препроцессором, который обычно выполняет замену текста перед передачей кода в "настоящий" компилятор. Таким образом, нет переменной с именем count, это как если бы все строки «count» в вашем коде волшебным образом заменялись строкой «1».
Так что нет никакой возможности найти эту «переменную».
В случае макроса он предварительно обрабатывается, и результирующий вывод компилируется. Таким образом, это абсолютно не способ узнать это имя, потому что после того, как препроцессор завершит свою работу, результирующий файл будет содержать «1» вместо «count» везде в файле.
Так что ответ отрицательный.
К сожалению, это невозможно.
Операторы #define - это инструкции для препроцессора, все экземпляры count заменяются на 1. Во время выполнения нет области памяти, связанной с count, поэтому усилия, очевидно, бесполезны.
Даже если вы используете переменные, после компиляции в программе не останется остатков исходных идентификаторов. Обычно это возможно только в динамических языках.
Если они смотрят на исходный код C (который они будут в отладчике), они увидят что-то вроде
int i = count;
в этот момент они могут поискать и найти строку
#define count 1
Если, однако, все, что у них есть, это переменная iDontKnowWhat, и они видят, что она равна 1, нет никакого способа отследить ее до «count».
Почему? Поскольку #define оценивается во время препроцессора, что происходит еще до компиляции (хотя почти для всех это можно рассматривать как первый этап компиляции). Следовательно, исходный код - это единственное, что имеет какую-либо информацию о «счетчике», например, знает, что он когда-либо существовал. К тому времени, когда компилятор заглянет внутрь, каждая ссылка на «count» будет заменена числом «1».
Это не указатель, это просто подстановка строки / токена. Препроцессор заменяет все #define перед компиляцией вашего кода. Большинство компиляторов включают аргумент -E или аналогичный для выдачи предварительно скомпилированного кода, поэтому вы можете видеть, как выглядит код после обработки всех #directives.
Если говорить более конкретно о вашем вопросе, невозможно сказать, что токен заменяется в коде. Ваш код даже не может отличить (count == 1) от (1 == 1).
Если вы действительно хотите это сделать, это можно сделать с помощью анализа текста исходного файла, скажем, с помощью инструмента сравнения.
Один из приемов, используемых в C, заключается в использовании синтаксиса # в макросах для получения строкового литерала параметра макроса.
#define displayInt(val) printf("%s: %d\n",#val,val)
#define displayFloat(val) printf("%s: %d\n",#val,val)
#define displayString(val) printf("%s: %s\n",#val,val)
int main(){
int foo=123;
float bar=456.789;
char thud[] = "this is a string";
displayInt(foo);
displayFloat(bar);
displayString(thud);
return 0;
}
Результат должен выглядеть примерно так:
foo: 123
bar: 456.789
thud: this is a string
Возможно, в нем нет прямого ответа на вопрос, но я нашел его полезным, ясным и полезным для меня.
Человек, задававший вопрос (был ли это вопрос интервью?), Возможно, пытался заставить вас различать использование констант #define и перечислений. Например:
#define ZERO 0
#define ONE 1
#define TWO 2
против
enum {
ZERO,
ONE,
TWO
};
Учитывая код:
x = TWO;
Если вы используете перечисления вместо #defines, некоторые отладчики смогут показать вам символьную форму значения TWO вместо просто числового значения 2.
count не является переменной. Для него нет выделенной памяти и нет записи в таблице символов. Это макрос, который заменяется препроцессором перед передачей исходного кода компилятору.
Если вы задаете не совсем правильный вопрос, есть способ получить имя с помощью макроса:
#define SHOW(sym) (printf(#sym " = %d\n", sym))
#define count 1
SHOW(count); // prints "count = 1"
Оператор # преобразует аргумент макроса в строковый литерал.
#define count 1 - очень плохая идея, потому что он не позволяет вам присвоить имя каким-либо переменным или полям структуры count.
Например:
void copyString(char* dst, const char* src, size_t count) {
...
}
Ваш макрос count приведет к замене имени переменной на 1, что предотвратит компиляцию этой функции:
void copyString(char* dst, const char* src, size_t 1) {
...
}
Это была ссылка на вопрос, на который я только что отвечал, об использовании this в конструкторе.