Нахождение имени переменной в C
-
02-07-2019 - |
Вопрос
Вчера вечером мне задали вопрос на языке C, и я не знал ответа, так как я не часто использовал C со времен колледжа, поэтому я подумал, что, возможно, я смогу найти ответ здесь, а не просто забыть об этом.
Если у человека есть такие определения, как:
#define count 1
Может ли этот человек найти имя переменной count
используя цифру 1, которая находится внутри него?
Я так не думал, поскольку думал, что счет будет указывать на 1, но не понимал, как 1 может указывать обратно на счет.
Решение
Простой ответ: нет, не могут.#Подобные определения обрабатываются препроцессором и указывают только в одном направлении.Конечно, другая проблема заключается в том, что даже компилятор не будет знать (поскольку «1» может указывать на что угодно), что несколько переменных могут иметь одно и то же значение одновременно.
Другие советы
Основываясь на ответе @Cade Roux, если вы используете препроцессор #define для связывания значения с символом, код не будет иметь никакой ссылки на символ после запуска препроцессора:
#define COUNT (1)
...
int myVar = COUNT;
...
После запуска препроцессора:
...
int myVar = (1);
...
Как уже отмечали другие, это в основном означает «нет» по вышеуказанной причине.
Может ли этот человек найти имя переменной «count», используя единицу, находящуюся внутри нее?
Нет
Поскольку я уверен, что кто-то более красноречивый и сведущий, чем я, укажет, что вещи #define'd не компилируются в исходный код, у вас есть макрос препроцессора, который будет проходить через исходный код и изменять все экземпляры 'count ' он находит с '1'.
Однако, чтобы пролить больше света на вопрос, который вам задали, поскольку C — это компилируемый язык вплоть до машинного кода, у вас никогда не будет тех размышлений и самоанализа, которые есть в таких языках, как Java или C#.Все имена теряются после компиляции, если только у вас нет структуры, построенной вокруг вашего исходного кода/компилятора и позволяющей делать какие-то изящные вещи.
Надеяться этот помогает.(простите за каламбур)
К сожалению, это невозможно.
#define
операторы являются инструкциями для препроцессора, все экземпляры count
заменяются на 1
.Во время выполнения нет никакой ячейки памяти, связанной с count
, поэтому усилия явно бесполезны.
Даже если вы используете переменные, после компиляции не останется остатков исходных идентификаторов, использованных в программе.Обычно это возможно только в динамических языках.
Один трюк, используемый в 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 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) {
...
}
Определения C — это директива препроцессора, а не переменная.Препроцессор просмотрит ваш файл C и заменит место, где вы пишете count, на то, что вы определили перед компиляцией.Посмотрите запутанные записи конкурса C, чтобы узнать о некоторых особенно содержательных способах использования этой и других директив препроцессора.
Дело в том, что не существует счетчика, указывающего на значение «1».Это просто простая операция поиска/замены, которая происходит до код даже действительно скомпилирован.
Я оставлю это редактируемым для тех, кто действительно знает C, чтобы он мог исправить.
count
не является переменной.Ему не выделена память и нет записи в таблице символов.Это макрос, который заменяется препроцессором перед передачей исходного кода компилятору.
Если вы задаете не совсем правильный вопрос, есть способ получить имя с помощью макроса:
#define SHOW(sym) (printf(#sym " = %d\n", sym))
#define count 1
SHOW(count); // prints "count = 1"
А #
Оператор преобразует аргумент макроса в строковый литерал.
#define
это директива препроцессора, поэтому она не является «переменной»
На самом деле у вас есть не переменная, а директива препроцессора.Когда вы скомпилируете код, препроцессор заменит все вхождения слова «count» в этом файле на 1.
Вы можете спросить, знаю ли я, могу ли я найти, что этот счетчик указывает на это?Нет.Поскольку связь между именами и значениями переменных не является биекцией, пути назад нет.Учитывать
int count = 1;
int count2 = 1;
совершенно законно, но что мне следует решить?
В общем, нет.
Во-первых, #define — это не переменная, а макрос препроцессора компилятора.
К моменту начала работы основного этапа компилятора имя будет заменено значением, и имя «count» не будет существовать нигде в компилируемом коде.
Что касается переменных, невозможно узнать имена переменных в коде C во время выполнения.Эта информация не сохраняется.В отличие от таких языков, как Java или C#, C вообще не хранит много метаданных и компилируется в язык ассемблера.
Директивы, начинающиеся с «#», обрабатываются препроцессором, который обычно выполняет замену текста перед передачей кода «настоящему» компилятору.Таким образом, не существует переменной с именем count, все строки «count» в вашем коде волшебным образом заменяются строкой «1».
Так что нет, нет способа найти эту «переменную».
В случае макроса он предварительно обрабатывается, и полученный результат компилируется.Таким образом, узнать это имя абсолютно невозможно, потому что после того, как препроцессор завершит свою работу, результирующий файл будет содержать «1» вместо «count» повсюду в файле.
Итак, ответ — нет.
Если они посмотрят исходный код C (который будет в отладчике), то увидят что-то вроде
int i = count;
в этот момент они могут выполнить поиск и найти строку
#define count 1
Однако если все, что у них есть, это переменная iDontKnowWhat, и они видят, что она содержит 1, нет никакого способа отследить ее до «count».
Почему?Потому что #define вычисляется во время препроцессора, что происходит еще до компиляции (хотя почти для всех это можно рассматривать как первый этап компиляции).Следовательно, исходный код — это единственное, что содержит какую-либо информацию о «счетчике», например, о том, что он когда-либо существовал.К тому времени, когда компилятор заглянет в программу, каждая ссылка на «count» будет заменена цифрой «1».
Это не указатель, это просто замена строки/токена.Препроцессор заменяет все #define еще до компиляции вашего кода.Большинство компиляторов включают аргумент -E или аналогичный для выдачи предварительно скомпилированного кода, поэтому вы можете увидеть, как выглядит код после обработки всех #директив.
Если говорить непосредственно о вашем вопросе, невозможно определить, что токен заменяется в коде.Ваш код даже не может определить разницу между (count == 1) и (1 == 1).
Если вы действительно хотите это сделать, это можно сделать с помощью анализа текста исходного файла, скажем, с помощью инструмента сравнения.
Что вы подразумеваете под словом «найти»?
Линия
#define count 1
определяет символ «count», имеющий значение 1.
На первом этапе процесса компиляции (называемом предварительной обработкой) каждое появление количества символов будет заменено на 1, так что если у вас есть:
if (x > count) ...
его заменит:
if (x > 1) ...
Если вы это поймете, вы поймете, почему «найти счетчик» бессмысленно.
Человек, задавший вопрос (был ли это вопрос на собеседовании?), возможно, пытался заставить вас различать использование констант #define и перечислений.Например:
#define ZERO 0
#define ONE 1
#define TWO 2
против
enum {
ZERO,
ONE,
TWO
};
Учитывая код:
x = TWO;
Если вы используете перечисления вместо #defines, некоторые отладчики смогут показать вам символическую форму значения TWO, а не просто числовое значение 2.