不同數據類型的內部秘密----編程內幕(2)

Q: char類型是如何被當成int處理的?

A: ? ?我們可以看看char類型變量在何時才會被當做int處理.

#include <stdio.h>int main()
{char ch;ch = 'a';printf("%c\n", ch);return 0;
}


匯編代碼如下:

hello`main:0x100000f60 <+0>:  pushq  %rbp0x100000f61 <+1>:  movq   %rsp, %rbp0x100000f64 <+4>:  subq   $0x10, %rsp0x100000f68 <+8>:  leaq   0x43(%rip), %rdi          ; "%c\n"0x100000f6f <+15>: movl   $0x0, -0x4(%rbp)
->  0x100000f76 <+22>: movb   $0x61, -0x5(%rbp)0x100000f7a <+26>: movsbl -0x5(%rbp), %esi0x100000f7e <+30>: movb   $0x0, %al0x100000f80 <+32>: callq  0x100000f92               ; symbol stub for: printf

movb $0x61, -0x5(%rbp)是把字符'a'保存到ch變量中. movb是單個字節的拷貝,顯然此時ch并沒有當做int來處理.

而在后面: movsbl -0x5(%rbp), %esi表明ch被放到了int大小的register中,說明ch被提升為int.

再看一個例子:

#include <stdio.h>int main()
{char ch;int i = 0xF;ch = 'a';i = i + ch;printf("%d\n", i);return 0;
}

hello`main:0x100000f40 <+0>:  pushq  %rbp0x100000f41 <+1>:  movq   %rsp, %rbp0x100000f44 <+4>:  subq   $0x10, %rsp0x100000f48 <+8>:  leaq   0x57(%rip), %rdi          ; "%d\n"0x100000f4f <+15>: movl   $0x0, -0x4(%rbp)0x100000f56 <+22>: movl   $0xf, -0xc(%rbp)0x100000f5d <+29>: movb   $0x61, -0x5(%rbp)
->  0x100000f61 <+33>: movl   -0xc(%rbp), %eax0x100000f64 <+36>: movsbl -0x5(%rbp), %ecx0x100000f68 <+40>: addl   %ecx, %eax0x100000f6a <+42>: movl   %eax, -0xc(%rbp)0x100000f6d <+45>: movl   -0xc(%rbp), %esi0x100000f70 <+48>: movb   $0x0, %al0x100000f72 <+50>: callq  0x100000f84               ; symbol stub for: printf

在執行i = i + ch:?

movsbl -0x5(%rbp), %ecx
addl   %ecx, %eax

此時,證明了char被提升為int.

由上面可見,char被提升為int是在char和int一起處理或者當參數傳遞時才會產生,如果char變量單獨使用,又有什么必要提升為int呢?

?

Q: unsigned int和int究竟有何區別?

A:?

