clang 分四步编译main.c

这里用的clang/clang++ 分四步编译main.c/main.cpp文件

1.1 C++源文件

#include

int main() {
    std::cout << "Hello Biter !" << std::endl;
    return 0;
}

1.2 预处理、编译、汇编、链接

clang或者clang++方式

1.2.1 预处理 命令: > > clang++ -E main.cpp -o main.ii

1.2.2 编译阶段,生成汇编

clang++ -S main.ii -o main.s

1.2.3 汇编阶段,生成目标文件

 clang++ -c main.s -o mian.o

1.2.4 连接阶段 bash clang++ mian.o -o main -c400

1.2.5 执行

 ./main

1.3 四部曲之一步到胃 clang++在编译的过程中,保存所有编译过程中产生的文件

 clang++ -save-temps main.cpp -o main
 clang++  main.cpp -o main

二 持有ndk的交叉编译工具 编译main.c

2.1 预处理

armv7a-linux-androideabi29-clang++ -E main.cpp -o main.ii

2.2 编译 armv7a-linux-androideabi29-clang++ -S main.ii -o main.s -c400

2.3 汇编

armv7a-linux-androideabi29-clang++ -c main.s -o mian.o

2.4 连接

armv7a-linux-androideabi29-clang++ mian.o -o main

3 原码、反码、补码 ## 3.1 知识点补充 在计算机内部,所有信息都是用二进制数串的形式表示的。整数通常都有正负之分,计算机中的整数分为无符号的和带符号的。无符号的整数用来表示0和正整数,即自然数;带符号的正数可以表示所有的整数。

由于计算机中符号和数字一样,都必须用二进制数串来表示,因此,正负号也必须用0、1来表示。通常我们用最高的有效位来 表示数的符号(当用8位来表示一个整数时,第8位即为最高有效位,当用16位来表示一个整数时,第16位即为最高有效位。)0表示正号、1表示负号。

这种正负号数字化(0表示正号、1表示负号)的机内表示形式就称为 机器码或者 机器数,而相应的机器外部用正负号表示的数称为 真值。将一个真值表示成二进制字串的机器数的过程就称为 &#x7F16;&#x7801;

无符号数没有原码、反码和补码一说。只有带符号数才存在不同的编码方式。带符号整数有原码、反码、补码等几种编码方式。

原码即直接将真值转换为其相应的二进制形式,而反码和补码是对原码进行某种转换编码方式。

&#x6B63;&#x6574;&#x6570;&#x539F;&#x7801;&#x53CD;&#x7801;&#x8865;&#x7801;都一样。

负数的反码是对原码的除符号位外的其他位进行取反后的结果(取反即如果该位为0则变为1,而该位为1则变为0的操作)。而补码是先求原码的反码,然后在反码的末尾位加1 后得到的结果,即补码是反码+1。

IBM-PC中带符号整数都采用补码形式表示。

注意,只是带符号的整数采用补码存储表示的,浮点数另有其存储方式。

对于字长为8位有符号的int,因为最高为符号位,占1位,所以最小为(11111111)2 = (-127)10,最大为(01111111)2 = (127)10;即其原码范围为:-127~127

有符号的8位二进制的原值表达范围为:-127至127,此时共255个数字;然而,8位二进制 的补码排列共有$2^8$ = 256个,0000 0000 至1111 1111 。

机器码组合 范围 个数 0000 0000 – 0111 1111 0 ~+127 128 10000000 多余的一种组合

1 1000 0001 – 1111 1111 -1~-127 127

10000000 看似要被浪费掉了啊!其实不然,( 100000000 ) 2 = ( 2^7 ) 10 = ( 128 ) 10,这个组合要利用起来,不能太偏离数值意义,表示128,显得更直观。

从大到小,依次减1看一下规律: 十进制 (字长8bit) 原码 反码 补码

0111 1111 0111 1111 0111 1111

0111 1110 0111 1110 0111 1110

