首页 \ 问答 \ C程序将变量名称作为输入和打印值(C program to get variable name as input and print value)

C程序将变量名称作为输入和打印值(C program to get variable name as input and print value)

我有一个程序test.c

int global_var=10;
printf("Done");

我做到了

gcc -g test.c -o test

我的查询是否有一种方法可以将变量名称作为参数(比如“global_var”)并打印该值。

谢谢


I have a program test.c

int global_var=10;
printf("Done");

i did

gcc -g test.c -o test

My query is Is there a way i can get the variable name as argument (say "global_var") and print the value.

Thanks


原文:https://stackoverflow.com/questions/25198322
更新时间:2019-12-03 09:46

最满意答案

通常,不可能在运行时按名称访问全局变量。 有时,它可能取决于操作系统以及如何调用编译器。 我仍然假设您要取消引用全局变量,并且您知道它的类型。

然后在Linux和其他一些系统上,你可以使用带有NULL路径的dlopen(3) (获取可执行文件的句柄),然后在全局变量名上使用dlsym来获取它的地址; 然后,您可以将void*指针强制转换为适当类型的指针并取消引用它。 请注意,您需要知道类型(或者至少有一个约定来对其名称中的变量类型进行编码; C ++正在使用名称修改 )。 如果您使用调试信息(即使用gcc -g )进行编译和链接,则类型信息位于ELF可执行文件的DWARF部分中,因此可以通过某种方式获取它。

如果使用-rdynamic-ldl链接可执行文件,则此方法有效

另一种可能性是使用您自己的MELT扩展来定制您最近的GCC ,该扩展将记住并稍后重新使用一些编译器内部表示(即与全局变量相关的GCC )。 使用MELT register_finish_decl_first函数在声明上注册处理程序。 但这需要一些工作(编码MELT扩展)。


使用预处理器技巧

您可以使用(可移植的)预处理器技巧来实现您的目标(在运行时按名称访问变量)。

最简单的方法可能是定义和遵循您自己的约定。 例如,您可以拥有自己的globvar.def头文件,其中只包含类似的行

 /* file globvar.def */
 MY_GLOBAL_VARIABLE(globalint,int)
 MY_GLOBAL_VARIABLE(globalint2,int)
 MY_GLOBAL_VARIABLE(globalstr,char*)
 #undef MY_GLOBAL_VARIABLE

并且您采用所有全局变量都在上面的globvar.def文件中的globvar.def 。 然后你会多次 #include "globvar.def" 。 例如,在全局标题中,将MY_GLOBAL_VARIABLE展开为某些extern声明:

 /* in yourheader.h */
 #define MY_GLOBAL_VARIABLE(Nam,Typ) extern Typ Nam;
 #include "globvar.def"

在你的main.c你需要一个类似的技巧来声明你的全局变量。