#include <stdio.h>int main()
{int i;unsigned int j;i = 1;j = 2;return 0;
}
hello`main:0x100000f90 <+0>:  pushq  %rbp0x100000f91 <+1>:  movq   %rsp, %rbp0x100000f94 <+4>:  xorl   %eax, %eax0x100000f96 <+6>:  movl   $0x0, -0x4(%rbp)
->  0x100000f9d <+13>: movl   $0x1, -0x8(%rbp)0x100000fa4 <+20>: movl   $0x2, -0xc(%rbp)0x100000fab <+27>: popq   %rbp0x100000fac <+28>: retq  

兩條movl語句并沒有太大區別,看起來int i和unsigned int j在cpu看來并沒有什么區別,都是4字節,對應不同地址而已.

下面我們用int和unsigned int比較大小:

#include <stdio.h>int main()
{int i;unsigned int j;i = 1;j = -1;printf("%d\n", i > j);return 0;
}

    0x100000f56 <+22>: movl   $0x1, -0x8(%rbp)0x100000f5d <+29>: movl   $0xffffffff, -0xc(%rbp)   ; imm = 0xFFFFFFFF 0x100000f64 <+36>: movl   -0x8(%rbp), %eax0x100000f67 <+39>: cmpl   -0xc(%rbp), %eax
->  0x100000f6a <+42>: seta   %cl0x100000f6d <+45>: andb   $0x1, %cl0x100000f70 <+48>: movzbl %cl, %esi0x100000f73 <+51>: movb   $0x0, %al0x100000f75 <+53>: callq  0x100000f88               ; symbol stub for: printf

在斷點在如上位置時,

(lldb) register read rflagsrflags = 0x0000000000000213

RFLAGS寄存器 b0: CF = 1, ?b6: ZF = 0.

所以seta ?%cl保存到cl寄存器的數值為0: 只有CF = 0, ZF = 0的時候cl才會是1.

注意: seta指令是對無符號數比較的結果. 這里是印證了int和unsigned int在一起操作會被提升成unsigned int.

所以最終printf輸出的結果為0.

對此規則,可能有人會提出異議,但基于一個基本的準則: 兩個數據操作,向數據更長不會丟失數值的方向去轉換.

Q: 1左移32位是多少?

A:?

#include <stdio.h>int main()
{int i = 1;int j;j = i << 32;printf("%d\n", j);return 0;
}
    0x100000f5f <+15>: movl   $0x20, %ecx0x100000f64 <+20>: movl   $0x0, -0x4(%rbp)0x100000f6b <+27>: movl   $0x1, -0x8(%rbp)0x100000f72 <+34>: movl   -0x8(%rbp), %eax0x100000f75 <+37>: shll   %cl, %eax0x100000f77 <+39>: movl   %eax, -0xc(%rbp)
->  0x100000f7a <+42>: movl   -0xc(%rbp), %esi0x100000f7d <+45>: movb   $0x0, %al0x100000f7f <+47>: callq  0x100000f92               ; symbol stub for: printf

可以看到shll左移%cl: 0x20即32位. 有一部分書籍說,左移語句對于超過數據大小比特長度會采用模比特長度的方式得到最終左移的位數,并認為這是編譯器的行為. 其實不然,這是指令集的行為.

如下為Intel指令集手冊的原文:

Shifts the bits in the first operand (destination operand) to the left or right 
by the number of bits specified in the second operand (count operand). Bits shifted 
beyond the destination operand boundary are first shifted into the CF flag, then 
discarded. At the end of the shift operation, the CF flag contains the last bit
shifted out of the destination operand.
The destination operand can be a register or a memory location. The count operand 
can be an immediate value or the CL register. The count is masked to 5 bits 
(or 6 bits if in 64-bit mode and REX.W is used). The count range is limited to 0 to 31
(or 63 if 64-bit mode and REX.W is used). A special opcode encoding is provided for a count of 1.


微風不燥,陽光正好,你就像風一樣經過這里,愿你停留的片刻溫暖舒心。

我是程序員小迷(致力于C、C++、Java、Kotlin、Android、Shell、JavaScript、TypeScript、Python等編程技術的技巧經驗分享),若作品對您有幫助,請關注、分享、點贊、收藏、在看、喜歡,您的支持是我們為您提供幫助的最大動力。

歡迎關注。助您在編程路上越走越好!

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/10688.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/10688.shtml
英文地址,請注明出處:http://en.pswp.cn/web/10688.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

修改了環境變量~/.bashrc后 報錯 命令 “dirname” 可在以下位置找到 * /bin/dirname * /usr/bin/dirname

問題如下&#xff1a; 修改了~/.bashrc后加入了環境變量之后報錯&#xff0c;如下所示 (base) jiedell:~/桌面$ source ~/.bashrc 命令 “dirname” 可在以下位置找到 * /bin/dirname * /usr/bin/dirname 由于 /usr/bin:/bin 不在 PATH 環境變量中&#xff0c;故無法找到該…

在Linux上安裝并啟動Redis

目錄 安裝gcc環境 上傳redis文件方法一&#xff1a;sftp 上傳redis文件方法二&#xff1a;wget 啟動redis-server ctrlc關閉redis-server 參考文章&#xff1a;Linux 安裝 Redis 及踩坑 - 敲代碼的阿磊 - 博客園 (cnblogs.com) 準備&#xff1a;打開VMware Workstation&am…

pair對組創建

創建方式1: pair<type,type> p(value1,value2); pair<string, int> p("Tom", 20); cout << "name:" << p.first << "age:" << p.second << endl; 創建方式2: pair<type,type> pmake_pair(v…

mysql權限分類

USAGE --無權限,只有登錄數據庫,只可以使用test或test_*數據庫 ALL --所有權限 select/update/delete/super/slave/reload --指定的權限 with grant option --允許把自己的權限授予其它用戶(此用戶擁有建立賬號的權限) 權限級別&#xff1a; 1、. &#xff0d;&#xff0d;全…

C語法:for循環執行順序

今天下編寫代碼時遇到了如下情況&#xff1a;期望是輸出 i1,j2 i1,j3 i1,j4 i2,j3 int main(void) {int i,j;for(i1;i<3;i){for(j1;j!i&&j<4;j){printf("i%d,j%d\n",i,j);}}return 0; }實際輸出結果&#xff1a; i2,j1 分析上述代碼&#xff1a…

商務分析方法與工具(九):Python的趣味快捷-Pandas處理公司財務數據集思路

Tips&#xff1a;"分享是快樂的源泉&#x1f4a7;&#xff0c;在我的博客里&#xff0c;不僅有知識的海洋&#x1f30a;&#xff0c;還有滿滿的正能量加持&#x1f4aa;&#xff0c;快來和我一起分享這份快樂吧&#x1f60a;&#xff01; 喜歡我的博客的話&#xff0c;記得…

LangChain:大模型框架的深度解析與應用探索

在數字化的時代浪潮中&#xff0c;人工智能技術正以前所未有的速度蓬勃發展&#xff0c;而大模型作為其中的翹楚&#xff0c;以生成式對話技術逐漸成為推動行業乃至整個社會進步的核心力量。再往近一點來說&#xff0c;在公司&#xff0c;不少產品都戴上了人工智能的帽子&#…

初識C語言——第十八天

循環while/do while while 語法結構 while(表達式) 循環語句; break:在while循環中&#xff0c;break用于永久的終止循環 continue:在while循環中&#xff0c;continue的作用是跳過本次循環continue后面的代碼 直接去判斷部分&#xff0c;看是否進行下一次循環。 注意事項…

Logstash詳解

Logstash詳解&#xff1a;構建強大日志收集與處理管道的利器 一、引言 在大數據和云計算的時代&#xff0c;日志數據作為企業運營和故障排查的重要依據&#xff0c;其收集、處理和分析能力顯得尤為重要。Logstash&#xff0c;作為一款強大的日志收集、處理和轉發工具&#xf…

[AI OpenAI-doc] 安全最佳實踐

使用我們的免費 Moderation API OpenAI 的 Moderation API 是免費使用的&#xff0c;可以幫助減少您完成中不安全內容的頻率。或者&#xff0c;您可能希望開發自己的內容過濾系統&#xff0c;以適應您的使用情況。 對抗性測試 我們建議對您的應用進行“紅隊測試”&#xff0…

即插即用篇 | YOLOv8引入軸向注意力 Axial Attention | 多維變換器中的軸向注意力

本改進已集成到 YOLOv8-Magic 框架。 我們提出了Axial Transformers,這是一個基于自注意力的自回歸模型,用于圖像和其他組織為高維張量的數據。現有的自回歸模型要么因高維數據的計算資源需求過大而受到限制,要么為了減少資源需求而在分布表達性或實現的便捷性上做出妥協。相…

解決wangEditor使用keep-alive緩存后,調用editor.cmd.do()失敗

前提&#xff1a;wangeditor版本&#xff1a;4.7.11 vue版本&#xff1a;vue2 問題&#xff1a;在使用wangeditor富文本編輯器時&#xff0c;需求需要通過點擊一個按鈕&#xff0c;手動插入定義好的內容&#xff0c;所以使用了 editor.cmd.do(insertHTML, ....) 方法新增…

青少年軟件編程(Python)等級考試試卷(二級)2024年3月

2024.03電子學會青少年軟件編程 Python二級 等級考試試卷 一、單選題 1.期末考試結束了&#xff0c;全班的語文成績都儲存在列表score 中&#xff0c;班主任老師請小明找到全班最高分&#xff0c;小明準備用Python 來完成&#xff0c;以下哪個選項&#xff0c;可以獲取最高分…

較難題 鏈表的回文結構

本題來自鏈表的回文結構_牛客題霸_牛客網 (nowcoder.com) 234. 回文鏈表 - 力扣&#xff08;LeetCode&#xff09; 題面&#xff1a; 對于一個鏈表&#xff0c;請設計一個時間復雜度為O(n),額外空間復雜度為O(1)的算法&#xff0c;判斷其是否為回文結構。 給定一個鏈表的頭…

03.Linux文件操作

1.操作系統與Linux io框架 1.1 io與操作系統 1.1.1 io概念 io 描述的是硬件設備之間的數據交互&#xff0c;分為輸? (input) 與輸出 (output)。 輸?&#xff1a;應?程序從其他設備獲取數據 (read) 暫存到內存設備中&#xff1b;輸出&#xff1a;應?程序將內存暫存的數據…

FANUC機器人基本保養概述

對于工業機器人來說&#xff0c;定期保養機器人可以延長機器人的使用壽命。對于FANUC機器人來說&#xff0c;FANUC機器人的常規保養周期可以分為日常、三個月、六個月、一年、兩年、三年。以下是FANUC機器人的基本保養周期概覽&#xff1a; 在實際生產應用中&#xff0c;可以參…

具身智能論文

目錄 1. PoSE: Suppressing Perceptual Noise in Embodied Agents for Enhanced Semantic Navigation2. Embodied Intelligence: Bionic Robot Controller Integrating Environment Perception, Autonomous Planning, and Motion Control3. Can an Embodied Agent Find Your “…

7.STL_string(詳細)

1. 什么是STL STL(standard template libaray-標準模板庫)&#xff1a;是C標準庫的重要組成部分&#xff0c;不僅是一個可復用的組件庫&#xff0c;而且 是一個包羅數據結構與算法的軟件框架。 2. STL的版本 原始版本 Alexander Stepanov、Meng Lee 在惠普實驗室完成的原始版…

maven遠程倉庫訪問順序

首先需要了解一下各個配置文件&#xff0c;主要分為三類&#xff1a; 全局配置文件(${maven.home}/conf/settings.xml)&#xff0c;maven安裝路徑下的/conf/settings.xml用戶配置文件(%USER_HOME%/.m2/settings.xml)&#xff0c;windows用戶文件夾下項目配置文件&#xff1a;p…

C/C++ 入門(10)list類(STL)

個人主頁&#xff1a;仍有未知等待探索-CSDN博客 專題分欄&#xff1a;C 歡迎來指教&#xff01; 目錄 一、標準庫中的list 1、了解 2、常用接口說明 a.常見的構造函數 b.迭代器 c. Capacity?編輯 d.Element access e.Modifiers 二、實現 1、框架 a.節點 b.迭代器 …