…… …… ……

0000 1010 0000 1010 0000 1010

…… …… ……

0000 0010 0000 0010 0000 0010

0000 0001 0000 0001 0000 0001

0000 0000 0000 0000 0000 0000

1000 0001 1111 1110 1111 1111

1000 0010 1111 1101 1111 1110

…… …… ……

10001010 11110101 11110110

…… …… ……

11111111 10000000 10000001

10000000 10000000 10000000

从递减规律中,发现,10000000 表示 -128更合适。

即规定:-128的补码为 10000000

10 -10 0 -128 127 的原码、反码、补码

十进制 (字长8bit) 原码 反码 补码

00001010 00001010 00001010

10001010 11110101 11110110

1000 0001 1111 1110 1111 1111

00000000 00000000 00000000

10000000 11111111 00000000

无 无 10000000

01111111 01111111 01111111

11111111 10000000 10000001

+0和-0的补码是一样的。即 0的补码只有一种表示,0的补码是 0000 0000,

四 输出结果,解释为什么是这样的

char c = 128;
printf("%d\n",c);
printf("%hhd\n",c);
printf("%hd\n",c);
printf("%hu\n",c);

4.1 格式输出符

格式符号 意义 %a 浮点数、十六进制数字和p-记数法 (C99) %A 浮点数、十六进制数字和P-记数法 (C99) %c 一个字符 %d 有符号十进制整数 %e 浮点数、e-记数法 %E 浮点数、E-记数法 %f 浮点数,十进制记数法 %g 根据数值不同自动选择%f或者%e。%e格式在指数小于-4或者大于等于精度时使用 %G 根据数值不同自动选择%f或者%E。%E格式在指数小于-4或者大于等于精度时使用 %i 有符号十进制整数 (与%d相同) %o 无符号八进制整数 %p 指针(就是指地址) %s 字符串 %u 无符号十进制整数 %x 使用十六进制数字0f 的无符号十六进制整数 %X 使用十六进制数字0F的无符号十六进制整数 %% 打印一个百分号

4.2 格式输出其修饰符 修饰符 意义 示例 h 和整数转换说明符一起使用,表示一个short int 或者 unsigned short int 类型数值。 “%hd hh 和整数转换说明符一起使用,表示一个signed char 或者unsigned char类型数值。 “%hhd” j 和整数转换说明符一起使用,表示一个intmax_t或uintmax_t值。 “%jd” l 和整数说明符一起使用,表示一个long int 或者unsigned long int 类型值。 “%8lu” ll 和整数说明符一起使用,表示一个long long int或 unsigned long long int 类型值 (C99)。 “%lld” L 和浮点转换说明符一起使用,表示一个long double值。 “%8.4Le” t 和整数转换说明符一起使用,表示一个ptrdiff_t值(与两个指针之间的差相对应的类型) (C99) “%td” – 项目是左对齐的,也就是说,会把项目打印在字段的左侧开始处 “%-20s” + 有符号的值若为正,则显示带加号的符号;若为负,则带减号的符号。 “%+3.2” (空格) 有符号的值若为正,则显示时带前导空格(但是不显示符号);若为负,则带减号符号。+标志会覆盖空格标志。 “% 3.2” # 使用转换说明的可选形式。若为%o格式,则以0开始;若为%x和%X格式,则以0x或0X开始,对于所有的浮点形式,#保证了即使不限任何数字,也打印一个小数点字符。对于%g和%G格式,它防止尾随零被删除。 “%#o” 0 对于所有的数字格式,用前导零而不是用空格填充字段宽度。如果出现-标志或者指定了精度(对于整数)则忽略该标志。 “%010d”

4.3 机器码求解

char c = 128;

此处是将一个 int赋值给一个 char类型变量,进行 隐式类型转换.int型数值赋给char型变量时,只保留其最低8位,高位部分舍弃。

