Вопрос

Вчера вечером мне задали вопрос на языке 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.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top