learn_C_deep_4 (类型和变量命名、sizeof(int) *p表示什么意思、原码、反码和补码的概念、计算机中数据计算时,为什么要转为二级制、unsigned和signed关键字)

本文涉及的产品
云原生大数据计算服务 MaxCompute,5000CU*H 100GB 3个月
云原生大数据计算服务MaxCompute,500CU*H 100GB 3个月
简介: learn_C_deep_4 (类型和变量命名、sizeof(int) *p表示什么意思、原码、反码和补码的概念、计算机中数据计算时,为什么要转为二级制、unsigned和signed关键字)

类型和变量命名


C语言为什么要有类型


类型是编程语言中一项非常基础的概念。它是用来描述数据的种类或数据类型的,可以是基本类型,如整数、浮点数、字符等,也可以是由基本类型组成的复合类型,如数组、结构体等。类型的存在有以下几个作用:


1. 内存分配:不同类型的数据需要占用不同大小的内存空间,类型可以告诉编译器为变量分配多大的内存空间。

2. 数据验证:类型可以帮助编译器验证数据的完整性和正确性。例如,如果一个变量被声明为整数类型,那么它就只能存储整数值,如果我们试图将它赋值为字符串或其他数据类型,编译器就会给出错误提示。

3. 数据处理:不同类型的数据有着不同的处理方式,例如整数和浮点数的运算方式就是不同的。因此类型可以告知编译器对数据进行何种运算或操作。

总之,类型让程序员可以更加准确地控制和处理数据。同时,类型也可以帮助编译器在编译时进行静态类型检查,防止一些错误在运行时才被发现,提高程序的可靠性和稳定性。


为什么又有那么多种数据类型


C语言有这么多不同的数据类型,是为了满足不同的需求,更确切地表示各种不同类型的数据。不同的数据类型在存储数据时占用不同的内存空间,也有不同的精度和范围,因此程序员需要根据具体的情况来选择合适的数据类型。

例如,在需要存储一个整数时,如果使用char类型,虽然它能够存储整数,但是它只能够存储非常小的整数,如果需要存储较大的整数,就需要使用int类型或long类型。同样的道理,如果需要存储小数,就需要使用float类型或double类型,因为它们具有更高的精度。

此外,不同的数据类型在编写程序时也有不同的用途。例如,指针类型用于动态内存管理,结构体类型用于组织复杂的数据,枚举类型用于在程序中定义特定的常量等等。


变量的命名规则


在C语言中,变量的命名必须遵循以下规则:


1. 变量名只能由字母、数字和下划线组成,不能使用其他符号。

2. 变量名必须以字母或下划线开头。

3. 变量名不能使用C语言中的关键字(例如,if、for、while等)。

4. 变量名的长度没有限制,但在实际编程中,建议将变量名控制在20个字符以内,以方便阅读和维护。

5. 变量名区分大小写,因此,变量名abc和ABC是不同的变量。

6. 变量名应该选择有意义的名称,能够清晰地反映变量的含义。


变量的命名规范


1. 使用有意义的变量名:应该使用能够清楚反映变量含义的名称,例如,使用count来表示计数器变量。

2. 使用小写字母:建议使用小写字母来表示变量名。这种命名方式更容易阅读和维护代码。 3. 使用驼峰命名法:对于由多个单词组成的变量名,可以使用驼峰命名法来表示,即第一个单词以小写字母开始,后续单词的首字母大写。例如,可以使用studentName来表示学生姓名。

4. 不要使用缩写和简写:尽量避免使用缩写和简写来表示变量名。这样的命名方式很容易引起歧义,降低代码的可读性。

5. 避免使用数字开头:变量名不能以数字开头,因为在C语言中,数字开头的名称会被解释为常量。

6. 使用下划线作为单词之间的分隔符:在驼峰命名法中,需要使用下划线作为单词之间的分隔符。例如,student_name。

7. 注意命名空间:变量名应该跟变量所属的函数相关,避免命名冲突。