首先,整型128在一个字长为4个字节的的原码为 00000000 00000000 00000000 10000000,当把一个int类型赋值给一个有符号的char类型时,高位被舍弃。实际给 c的是 10000000,此时,被系统认为是一个负数,补码为 10000000,结合上面的分析,其值就是-128

4.4 格式化输出

char c = 128;

先给出通过这次作业得出的一个不完全归纳法结论吧,也是我做出的解释。最后会给出原码验证

1、正数的原码的反码、补码是其本身,扩展时,高位补0;

2、负数扩展为有符号的高位补1,无符号的高位补0。

2、 负数扩展时,高位补 1。格式化输出无符号的数据时,机器码即为原码;格式化输出有符号数据时,要先求其原码,然后求得真值。

c 的机器码为 10000000

printf("%d\n",c);//默认的 int ,32位

1000 0000 转为有符号的32位机器码: 1111 1111 1111 1111 1111 1111 1000 0000

反码: 1111 1111 1111 1111 1111 1111 0111 1111

原码: 1000 0000 0000 0000 0000 0000 1000 0000

有符号,其值为:-128.

printf("%hhd\n",c);//signed char,  8位

8位机器码: 1000 0000

此机器码没有反码和源码,机器码即为真值:-128.

printf("%hd\n",c);//short int,16 位

1000 0000 转为有符号的16位机器码: 1111 1111 1000 0000

反码: 1111 1111 0111 1111 原码: 1000 0000 1000 0000

有符号,其值为:-128.

printf("%hu\n",c);

1000 0000 转为16位机器码: 1111 1111 1000 0000

格式化输出无符号十进制数据,此码即为原码。

原码: 1111 1111 1000 0000

做无符号运算,其值:65408

4.5 源码

#include
#include

int main() {
    using namespace std;
    cout << "Hello Biter !" << endl;
    char c = 128;
    cout << "---------------- -" << int(c) << "-----------------------  " << endl;
    cout << "char 型 机器码 =  " << bitset(c) << endl;
    cout << "int 型 机器码 =  " << bitset(c) << endl;
    cout << "signed char 型 机器码 =  " << bitset(c) << endl;
    cout << "short int 型 机器码 =  " << bitset(c) << endl;
    cout << "unsigned short int 型 机器码 =  " << bitset(c) << endl;
    cout << "char 二进制形式为 =  " << bitset(c) << endl;
    cout << "--------------------------------------------  " << endl;
//    printf("将 char 直接 输出 128 超范围了 = %c\n", c);
//    cout << "--------------------------------------------  " << endl;
    printf("有符号的 int 输出 = %d\n", c);
    cout << "--------------------------------------------  " << endl;
    printf("有符号的 signed char 输出 = %hhd\n", c);//1000,0000
    cout << "--------------------------------------------  " << endl;
    printf("有符号的 short int 输出= %hd\n", c);//0000,0000 1000,0000
    cout << "--------------------------------------------  " << endl;
    printf("无符号的 unsigned short int 输出= %hu\n", c);// 1111,1111 1000,0000
    cout << "--------------------------------------------  " << endl;

    return 0;
}