在其他地方,您可以定义一个函数来按名称获取整数变量:

 /* return the address of  global int variable or else NULL */
 int* global_int_var_by_name (const char*name) {
    #define MY_GLOBAL_VARIABLE(Nam,Typ) \
      if (!strcmp(#Typ,"int") && !strcmp(name,#Nam)) return (int*)&Nam;
    #include "globvar.def"
      return NULL;
 }

等等......我正在使用宏参数的字符串化

这样的预处理器技巧纯粹是标准C,可以与任何符合C99的编译器一起使用。


In general, it is not possible to access at runtime global variables by name. Sometimes, it might depend upon the operating system, and how the compiler is invoked. I still assume you want to dereference a global variable, and you know its type.

Then on Linux and some other systems, you could use dlopen(3) with a NULL path (to get a handle for the executable), then use dlsym on the global variable name to get its address; you can then cast that void* pointer to a pointer of the appropriate type and dereference it. Notice that you need to know the type (or at least have a convention to encode the type of the variable in its name; C++ is doing that with name mangling). If you compiled and linked with debug information (i.e. with gcc -g) the type information is in its DWARF sections of your ELF executable, so there is some way to get it.

This works if you link your executable using -rdynamic and with -ldl

Another possibility might be to customize your recent GCC with your own MELT extension which would remember and later re-use some of the compiler internal representations (i.e. the GCC Tree-s related to global variables). Use MELT register_finish_decl_first function to register a handler on declarations. But this will require some work (in coding your MELT extension).


using preprocessor tricks

You could use (portable) preprocessor tricks to achieve your goals (accessing variable by name at runtime).

The simplest way might be to define and follow your own conventions. For example you could have your own globvar.def header file containing just lines like

 /* file globvar.def */
 MY_GLOBAL_VARIABLE(globalint,int)
 MY_GLOBAL_VARIABLE(globalint2,int)
 MY_GLOBAL_VARIABLE(globalstr,char*)
 #undef MY_GLOBAL_VARIABLE

And you adopt the convention that all global variables are in the above globvar.def file. Then you would #include "globvar.def" several times. For instance, in your global header, expand MY_GLOBAL_VARIABLE to some extern declaration:

 /* in yourheader.h */
 #define MY_GLOBAL_VARIABLE(Nam,Typ) extern Typ Nam;
 #include "globvar.def"

In your main.c you'll need a similar trick to declare your globals.

Elsewhere you might define a function to get integer variables by name:

 /* return the address of  global int variable or else NULL */
 int* global_int_var_by_name (const char*name) {
    #define MY_GLOBAL_VARIABLE(Nam,Typ) \
      if (!strcmp(#Typ,"int") && !strcmp(name,#Nam)) return (int*)&Nam;
    #include "globvar.def"
      return NULL;
 }

etc etc... I'm using stringification of macro arguments.

Such preprocessor tricks are purely standard C and would work with any C99 compliant compiler.

2014-08-08

相关问答

更多

inf输出计算线斜率(inf output computing line slopes)

这一行: LineSeg1 = ((pointB[1]-pointA[1])/(pointB[0]-pointB[0])); 有一个除零误差。 我相信这个等式应该是: LineSeg1 = ((pointB[1]-pointA[1])/(pointB[0]-pointA[0])); This line: LineSeg1 = ((pointB[1]-pointA[1])/(pointB[0]-pointB[0])); has a divide by zero error. I believ

OutputCache排除Mvc 4中的布局(OutputCache exclude Layout in Mvc 4)

甜甜圈缓存和甜甜圈洞做类似的事情,只是尝试这个例子http://www.dotnet-tricks.com/Tutorial/mvc/ODJa210113-Donut-Caching-and-Donut-Hole-Caching-with-Asp.Net-MVC -4.html Donut Caching and Donut Hole does similar thing, just try this example http://www.dotnet-tricks.com/Tutorial/m

Keras:flow_from_directory在fit_generator调用期间保存了太多图像(Keras: flow_from_directory saving too many images during fit_generator call)

fit_generator函数有两个额外的参数,可能是观察到的行为的原因: 默认值为=1意味着将使用额外的线程来加载图像。 线程将从提供的生成器中获取图像并将它们放入队列中。 max_queue_size ,默认值=10是此队列的最大长度。 当对fit_generator的调用返回时, fit_generator线程将停止,但在它继续用图像填充队列之前,即使其中一些不再需要,也会停止。 The fit_generator function has two additional parameter

访问属性Javascript的属性(Access property of a property Javascript)

这里有点小提琴 。 var indexes = [1, 3, 5]; var Obj_1 = {'100':[3,183,1],'200':[101,5,2,179],'300':[1,11]}; var Obj_2 = { }; var needle = 0; for (var i in indexes) { needle = indexes[i]; Obj_2['' + needle] = { }; for (var prop_1 in Obj_1) {

尝试将SQL中的值转换为Unix时间戳(Trying to convert values in SQL to Unix Timestamp)

在这里粘贴答案,因为我之前无法回答,因为我的帐户太新了。 好的语法错误最终是为UPDATE不喜欢的列字段添加引号。 删除那些给了我NULL值但查询运行。 然后我发现我必须在SELECT函数中包装时间戳转换。 这是我成功转换所有字段的代码: UPDATE wp_6222_postmeta SET meta_value = (SELECT UNIX_TIMESTAMP(STR_TO_DATE(meta_value`,'%m/%d/%Y'))) WHERE meta_key='wpcf-end-dat

如何在React组件上测试定义为箭头函数(类属性)的组件方法?(How do I test component methods on a React component that are defined as arrow functions (class properties)?)

即使渲染很浅,也可以调用wrapper.instance()方法。 it("should call sort ids", () => { const wrapper = shallow(<Chat />); wrapper.instance().sortIds = jest.fn(); wrapper.update(); // Force re-rendering wrapper.instance().componentDidMount(); ex

找到与jQuery最近的链接(Find closest link with jQuery)

做这个: #main-about-div a { display: block } 由于你的LI元素每个只包含一个A元素,如果你使A元素成为块级别,它们应该占用它们的父LI元素的整个空间,然后单击LI元素将自动意味着相应的A元素是也点击了。 更新:看到您的CSS代码后。 #main-about-div li { list-style-type: none; font-size:13px; border-bottom:1px dotted #1f5779; } #

注入的依赖项为null(Injected dependency is null)

我认为Activity class / custom-element正在注入一个不同的Login类/ custom-element实例。 虽然这些项目通常具有容器控制的“单身”生命周期,但UI组件却没有。 我认为你可以通过将@singleton添加到Login ui组件来获得你必须工作的@singleton ,但你可能最好创建一个单独的类,可能称为“User”,你可以注入Login UI组件和Activity UI零件。 I think Activity class / custom-eleme

相关文章

更多

最新问答

更多
  • 根据Woocommerce中的自定义字段计算自定义购物车商品价格(Custom cart item price calculation based on dimentions custom fields in Woocommerce)
  • 分开foreach项目并单独打印(Separate foreach items and print them individually)
  • 写模式管道是否同步?(Is write mode pipe synchronous?)
  • 发现可用的Windows Phone强调色和本地化名称(Discover available Windows Phone accent colors and localized names)
  • 使用多线程和WPF更新集合(Update Collection with multithreading and WPF)
  • 如何在字符串的情况下使用同步?(How should the synchronization be used in case of strings?)
  • 打印唯一的行,比较不超过N个字符(Print unique lines, compare no more than N characters)
  • Javascript / jQuery - 如何调用switch case从另一个函数执行(Javascript/jQuery - how to call a switch case to execute from another function)
  • Hbase超时错误不断发生(Hbase timeout errors keep occuring)
  • 如何在Delphi中更改TabControl中活动TAB的颜色(How to change the color of active TAB in a TabControl, in Delphi)
  • 正则表达式:在sublime文本中替换一些PHP代码(Regex: replace some pieces of php code in sublime text)
  • 在带有Scene2D的LibGDX中,如何在按下按钮时连续向右走?(In LibGDX with Scene2D, how can I continuously walk to the right when a button is pressed?)
  • 累加器如何在Haskell中工作?(How do accumulators work in Haskell?)
  • 使用开关检查市场和前缀与正确的货币符号(using switch to check market and prefix with correct currency symbol)
  • 在哪里分配一次使用类?(Where to allocate one time use class?)
  • 如何从两个DateTime / NaiveDateTime获取持续时间?(How do I get Duration from two DateTime / NaiveDateTime?)
  • 解析TimeSpan大于24小时?(Parse a TimeSpan greater than 24 hours? [duplicate])
  • 如何在球拍中本地更改阅读规则?(How to locally change reading rules in racket?)
  • 数据库应该由DI注入时的模拟存储(通过构造函数)(Mock storage when database should be injected by DI (through constructor))
  • 使用maven集成2个eclipse项目(Integrate 2 eclipse projects using maven)
  • 角度ng-repeat不检测变化(Angular ng-repeat not detecting changes)
  • Xaml组件在Silverlight + XNA应用程序的多个页面中可见(Xaml component visible in multiple pages in Silverlight+XNA applications)
  • 如何将`var`变量等同于另一个查询(How to equate `var` variable to another query)
  • 如何设计hyperledger链代码以适合您的业务?(how to design your chaincode of hyperledger to fit for your business?)
  • PHP readfile错误(PHP readfile error)
  • 在Date之后排序列表然后是时间(Sorting list after Date then time)
  • Android内部版本号(Android build number)
  • 在没有预设退出条件的情况下停止无限循环(stopping an infinite loop with no preset exit condition)
  • Phonegap应用程序全屏通过html页面中的按钮(Phonegap Application fullscreen through a button in html page)
  • PAA是否适合在门户网站中自动执行wcm库部署和设置?(Is PAA a good candidate for automating wcm library deployment and setup in portal?)