8.使用"g_"或 "s_"前缀:建议在全局变量名前加上"g_"或 "s_"前缀,以便区别于局部变量。其中,"g_"表示全局变量,"s_"表示静态全局变量。

9.所有的宏定义、枚举常量、只读变量全用大写字母命名,用下划线线分割。


定义变量一定要初始化


#include<stdio.h>
int main()
{
  int a;
  printf("%d", a);
  //vs编译器直接禁止使用未初始化的变量
  //error C4700: 使用了未初始化的局部变量“a”
  return 0;
}


  如果您声明了一个局部变量但没有初始化它,那么这个变量的初始值将是未定义的,并且其内容可能是任意值。打印未初始化的变量的值是一种不确定行为,因为其内容是不确定的,可能会有垃圾值、0或其他值。


sizeof(int) *p表示什么意思


       继上章的sizeof关键字,我们接着来讲解sizeof关键字,先回忆回忆sizeof是干嘛的

#include<stdio.h>
int main()
{
  int* p = NULL; //声明一个指向整型变量的指针,赋初值为NULL。
  int arr[10]; //声明一个包含10个整型变量的数组。
  int* test[3]; //声明一个包含3个指向整型变量的指针数组。
  printf("%d\n", sizeof(p));//4
  printf("%d\n", sizeof(arr));//40
  printf("%d\n", sizeof(test));//12
  return 0;
}


`sizeof`是C和C++中的一个操作符,用于获取其操作数(变量、类型、表达式等)的字节大小。


那么现在来解释一下sizeof(int) *p表示什么意思。


`sizeof(int)`是一个求整型变量大小的操作符,它返回类型`int`在内存中占据的字节数。通常情况下,一个`int`类型变量占据4个字节(32位系统)或者8个字节(64位系统),具体取决于编译器和操作系统的实现。

`*p`是指针运算符,用来访问指针所指向的内存地址处的值。`p`是一个指向某个整型变量的指针。

因此,`sizeof(int) *p`表示用一个指向整型变量的指针`p`存储一个整型变量的大小。因为一个`int`类型变量通常占据4个字节,所以这条语句等价于`4 *p`。

注意,`sizeof`是一个关键字,而不是函数,不需要用括号将它的参数括起来。在这个例子中,括号会被认为是指向一个函数的指针,而不是求类型大小的操作符。因此,正确的写法应该是`sizeof(int) * p`。


原码、反码和补码的概念


原码(Sign-Magnitude):原码是二进制表示有符号整数的最简单方式,它的表示方法就是使用二进制数,最高位表示符号位,0表示正数,1表示负数。例如,+5的原码为00000101,-5的原码为10000101。原码的优点是简单直观,易于理解,但是存在着符号位和数值位的处理不一致的问题。


