gcc编译器、进制、数据类型、原反补、常量

gcc、进制、数据类型、原反补、常量

一、hello world 程序说明

我们的系统中:

切换输入法 ctrl + 空格

切换中英文 shift

#include <stdio.h>

// C语言中以#开头的行 称为预处理行 是在预处理阶段处理的
// #include 是包含头文件的关键字
// stdio.h 标准输入输出的头文件 我们的使用的printf就在这个头文件里

//int 函数的返回值类型 先不用管
//main 主函数 是程序的入口 每个程序必须有且仅有一个
//() 里面是main函数的参数 先不用管 ()里面的内容可以不写 但是 ()必须写
//可以写成  int main()
//	()圆括号  []方括号  {}花括号
int main(int argc, const char *argv[])
{
	//{}里面包住的部分叫做函数体,就是我们实际要执行的代码

	//printf 是系统给我们提供的输出的函数 
	//功能就是将 "" 内的内容打印到终端  \n 表示换行的意思 就是回车
	printf("hello world\n"); //C语言中每条指令结束 都需要加 分号
	return 0;//函数的返回值  先不用管
}

//单行注释

/*
	多行
	注释
*/

#if 0
	多行
	注释
#endif

二、gcc编译器

2.1 编译型语言和解释型语言

编程语言分为两大类,编译型语言解释型语言

编译型语言

程序在运行之前,需要专门有一个翻译的过程,将我们人类好识别的语言翻译成方便计算机识别的二进制的语言,翻译的过程就是有编译器来完成的,编译器也是一个应用程序。编译型语言在执行的过程中,就无须重新编译了。

linux系统中C语言的编译器就是gcc编译器。

例如:C C++

优点:在执行的过程中,无须重新编译执行效率相对较高。

缺点:对编译器要求较高,不同的操作系统,不同的架构,不同的版本,跨平台性较差。

解释型语言

在程序运行之前,无需事先编译,而是在执行的过程中,由解释器逐行的翻译给计算机看。

例如:shell python 解释型语言也称之为脚本语言

优点:一般只要解释器版本相同,跨平台性相对较好

缺点:每次执行都需要解释器逐行解释,执行效率相对较低

2.2 gcc编译器的使用

2.2.1 简单明了

gcc xxx.c //xxx.c是你自己的.c文件名

这种编译编译方式,如果代码没问题,会在当前路径下,默认生成一个叫做 a.out 的可执行文件

使用 ./a.out 就可以执行

2.2.2 可以自定义可执行文件名

gcc xxx.c -o diy_name //xxx.c是你自己的.c文件名 diy_name 是你自定义的可执行文件名

这种编译编译方式,如果代码没问题,会在当前路径下,生成一个 自定义名字 的可执行文件

使用 ./自定义的名字 就可以执行了

2.2.3 按照编译流程分步骤编译

编译流程共有四步 : 预处理–>编译–>汇编–>链接 //顺序不能变!!

预处理头文件的展开 宏定义的替换 注释的删除

gcc -E xxx.c -o xxx.i

编译:词法分析 语法分析 --用来查错的

如果无误,则生成汇编文件

gcc -S xxx.i -o xxx.s

汇编:将汇编文件生成计算机能识别的二进制文件

gcc -c xxx.s -o xxx.o

链接:链接库文件,生成最终的可执行文件

gcc xxx.o -o a.out

我们实际使用的时候,使用前两种方式即可,笔试面试时候有可能会问到编译步骤

三、计算机中数据的存储

计算机中数据的存储分为两大部分

数值型数据 520 1314

非数值型数据 “www.baidu.com” “华清远见”

3.1 数值型数据的存储

3.1.1 十进制

在C语言中,没有特殊说明和前导符时,默认的都是10进制数据

特点:逢10进1 每一位上的数字范围 [0, 9]

例如:520 1314

十进制转二进制

使用除2取余法:用十进制数除以2,保留商和余数,

然后再用商继续除以2,保留商和余数,依次类推