Original: https://www.cnblogs.com/burner/p/clang-fen-si-bu-bian-yimainc.html
Author: 浪客禅心
Title: clang 分四步编译main.c

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/606498/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • 【.Net vs Java? 】 看一看二者的类有多像?

    1. 包(Package)、命名空间(NameSpace) 在Java中常用的是包(Package),较少提到NameSpace的概念。Java官方文档中这样说: 为了使类型更易于…

    Linux 2023年6月7日
    096
  • Linux 宿主机故障虚拟机重启rhel6网卡报已使用故障&rhel7网卡无法启动

    宿主机故障虚拟机重启rhel6 网卡 报已使用故障 &rhel7 网卡无法启动 宿主机故障虚拟机重启rhel6网卡 报已使用 一、故障分析 1 、故障现象:RHEL6 虚拟…

    Linux 2023年6月13日
    0100
  • Python中class内置方法__init__与__new__作用与区别探究

    最近尝试了解Django中ORM实现的原理,发现其用到了metaclass(元类)这一技术,进一步又涉及到Python class中有两个特殊内置方法__init__与__new_…

    Linux 2023年6月6日
    093
  • MVC(二)

    通过前一篇文章,我们对MVC有了一定的了解。 三、MVC能做什么 网站——服务器返回页面——实际上就是一段文本(response header+html)。 实际上mvc的acti…

    Linux 2023年6月13日
    0112
  • MySQL备份与恢复

    MySQL备份与恢复 备份是数据安全的最后一道防线,对于任何数据丢失的场景,备份虽然不一定能恢复百分之百的数据(取决于备份周期),但至少能将损失降到最低。 数据丢失的场景举例: 人…

    Linux 2023年6月7日
    0177
  • Redis时延问题分析及应对

    Redis时延问题分析及应对 Redis的事件循环在一个线程中处理,作为一个单线程程序,重要的是要保证事件处理的时延短,这样,事件循环中的后续任务才不会阻塞;当redis的数据量达…

    Linux 2023年5月28日
    096
  • 阿里云ddns shell 脚本

    https://files-cdn.cnblogs.com/files/ahuo/aliyun-ddns.sh Original: https://www.cnblogs.com/…

    Linux 2023年5月28日
    0106
  • SQLI-LABS(Less-3)

    Less-3(GET-Error based-Single quotes with twist-string) 打开 Less-3页面,可以看到页面中间有一句 Please inp…

    Linux 2023年6月6日
    093
  • 使用Visual Studio 2019将ASP.NET Core发布为linux-arm64程序

    前言 前段时间入手了一台树莓派4B,一直闲置未使用,最近工作需要,要在上面跑下.NET Core程序,由于树莓派4B使用的是ARM架构,并且支持64位操作系统,为了充分发挥树莓派性…

    Linux 2023年6月8日
    0119
  • url参数+,&,=,/等转义编码【转】

    问题描述 在使用postman发送请求时,url出现了有+,空格,/,?,%,#,&,= 等特殊符号,可能在转义之后导致服务器端无法获得正确的参数值。解决办法 将这些字符转…

    Linux 2023年6月8日
    090
  • muduo项目介绍

    在上一个集群聊天服务器项目中,我使用了 muduo作为网络库,然后主要实现了业务逻辑等,所以为了深入网络库的代码和实现,我跟着一位老师的代码去实现了 muduo库的基本原理和作用,…

    Linux 2023年6月13日
    0109
  • 【原创】Linux v4l2框架分析

    背景 Read the fucking source code! –By 鲁迅 A picture is worth a thousand words. –…

    Linux 2023年5月27日
    083
  • djnago-filter用法

    django-filter用法 集成drf 不指定字段的过滤参数,那么该字段就默认为exact,精准匹配自定义filter文件内 from django_filters impor…

    Linux 2023年6月14日
    0130
  • 函数的设计和使用

    1.函数的定义 将可能需要反复执行的代码封装为函数,并在需要该功能的地方进行调用,不仅可以实现代码复用,更重要的是可以保证代码的一致性,只需要修改函数代码则所有调用均受影响。 设计…

    Linux 2023年6月7日
    0184
  • Kubenertes-实战入门

    实战入门 Namespace Namespace是kubernetes系统中的一种非常重要资源,它的主要作用是用来实现 多套环境的资源隔离。 默认情况下,kubernetes集群中…

    Linux 2023年6月13日
    0101
  • Linux文件属性详述

    一、文件属性信息概述 文件属性信息组成如下: 文件索引属性信息——inode编号; 文件类型权限信息; 文件链接属性信息——硬链接数; 文件属主信息——文件所有者; 文件属组属性信…

    Linux 2023年5月27日
    0104
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球