反码(One's Complement):反码是在原码的基础上,为了解决符号位和数值位处理不一致的问题而设计的。对于正数,其反码就是其原码本身;对于负数,反码的符号位一定是1,数值部分则取原码的数值部分按位取反(0变成1,1变成0),得到的二进制码就是该负数的反码表示。例如,+5的反码为00000101,-5的反码为11111010。反码的优点是对于数值部分的计算仍然是直接相加,但是符号位仍需要额外判断。


补码(Two's Complement):补码是在反码的基础上,为了解决符号位和数值位处理不一致的问题而产生的。补码表示负数时,先将其转换为其反码,再将反码加1得到补码;补码表示正数时,与原码一样。例如,+5的补码为00000101,-5的补码为11111011。补码的优点在于符号位的处理与数值位的处理是统一的,不需要特殊处理。在补码的表示方式下,负数的补码是它的绝对值的原码按位取反再加1,正数的补码和原码一样。


       总的来说,原码、反码和补码都是表示整数的方法,但是它们对于负数的处理方式不同,补码是最常用的表示方法,也是计算机中进行加减运算时的默认方式,因为补码可以实现符号位和数值位的统一处理,同时在计算机中进行加减运算时也非常方便。


计算机中数据计算时,为什么要转为二级制


       二进制是一种只包含二个数字(0和1)的进制,这种进制可以用来表示所有数字、文字、图形等。而计算机中的所有操作都是由电子元器件完成的,这些元器件只能表示两种状态(电信号的通/断状态),即0和1,所以在计算机中使用二进制可以更直接地与硬件电路之间进行交互。具体来说,计算机将二进制位串(由一系列0和1组成的序列)转换为数字、文字、图形等,进行处理后再将其转换为二进制位串储存到计算机存储器中,在需要时再将其读取并进行相应的操作,最后再将其转换为人类可读的形式输出。这种转换过程虽然看似繁琐,但是计算机中的各种运算、逻辑判断、图像处理等操作都是以二进制数值形式进行的,因此转换为二进制有助于计算机进行高效的运算和存储。所以任何数据在计算中中,都必须转为二级制。


unsigned和signed关键字


unsigned和signed关键字的理解


       在计算机中,整数类型的表示和存储通常是通过二进制补码来完成的。对于有符号整数类型(即signed类型),最高位是符号位,0表示正数,1表示负数。如果要表示-1这个数,需要使用二进制补码来表示,即将1的二进制码取反(变成0),再加1,得到11111111(表示-1的补码),正数的原反补码相同。


而对于无符号整数类型(即unsigned类型),没有符号位,其所有二进制位都表示数值,最小值为0。其原反补码都相同,因此,对于unsigned类型的整数,它只能表示非负整数,而无法表示负数。


因为signed和unsigned类型的表示方式不同,所以它们在使用时需要注意:


1. 范围不同:带符号类型能够表示的整数范围是从负的最大值到正的最大值,而无符号类型只能表示从0到正的最大值。

2. 溢出问题:在进行运算时,如果signed类型的值超过了其范围,会出现溢出现象。而unsigned类型的值超过了其范围,则会进行“回绕”,即从最小值重新开始。

3. 运算方式不同:在进行运算时,signed类型和unsigned类型的运算方式也有所不同。比如,在进行位运算时,signed类型的值会进行符号扩展,而unsigned类型的值则会进行零扩展。


计算二进制的便捷方法 - 2^n


#include<stdio.h>
int main()
{
  //计算机内存储的整形必须是补码
  int a = 10;
  //任何数据在计算中中,都必须转为二级制
  //符号位(0,1) + 数据位
  //有符号正数,原反补码相同
  //0000 0000 0000 0000 0000 0000 0000 1010 - 原码、反码、补码
  //16进制
  //0x00 00 00 0a
  int b = -20;
  //16+4 16 = 2^4   4 = 2^2
  //2^n次方 二级制1后面就有n个0
  //16 = 2^4  10000
  //4 = 2^2   00100
  //         相加
  //因为-20是负数 int - 4字节 - 32位
  //最高位是符号位 - 负数 - 1
  //1000 0000 0000 0000 0000 0000 0001 0100 - 原码
  //1111 1111 1111 1111 1111 1111 1110 1011 - 反码,符号位不变,其他按位取反
  //1111 1111 1111 1111 1111 1111 1110 1100 - 补码,反码加1
  //16进制
  //0xff ff ff ec
  return 0;
}


计算补码的方法


计算补码的方法如下:


1. 对于正数,其原码、反码和补码相同。

2. 对于负数,先求其绝对值的二进制表示的反码(即除符号位外的各位取反),然后再将其反码加1得到其补码。


例如,假设要求-5的补码,步骤如下:


       1. 5的二进制表示为0000 0101,因为是正数,所以补码、反码和原码都相同,都是0000 0101。

       2. 将其转换为负数,即符号位变为1,得到1000 0101。

       3. 除符号位外的各位取反,得到1111 1010,这就是-5的反码。

       4. 将反码加1,得到1111 1011,这就是-5的补码。


因此,-5的补码是1111 1011。需要注意的是,在计算机中,通常采用补码表示有符号整数,这样可以避免加减法、逻辑运算等操作的特殊处理。


计算原码的方法


原码是一种二进制数的表示方法,符号位为0表示正数,为1表示负数。计算原码的方法如下:


1. 对于正数,直接将其转换为二进制数即可得到原码。

2. 对于负数,先将其转换成绝对值的二进制数,然后将该二进制数的每个位取反(0变成1,1变成0),最后再将符号位变成1即可得到原码。

3.通过补码求原码


3.1.-20的补码 -> 原码    

方法一:
1111 1111 1111 1111 1111 1111 1110 1100 - 补码 
1111 1111 1111 1111 1111 1111 1110 1011 - 反码 = 补码 - 1
1000 0000 0000 0000 0000 0000 0001 0100 - 原码 = 反码按位取反,符号位不变

3.2.-20的补码 -> 原码  

方法二:
1111 1111 1111 1111 1111 1111 1110 1100 - 原码
1000 0000 0000 0000 0000 0000 0001 0011 - 反码,符号位不变,其他按位取反
1000 0000 0000 0000 0000 0000 0001 0100 - 补码,反码加1


将上面的10和-20的补码转为16进制分别是0x00 00 00 0a和0xff ff ff ec,那我们再来看看它在计算机的内存是怎么存储的。


但是我们发现和我们计算的十六进制有一些区别,计算机的顺序好像是到过来的,这里我们就需要了解计算机存储数据的方式 - 大小端


大小端概念


       大小端(Endianness)是用于描述不同类型的计算机中多字节数据的存储方式。简单来说就是指定了大字节和小字节的存储顺序。一个字节通常由8个二进制位组成,而多字节数据是由多个字节组成的。在存储多字节数据时,我们需要确定这些字节在内存中的排列顺序。 具体来说,大端模式(Big Endian)是将最高有效位存放在最低的内存地址,而小端模式(Little Endian)则是将最低有效位存放在最低的内存地址。在大端模式中,字节序列的存储顺序与它们在数值序列中的顺序一致;而在小端模式中,字节序列的存储顺序与它们在数值序列中的顺序相反。 例如,十六进制值为0x12345678的32位整数,在大端模式中的存储顺序为12 34 56 78,而在小端模式中的存储顺序为78 56 34 12。 不同的处理器和操作系统使用的大小端模式可能不同,因此在进行数据交换和传输时,需要注意其大小端模式的差异。


所以我们刚刚求解的十六进制是大端模式,而我们的电脑存储数据的方式是小端模式。


反码在进行+1的操作时候,符号位也是要参与运行的


接下来我们看一下下面的代码是否正确


#include<stdio.h>

int main()

{

   unsigned int a = 10;//right

   unsigned int b = -10;//?


   //编译不报错

   return 0;

}

       在这个代码中,将-10赋值给了unsigned int类型的变量b。由于unsigned int是无符号整型,它的取值范围是0~4294967295,因此b实际上存储的是4294967286,这是-10的补码在无符号整型范围内的表示。

相关实践学习
基于MaxCompute的热门话题分析
本实验围绕社交用户发布的文章做了详尽的分析,通过分析能得到用户群体年龄分布,性别分布,地理位置分布,以及热门话题的热度。
SaaS 模式云数据仓库必修课
本课程由阿里云开发者社区和阿里云大数据团队共同出品,是SaaS模式云原生数据仓库领导者MaxCompute核心课程。本课程由阿里云资深产品和技术专家们从概念到方法,从场景到实践,体系化的将阿里巴巴飞天大数据平台10多年的经过验证的方法与实践深入浅出的讲给开发者们。帮助大数据开发者快速了解并掌握SaaS模式的云原生的数据仓库,助力开发者学习了解先进的技术栈,并能在实际业务中敏捷的进行大数据分析,赋能企业业务。 通过本课程可以了解SaaS模式云原生数据仓库领导者MaxCompute核心功能及典型适用场景,可应用MaxCompute实现数仓搭建,快速进行大数据分析。适合大数据工程师、大数据分析师 大量数据需要处理、存储和管理,需要搭建数据仓库?学它! 没有足够人员和经验来运维大数据平台,不想自建IDC买机器,需要免运维的大数据平台?会SQL就等于会大数据?学它! 想知道大数据用得对不对,想用更少的钱得到持续演进的数仓能力?获得极致弹性的计算资源和更好的性能,以及持续保护数据安全的生产环境?学它! 想要获得灵活的分析能力,快速洞察数据规律特征?想要兼得数据湖的灵活性与数据仓库的成长性?学它! 出品人:阿里云大数据产品及研发团队专家 产品 MaxCompute 官网 https://www.aliyun.com/product/odps&nbsp;
相关文章
|
30天前
|
存储 C语言
使用 sizeof 操作符计算int, float, double 和 char四种变量字节大小
【10月更文挑战第13天】使用 sizeof 操作符计算int, float, double 和 char四种变量字节大小。
76 1
|
1月前
|
Python
[oeasy]python036_数据类型有什么用_type_类型_int_str_查看帮助
本文回顾了Python中`ord()`和`chr()`函数的使用方法,强调了这两个函数互为逆运算:`ord()`通过字符找到对应的序号,`chr()`则通过序号找到对应的字符。文章详细解释了函数参数类型的重要性,即`ord()`需要字符串类型参数,而`chr()`需要整数类型参数。若参数类型错误,则会引发`TypeError`。此外,还介绍了如何使用`type()`函数查询参数类型,并通过示例展示了如何正确使用`ord()`和`chr()`进行转换。最后,强调了在函数调用时正确传递参数类型的重要性。
21 3
|
3月前
|
Java
【Java基础面试五】、 int类型的数据范围是多少?
这篇文章回答了Java中`int`类型数据的范围是-2^31到2^31-1,并提供了其他基本数据类型的内存占用和数值范围信息。
【Java基础面试五】、 int类型的数据范围是多少?
|
3月前
|
自然语言处理 Go 数据安全/隐私保护
对 int 类型的数据加密,有哪些好的方案?
对 int 类型的数据加密,有哪些好的方案?
99 13
|
3月前
|
存储 Java 索引
32 位和 64 位 JVM 中 int 变量的大小解析
【8月更文挑战第21天】
203 0
|
5月前
|
机器学习/深度学习 人工智能 分布式计算
人工智能平台PAI产品使用合集之int类型是否可以为raw feature
阿里云人工智能平台PAI是一个功能强大、易于使用的AI开发平台,旨在降低AI开发门槛,加速创新,助力企业和开发者高效构建、部署和管理人工智能应用。其中包含了一系列相互协同的产品与服务,共同构成一个完整的人工智能开发与应用生态系统。以下是对PAI产品使用合集的概述,涵盖数据处理、模型开发、训练加速、模型部署及管理等多个环节。
|
5月前
|
运维 Cloud Native 关系型数据库
云原生数据仓库AnalyticDB产品使用合集之布尔类型和int类型可以自动转换吗
阿里云AnalyticDB提供了全面的数据导入、查询分析、数据管理、运维监控等功能,并通过扩展功能支持与AI平台集成、跨地域复制与联邦查询等高级应用场景,为企业构建实时、高效、可扩展的数据仓库解决方案。以下是对AnalyticDB产品使用合集的概述,包括数据导入、查询分析、数据管理、运维监控、扩展功能等方面。
157 1
|
4月前
|
存储 Python
语音输入,python数据类型,type()用来查看数据类型,数据类型转换,int(x)转整数,float(x)转换为浮点数,str(x),将对象转为字符串,标识符,标识符不允许使用关键字,关键字参考
语音输入,python数据类型,type()用来查看数据类型,数据类型转换,int(x)转整数,float(x)转换为浮点数,str(x),将对象转为字符串,标识符,标识符不允许使用关键字,关键字参考
|
6月前
channelSftp.put(InputStream src, String dst, int mode);里的mode都是什么类型的
【5月更文挑战第15天】channelSftp.put(InputStream src, String dst, int mode);里的mode都是什么类型的
96 2
|
6月前
|
SQL 关系型数据库 MySQL
unsigned int 虽然mysql支持,但是不建议使用,因为可能在未来某个版本删除
unsigned int 虽然mysql支持,但是不建议使用,因为可能在未来某个版本删除
46 2