衡阳派盒市场营销有限公司

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

如何給一個變量設置一個別名?

strongerHuang ? 來源:IOT物聯網小鎮 ? 作者:IOT物聯網小鎮 ? 2022-06-06 09:33 ? 次閱讀

別名是啥玩意?

stackoverflow上看到一個有趣的話題:如何給一個變量設置一個別名?(How to assign to a variable an alias?

4eaada1e-e530-11ec-ba43-dac502259ad0.png

所謂的變量別名,就是通過通過不同的標識符,來表示同一個變量。

我們知道,變量名稱是給程序員使用的。

編譯器的眼中,所有的變量都變成了地址

請注意:這里所討論的別名,僅僅是通過不同的標識符來引用同一個變量。

與強符號、弱符號的概念沒有任何關系,那是另一個話題。

在上面這個帖子中,作者首先想到的是通過宏定義,對變量進行重新命名。

這樣的做法,將會在編譯之前的預處理環節,把宏標識符替換為變量標識符。

在網友回復的答案中,大部分都是通過指針來實現:讓不同的標識符指向同一個變量。

不管怎么說,這也算是一種別名了。

但是,這些答案有一個局限:這些代碼必須一起進行編譯才可以,否則就可能出現無法找到符號的錯誤信息

現在非常流行插件編程,如果開發者想在插件中通過一個變量別名來引用主程序中的變量,這該如何處理呢?

本文提供兩個方法來實現這個目的,并通過兩個簡單的示例代碼來進行演示。

文末有示例代碼的下載地址。

方法1:反向注冊

之前我接觸過一些CodeSys的代碼,里面的代碼質量真的是非常的高,特別是軟件架構設計部分。

傳說:CodySys 是工控界的 Android

其中有個反向注冊的想法,正好可以用在變量別名上面。

示例代碼中一共有 2 個文件:main.cplugin.c

main.c中定義了一個全局變量數組,編譯成可執行程序main

plugin.c中通過一個別名來使用main.c中的全局變量。

plugin.c被編譯成一個動態鏈接庫,被可執行程序main動態加載(dlopen)。

plugin.c中,提供一個函數func_init,當動態庫被main dlopen之后,這個函數就被調用,并且把真正的全局變量的地址通過參數傳入

這樣的話,在插件中就可以通過一個別名來使用真正的變量了(比如:修改變量的值)。

本質上,這仍然是通過指針來進行引用。

只不過利用動態注冊的思想,把指針與變量的綁定關系在時間和空間上進行隔離。

plugin.c 源文件

#include 

int *alias_data = NULL;

void func_init(int *data)
{
printf("libplugin.so: func_init is called. 
");
alias_data = data;
}

void func_stage1(void)
{
printf("libplugin.so: func_stage1 is called. 
");
if (alias_data)
{
alias_data[0] = 100;
alias_data[1] = 200;
}
}

main.c 源文件

#include 
#include 
#include 

// defined in libplugin.so
typedef void (*pfunc_init)(int *);
typedef void (*pfunc_stage1)(void);

int data[100] = { 0 };


void main(void)
{
data[0] = 10;
data[1] = 20;

printf("data[0] = %d 
", data[0]);
printf("data[1] = %d 
", data[1]);

// open libplugin.so
void *handle = dlopen("./libplugin.so", RTLD_NOW);
if (!handle)
{
printf("dlopen failed. 
");
return;
}

// get and call init function in libplugin.so
pfunc_init func_init =  (pfunc_init) dlsym(handle, "func_init");
if (!func_init)
{
printf("get func_init failed. 
");
return;
}
func_init(data);

// get and call routine function in libplugin.so
pfunc_stage1 func_stage1 =  (pfunc_stage1) dlsym(handle, "func_stage1");
if (!func_stage1)
{
printf("get func_stage1 failed. 
");
return;
}
func_stage1();

printf("data[0] = %d 
", data[0]);
printf("data[1] = %d 
", data[1]);

return;
}

編譯指令如下:

gcc -m32 -fPIC --shared plugin.c -o libplugin.so
gcc -m32 -o main main.c -ldl

執行結果:

data[0] = 10 
data[1] = 20 
libplugin.so: func_init is called. 
libplugin.so: func_stage1 is called. 
data[0] = 100 
data[1] = 200

可以看一下動態鏈接庫的符號表:

readelf -s libplugin.so | grep data
4ee38580-e530-11ec-ba43-dac502259ad0.png

可以看到alias_data標識符,并且是在本文件中定義的全局變量。

方法2:嵌入匯編代碼

在動態加載的插件中使用變量別名,除了上面演示的動態注冊的方式,還可以通過嵌入匯編代碼來: 設置一個全局標號來實現。

直接上示例代碼:

plugin.c源文件

#include 

asm(".Global alias_data");
asm("alias_data = data");

extern int alias_data[];

void func_stage1(void)
{
printf("libplugin.so: func_stage1 is called. 
");

*(alias_data + 0) = 100;
*(alias_data + 1) = 200;
}

main.c源文件

#include 
#include 
#include 

// defined in libplugin.so
typedef void (*pfunc_init)(int *);
typedef void (*pfunc_stage1)(void);

int data[100] = { 0 };


void main(void)
{
data[0] = 10;
data[1] = 20;

printf("data[0] = %d 
", data[0]);
printf("data[1] = %d 
", data[1]);

// open libplugin.so
void *handle = dlopen("./libplugin.so", RTLD_NOW);
if (!handle)
{
printf("dlopen failed. 
");
return;
}

// get and call routine function in libplugin.so
pfunc_stage1 func_stage1 =  (pfunc_stage1) dlsym(handle, "func_stage1");
if (!func_stage1)
{
printf("get func_stage1 failed. 
");
return;
}
func_stage1();

printf("data[0] = %d 
", data[0]);
printf("data[1] = %d 
", data[1]);

return;
}

編譯指令:

gcc -m32 -fPIC --shared plugin.c -o libplugin.so
gcc -m32 -rdynamic -o main main.c -ldl

執行結果:

data[0] = 10 
data[1] = 20 
libplugin.so: func_stage1 is called. 
data[0] = 100 
data[1] = 200

也來看一下libplugin.so中的符號信息:

readelf -s libplugin.so | grep data
4f4798ea-e530-11ec-ba43-dac502259ad0.png

小結

這篇文檔通過兩個示例代碼,討論了如何在插件中(動態鏈接庫),通過別名來訪問真正的變量。

不知道您會不會有這樣的疑問:直接使用extern來聲明一下外部定義的變量不就可以了,何必這么麻煩?

道理是沒錯!

但是,在一些比較特殊的領域或場景中(比如一些二次開發中),這樣的需求是的確存在的,而且是強需求。

審核編輯 :李倩


聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 函數
    +關注

    關注

    3

    文章

    4346

    瀏覽量

    62973
  • 代碼
    +關注

    關注

    30

    文章

    4827

    瀏覽量

    69054
  • 變量
    +關注

    關注

    0

    文章

    613

    瀏覽量

    28466

原文標題:如何給全局變量起一個別名?

文章出處:【微信號:strongerHuang,微信公眾號:strongerHuang】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    分享keil MDK編譯信息增強工具

    今天大家分享 keil MDK 編譯信息增強工具:keil-build-viewer. 1 keil-build-viewer介紹 這是
    的頭像 發表于 11-14 11:01 ?715次閱讀

    如何在文本字段中使用上標、下標及變量

    在KiCad的任何文本字段中,都可以通過以下的方式實現上標、下標、上劃線以及顯示變量及字段值的描述: 文本變量“文本變量”可以在 原理圖設置->工程->文本
    的頭像 發表于 11-12 12:23 ?183次閱讀
    如何在文本字段中使用上標、下標及<b class='flag-5'>變量</b>

    Linux環境變量配置方法

    Linux上環境變量配置分為設置永久變量和臨時變量兩種。環境變量設置方法同時要考慮環境Shell
    的頭像 發表于 10-23 13:39 ?217次閱讀

    Xilinx設計工具怎么設置環境變量

    如果您不確定如何設置環境變量,嘗試"1" 或 "TRUE"。
    的頭像 發表于 10-22 13:32 ?265次閱讀

    文帶你了解IP地址別名

    、什么是IP地址別名 IP地址別名是將多個IP地址與網絡接口關聯起來的種方式。實現在網絡
    的頭像 發表于 09-05 14:11 ?279次閱讀

    ad如何設置元器件的距離

    之間應保持的最小距離,以確保電路板的電氣性能和制造過程的可靠性。以下是如何在AD中設置元器件之間距離的步驟: 、進入規則設置界面 打開AD軟件 :首先,確保你已經打開了Altiu
    的頭像 發表于 09-02 15:31 ?8479次閱讀

    電感的電流能否分流一個電感

    電感的電流能否分流一個電感,這個問題涉及到電感器的工作原理、特性以及在電路中的應用。 電感器的基本概念 電感器是種被動電子元件,其主要功能是存儲能量。電感器由
    的頭像 發表于 08-21 10:02 ?537次閱讀

    socket對應連接嗎

    在探討“socket對應連接”這命題時,我們首先需要明確socket的基本概念和它在網絡通信中的作用。Socket,即套接字,是網
    的頭像 發表于 08-16 10:55 ?574次閱讀

    如何在esp32的程序體中指定變量的絕對地址,或者相對于程序首地址的固定偏移位置?

    請問下如何在esp32的程序體中指定變量的絕對地址,或者相對于程序首地址的固定偏移位置
    發表于 06-21 08:12

    鴻蒙ArkUI開發實戰:制作【簡單計數器】

    ,?`@State`?是狀態標識符,當它修飾的變量值改變時ArkUI開發框架會調用?`build()`?方法進行頁面的刷新。
    的頭像 發表于 04-08 18:05 ?679次閱讀
    鴻蒙ArkUI開發實戰:制作<b class='flag-5'>一</b><b class='flag-5'>個</b>【簡單計數器】

    如何在ADI DSP中設計合理的混響(下)

    在上篇文章中,我們提及了混響的類型和基本實現原理。目前做一個專業級混響需要設置許多參數,有些參數是必備的,而有些是在特定需求下慢慢增加起來的。
    的頭像 發表于 03-06 15:33 ?1683次閱讀
    如何在ADI DSP中設計<b class='flag-5'>一</b><b class='flag-5'>個</b>合理的混響(下)

    變頻器調試指南:16關鍵參數的設置與優化技巧(1/2)

    變頻器的設定參數較多,每個參數均有定的選擇范圍,使用中常常遇到因個別參數設置不當,導致變頻器不能正常工作的現象。因此,變頻器調試是從正確設置變頻器參數開始的。總結了16
    的頭像 發表于 03-05 08:42 ?2202次閱讀
    變頻器調試指南:16<b class='flag-5'>個</b>關鍵參數的<b class='flag-5'>設置</b>與優化技巧(1/2)

    輕量級的LED控制模塊

    比如LED周期控制函數為100ms,理論上設置500ms間隔閃爍,則需要占用10bit,但是增加bit時間顆粒度變量,只需要占用兩
    發表于 02-29 11:43 ?628次閱讀

    進程內多次使用open打開同一個文件,可以嗎?

    進程內多次使用 open 打開同一個文件時,每次都會得到新的文件描述符(file descriptor)。
    的頭像 發表于 02-27 13:54 ?1409次閱讀

    蘋果手機用同一個id怎么取消同步

    蘋果手機用同一個id怎么取消同步? 取消蘋果手機間的同步功能可以通過以下步驟完成。請注意,這些步驟適用于iOS 11及更高版本。 步驟1:打開“設置”應用程序 首先,打開您的iPhone或iPad
    的頭像 發表于 02-19 10:19 ?3532次閱讀
    明升百家乐QQ群| 乐宝百家乐游戏| 海南省| 最新百家乐网评测排名| 678百家乐官网博彩娱乐场| 塔城市| 模拟百家乐下| 百家乐机器昀程序| 蓝盾百家乐官网具体玩法技巧| 如东县| 德州扑克比大小| 百家乐博赌场| 网上百家乐的技巧| 百家乐官网最佳注码法| 洛扎县| 大发888娱乐客户端| 百家乐五湖四海娱乐平台| 百家乐官网筹码防伪| 澳门百家乐官网战法| 赌场大轮盘| 大发888娱乐场手机| 百家乐博娱乐场开户注册| 百家乐重要心态| 在线百家乐官网下注| 百家乐官网网上投注网站| 大发888官网46| 实战百家乐的玩法技巧和规则 | 赌博堕天录 和也篇| 大发888网页| 百家乐玩揽法大全| 百家乐游戏机说明书| 鼎龙百家乐官网的玩法技巧和规则| 网上百家乐官网分析软件| 菲比国际娱乐| 大发888赌博网站| 百家乐赌博详解| 百家乐视频无法显示| 院子围墙砌18还是24| 百家乐官网首页红利| 广东百家乐官网桌布| 百家乐官网试玩全讯网2|