直到商为 0,将得到的余数 倒序取出 就是对应的二进制数了。

​ [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fmdVGWOP-1665305355371)(https://note.youdao.com/yws/public/resource/fb5a63acd0c8da3e5e41921089f319e7/xmlnote/879F66158E8943249420831B233DDE7F/B2F7806F576846FBB2733092BAF9B961/60100)]

3.1.2 二进制

前导符 0b

特点:逢2进1 每一位上的数字 只能是 0 或者 1

例如:0b1110 0b1100

二进制转十进制:

从右到左算

0b1110 == 02^0 + 12^1 + 12^2 + 12^3 == 0 + 2 + 4 + 8 = 14

其他进制转换十进制都可以使用这种方式,只不过将底数的2换成对应进制的数字即可

也可以使用8421的方式转换

1000 --> 8

0100 --> 4

0010 --> 2

0001 --> 1

3.1.3 八进制

前导符 0 (是数字零 不是字母o)

特点:逢8进1 每一位上的数字范围 [0,7]

例如:0456 0666 0765

八进制转二进制:

方法1:八先转十 然后十转二

方法2:从右向左,1位八进制数表示 3位二进制数

0735 -->0b111011101

二进制转八进制:

从右向左,每3位二进制数表示 1位八进制数,高位不够补0

0b010110101 --> 0265

3.1.4 十六进制

前导符 0x

特点:逢16进1 每一位上的数字范围 0~9 a10 b11 c12 d13 e14 f15

例如:0x4F5D 0x1234 0xABCD

十六进制转二进制:

方法1:十六先转十 然后十转二

方法2:从右向左,1位十六进制数表示 4位二进制数

0x45EF -->0b0100010111101111

二进制转十六进制:

从右向左,每4位二进制数表示 1位十六进制数,高位不够补0

0b001010110101 --> 0x2B5

注意:不管几进制的数据,在计算机中都会转换成二进制来处理。

例如:

#include <stdio.h>

int main(int argc, const char *argv[])
{
	//int 是数据类型 是用来定义变量的
	//value 是我自己起的变量名 变量可以用来存储数据
	int value;

	value = 520;//用十进制的 520 给变量赋值
	printf("十进制 %d\n", value);// %d 是十进制的占位符
	printf("八进制 %#o\n", value);// %o 是八进制的占位符 #表示输出前导符
	printf("十六进制 %#x\n", value);// %x 是十六进制的占位符 #表示输出前导符
	//printf 函数没有按照二进制输出的方式 等后面我们学了位运算 可以自己写一个

	printf("-----------------\n");

	value = 0b10100011;//用二进制数 给变量赋值
	printf("十进制 %d\n", value);
	printf("八进制 %#o\n", value);
	printf("十六进制 %#x\n", value);

	printf("-----------------\n");
	
	value = 0765;//用八进制数 给变量赋值
	printf("十进制 %d\n", value);
	printf("八进制 %#o\n", value);
	printf("十六进制 %#x\n", value);

	printf("-----------------\n");
	
	value = 0xAB45;//用十六进制数 给变量赋值
	printf("十进制 %d\n", value);
	printf("八进制 %#o\n", value);
	printf("十六进制 %#x\n", value);

	return 0;
}

执行结果:

0

3.2 非数值型数据的存储

计算机中只能处理二进制的数值型数据,而在编码的过程中,经常也会出现一些非数值型的数据

如:网址、人名、企业名 等,所以科学家们就发明一种叫 ascii码 的东西,

专门用来表示非数值型数据

在C语言中遇到的 所有被单引号 或者 双引号引起来的 都是非数值型数据 ‘m’ ‘H’ “hqyj”

linux系统中可以使用 man ascii 来查看ascii码

常见的字符对应的ascii码

'\0'  --> 0
'\n'  --> 10
空格 SPACE --> 32
'0'~'9' --> 48~57
'A'~'Z' --> 65~90
'a'~'z' --> 97~122

​ 转义字符:

在C语言中,任何一个字符都可以使用一个 ‘’+八进制数 来表示

C语言中还定义了一个 ‘’ + 字母 来表示一些无法显示的字符

这些字符就叫做转义字符,因为字母已经不是本身的含义了

注意 : 转义字符虽然有两个符号 (一个反斜杠 和 一个字母),但是转义字符也是一个字符

四、词法符号

4.1 关键字

所谓的关键字就是编译器已经规定好的一些单词,直接使用即可,不用提前声明或者定义。

char short int long float double struct enum union signed unsigned void
const static extern register volatile auto
typedef
sizeof
if else switch case break default goto for while do return continue

4.2 标识符

标识符就是我们自己起的名字,如 变量名 函数名 结构体名 共用体名 等。。。

标识符的命名规范:

1.只能由数字、字母、或者下滑线组成

2.不能以数字开头

3.不能和关键字冲突

五、数据类型

5.1 概念

C语言的本质是操作内存。

内存和硬盘的区别:

内存:数据访问快 掉电丢失

硬盘:数据访问慢 掉电不丢失

C语言内存分配的最小单位是 字节 B

数据类型的作用:

相当于与一个模子,告诉操作系统需要给该类型定义的变量分配多大的内存空间。

不同的数据类型占用的内存空间大小是不一样的,

占用的内存空间大小不同,决定了能存储的数据范围也不同。

5.2 数据类型的分类

基本类型:

整数类型

实型(小数)

枚举类型

构造类型:

数组

结构体

共用体

指针类型:*

空类型:void

5.3 整数类型

整数类型又细分为 char(字符类型) short(短整型) int(整型) long(长整型) long long(长长整型)

都是整数类型,区别是占用的内存空间大小不同,能存储的数据范围不同

上面的每个类型又分为有符号(signed)的和无符号(unsigned)的

对于有符号数 最高位为符号位 剩下的叫数据位

符号位为0 正数 符号位为1 负数

如果不写有无符号,默认的都是有符号的

5.3.1 char

占用内存空间的大小 1字节 8bit

存储数据的范围

无符号:0 ~ 2^8-1

有符号:-2^7 ~ 2^7-1

有符号数说明:

​ 符号位 数据位

7 6 5 4 3 2 1 0

0 1 1 1 1 1 1 1 --> 2^7-1 最大值

1 0 0 0 0 0 0 0 --> -2^7 最小值

5.3.2 short

占用内存空间的大小 2字节 16bit

存储数据的范围

无符号:0 ~ 2^16-1

有符号:-2^15 ~ 2^15-1

5.3.3 int

占用内存空间的大小 4字节 32bit

存储数据的范围

无符号:0 ~ 2^32-1

有符号:-2^31 ~ 2^31-1

5.3.4 long

写可以写成 long int 输出占位符 %ld (小写的L)

在32位操作系统中 和 int 一样

在64位操作系统中 和 long long 一样

5.3.5 long long

写可以写成 long long int 输出占位符 %lld (小写的L)

占用内存空间的大小 8字节 64bit

存储数据的范围

无符号:0 ~ 2^64-1

有符号:-2^63 ~ 2^63-1

5.4 实型数据的存储

实型数据就是小数,也叫浮点型。 如:3.14

单精度浮点型 float 4字节

双精度浮点型 double 8字节

浮点型存储涉及到小数的二进制,是一个拼凑的近似值。

等我们后面学了指针、位运算等知识的时候,可以自己验证。

可以参考下面的博客。

https://blog.csdn.net/weixin_44767670/article/details/118084379

数据类型占用内存空间的大小存储数据的范围
char1字节 8bit无符号:2^8-1 有符号:-27–27-1
short2字节 16bit无符号:2^16-1 有符号:-215–215-1
int4字节 32bit无符号:2^32-1 有符号:-231–231-1
long在32位操作系统中 和 int 一样在64位操作系统中 和 long long 一样
long long8字节 64bit无符号:2^64-1 有符号:-263–263-1
float4字节 32bit无符号:2^32-1 有符号:-231–231-1
double8字节 64bit无符号:2^64-1 有符号:-263–263-1

六、原码、反码、补码的问题

数据在存储的时候设计到原码、反码和补码相互转换的问题。

原码:是给人类看的

反码:用来做原码和补码转换的

补码:是给计算机看的

无符号数:原码、反码、补码都是一样的

有符号的正数:原码、反码、补码都是一样的

有符号的负数:

反码 = 原码的符号位不变,其他位按位取反 0变1 1变0

补码 = 反码+1

注意:以char为例,1000 0000 规定为 -128 的补码

小技巧:存储时看数据(正负) 取出看类型(有无符号)

#include <stdio.h>

int main(int argc, const char *argv[])
{
	unsigned char a = 10;//正常
	//存储时:
	//原码: 0000 1010
	//反码: 0000 1010
	//补码: 0000 1010
	//取出时:
	//补码: 0000 1010
	//反码: 0000 1010
	//原码: 0000 1010 --> 10
	printf("a = %d\n", a);//10

	signed char b = -10;//正常
	//存储时:
	//原码: 1000 1010
	//反码: 1111 0101
	//补码: 1111 0110
	//取出时:
	//补码: 1111 0110
	//反码: 1111 0101
	//原码: 1000 1010 --> -10
	printf("b = %d\n", b);// -10

	signed char c = 129;//异常
    //正常范围-2^7--2^7-1  129超出范围但并未溢出,占据了符号位 
	//存储时:
	//原码: 1000 0001
	//反码: 1000 0001
	//补码: 1000 0001
	//取出时:
	//补码: 1000 0001
	//反码: 1000 0000
	//原码: 1111 1111 --> -127
	printf("c = %d\n", c);// -127

	unsigned char d = -1;//异常
    //原因:计算机按照无符号类型处理
	//存储时:
	//原码: 1000 0001
	//反码: 1111 1110
	//补码: 1111 1111
	//取出时:
	//补码: 1111 1111
	//反码: 1111 1111
	//原码: 1111 1111 --> 255
	printf("d = %d\n", d);// 255

	return 0;
}

练习:

signed char m = 135;

//存储时:

​ //原码: 1000 0111

​ //反码: 1000 0111

​ //补码: 1000 0111

​ //取出时:

​ //补码: 1000 0111

​ //反码: 1000 0110

​ //原码: 1111 1001 --> -121

printf(“m = %d\n”, m);//-121

七、常量

7.1 概念

在整个程序运行的过程中,值不会发生变化的量。

520 1314 3.14 “hqyj”

7.2 常量的分类

7.2.1 整型常量
常量类型前导符输出占位符例如
二进制0b0b1010
八进制0%#o0765
十进制%d1314
十六进制0x%x0xAB34
#include <stdio.h>

int main(int argc, const char *argv[])
{
	//常量一般是用来给变量赋值的
	short v1 = 520;
	printf("v1 = %d\n", v1);//520

	long int v2 = 1314;
	printf("v2 = %ld\n", v2);//1314

	long long int v3 = 0xAB34;
	printf("v3 = %#llx\n", v3);//0xab34

	return 0;
}
7.2.2 浮点型常量

浮点型常量(实型):

浮点型常量(实型)输出占位符例如
float%f3.14
double%lf(小写的L)5.28
字符常量%c‘M’ ‘8’ 单引号
字符串常量%s“hqyj” “www.baidu.com” 双引号
指数常量%e3.14e2 —> 3.14 * 10^2 --> 314
标识常量宏定义#define

程序中出现的小数,都是十进制小数。

一般形式(带有小数位的):

单进度 float 双精度 double

3.14 5.28

指数形式

格式: [+/-]M.Ne[+/-]T

如: -3.14e-2 --> -3.14*10^(-2) --> -0.0314

#include <stdio.h>

int main(int argc, const char *argv[])
{
	float f1 = 3.1415926;
	printf("f1 = %f\n", f1);//  3.141593 默认显示6位小数 超过的部分 四舍五入
	//也可以使用 %.nf 的方式 来指定显示n位小数
	printf("f1 = %.2f\n", f1);// 3.14

	//如果是double 占位要用 %lf
	double f2 = 3.1415926;
	printf("f2 = %lf\n", f2);// 3.141593 默认也是显示6位小数
	printf("f2 = %.2lf\n", f2);// 3.14

	//指数形式
	float f3 = 314;
	printf("指数: f3 = %e\n", f3);// 3.140000e+02  可以按指数形式输出

	//也可以使用指数常量给变量赋值
	float f4 = -5.67e-3;
	printf("f4 = %f\n", f4);//-0.005670

	return 0;
}
7.2.3 字符常量

C语言中所有的字符常量必须用 单引号 引起来,且单引号中只能引一个字符。

转义字符算一个字符

例如:‘m’ ‘H’ ‘8’ ‘\n’ ‘\0’ 注意 ‘8’ 和 8 是不一样的

输出方式:

想输出对应的字符 %c

想输出字符对应的ascii码 %d

#include <stdio.h>

int main(int argc, const char *argv[])
{
	//定义一个字符类型的变量 用来保存 字符常量 'H'
	char v1 = 'A';
	printf("v1 = [%d] [%c]\n", v1, v1);// 65  A

	//常量也可以直接输出  但是一般不这样用
	printf("[%d] [%c]\n", 'B', 'B');// 66 B
	printf("[%d] [%c]\n", '\n', '\n');// 10 换行
	printf("[%d] [%c]\n", 10, 10);// 10 换行

	//字符常量也可以参与运算  --本质就是 ascii码的运算
	char v2 = 'M'+1;  //v2中实际存储的是 'N' 的ascii码
	printf("v2 = [%d] [%c]\n", v2, v2);// 78 N

	char v3 = 67;//使用字符的ascii码给变量赋值也可以
	printf("v3 = [%d] [%c]\n", v3, v3);// 67 C

	//上述例子中可以得到结论:
	//字符就是整形 整形就是字符 具体看我们怎么用
	
	//思考
	//如何将 'M' 转换成 'm'  ?
	char v4 = 'M';
	//v4 = v4+32;
	v4 = v4+'a'-'A';
	printf("v4 = [%d] [%c]\n", v4, v4);// 109 m

	//思考
	//如何将 '8' 转换成 8  ?
    //意思是将字符类型'8'转换成整型8
	char v5 = '8';
	//v5 = v5 - 48;
	v5 = v5 - '0';
	printf("v5 = %d\n", v5);//8

	return 0;
}

]\n", v1, v1);// 65 A

//常量也可以直接输出  但是一般不这样用
printf("[%d] [%c]\n", 'B', 'B');// 66 B
printf("[%d] [%c]\n", '\n', '\n');// 10 换行
printf("[%d] [%c]\n", 10, 10);// 10 换行

//字符常量也可以参与运算  --本质就是 ascii码的运算
char v2 = 'M'+1;  //v2中实际存储的是 'N' 的ascii码
printf("v2 = [%d] [%c]\n", v2, v2);// 78 N

char v3 = 67;//使用字符的ascii码给变量赋值也可以
printf("v3 = [%d] [%c]\n", v3, v3);// 67 C

//上述例子中可以得到结论:
//字符就是整形 整形就是字符 具体看我们怎么用

//思考
//如何将 'M' 转换成 'm'  ?
char v4 = 'M';
//v4 = v4+32;
v4 = v4+'a'-'A';
printf("v4 = [%d] [%c]\n", v4, v4);// 109 m

//思考
//如何将 '8' 转换成 8  ?
//意思是将字符类型'8'转换成整型8
char v5 = '8';
//v5 = v5 - 48;
v5 = v5 - '0';
printf("v5 = %d\n", v5);//8

return 0;

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值