首页 > 其他分享 >C语言学习日志3-关键字ii

C语言学习日志3-关键字ii

时间:2024-06-07 16:55:06浏览次数:19  
标签:int 补码 unsigned signed C语言 ii 0xFFFFFFFF printf 日志

1.4,signed、unsigned 关键字
编译器缺省默认情况下数据为 signed 类型 的。

举例:
上面的解释很容易理解,下面就考虑一下这个问题:

include<stdio.h>

include<string.h>

int main()
{
char a[1000];
int i;
for (i = 0; i < 1000; i++)
{
a[i] = -1 - i;
//printf("a[%d] = 0x%x\n", i, a[i]);
//printf("a[%d] = %c\n", i, a[i]);
}
printf("%d", strlen(a));
return 0;
}
我们知道在计算机系统中,数值一律用补码来表示(存储)。int在真正存储在内存中的二进制数不是值的原码,而是其补码。主要原因是使用补码,可 以将符号位和其它位统一处理;同时,减法也可按加法来处理。另外,两个用补码表示的数 相加时,如果最高位(符号位)有进位,则进位被舍弃。正数的补码与其原码一致;负数的 补码:符号位为 1,其余位为该数绝对值的原码按位取反,然后整个数加 1。
按照负数补码的规则,可以知道-1 的补码为 0xff,-2 的补码为 0xfe
当 i 的值为 127 时,a[127]的值为-128,而 -128 是 char 类型数据能表示的最小的负数。当 i 继续增加,a[128] 的值肯定不能是-129。因为这时候发生了溢出,-129 需要 9 位才能存储下来,而 char 类型 数据只有 8 位,所以最高位被丢弃。剩下的 8 位是原来 9 位补码的低 8 位的值,即 0x7f。 当 i 继续增加到 255 的时候,-256 的补码的低 8 位为 0。然后当 i 增加到 256 时,-257 的补 码的低 8 位全为 1,即低八位的补码为 0xff,如此又开始一轮新的循环......
按照上面的分析,a[0]到 a[254]里面的值都不为 0,而 a[255]的值为 0。strlen 函数是计 算字符串长度的,并不包含字符串最后的‘\0’。而判断一个字符串是否结束的标志就是看 是否遇到‘\0’。如果遇到‘\0’,则认为本字符串结束。

\0 在 C 语言中表示空字符或空终止符(null terminator)。它的 ASCII 编码值是 0。在 ASCII 编码中,值为 0 的字符就是空字符。它没有任何可打印的字符形式,通常用于表示字符串的结尾。空字符 \0 是 ASCII 编码中 128 个字符中的一个。它的编码值是 0x00,对应二进制 00000000。空字符 \0 作为字符串的结束标志非常重要。它允许应用程序确定字符串的长度,而不需要保存字符串长度的额外信息。在 C 语言中,字符串常量的最后一个字符总是空字符 \0。这是 C 语言字符串处理的基础。

留三个问题:
1),按照我们上面的解释,那-0 和+0 在内存里面分别怎么存储?
2),int i = -20; unsigned j = 10; i+j 的值为多少?为什么?
3), 下面的代码有什么问题?
unsigned i ;
for (i=9;i>=0;i--)
{
printf("%u\n",i);
}

1)正零 (+0) 的存储:在计算机中,正零 (+0) 通常以 00000000 的二进制形式存储。也就是说,正零的位模式是全 0。这种表示方式是唯一的,没有其他的正零表示。负零 (-0) 的存储:负零 (-0) 的二进制位模式是 10000000。也就是说,负零的最高位是 1,表示负数,其余位都是 0。这种表示方式与正零的位模式是不同的。

2)当表达式中存在有符号类型和无符号类型时所有的操作数都自动转换为无符号类型。
标准转换的规则是:短的的向长的转;有符号的向无符号的转。
无符号十进制数 = 2^32 + 补码对应的有符号十进制数。
因为int i = -20,所以unsigned int i = 2^32 - 20(十进制)。
所以i+j = unsigned int i + unsigned int j = 2^32 - 20 + 10 = 2^32 - 10(十进制)= 4294967296 -10 = 4294967286。

int i = -20; unsigned int j = 10; i+j 的值为多少?
//-20(补码) = 0xFFFFFFEC;
//int i = 0xFFFFFFEC;
//i + j = unsigned int i + unsigned int j;
//int i -> unsigned int i;(signed -> unsigned)
//unsigned int i = 0xFFFFFFEC;
//i = 4294967276(十进制);
//(i+j) = 4294967276 + 10 = 4294967286

3)
//当i==-1时,unsigned i = 4294967295;

补充1:unsigned 和 signed 类型相互转换
1)unsigned → signed 的时候:
如果位数相同,直接复制;
如果位数不同:
① unsigned 位数 < signed 位数,unsigned 直接复制到 signed 低位,signed 高位填0;
② unsigned 位数 > signed 位数,直接装载 unsigned 低位到 signed 。
2)signed → unsigned 的时候:
如果位数相同,直接复制;
如果位数不同:
① signed 位数 < unsigned 位数,signed 直接复制到 unsigned 低位,unsigned 高位填符号位
(如果 signed 是负数,则 unsigned 高位填1,;如果 signed 是正数,则 unsigned 高位填0);
② signed 位数 > unsigned 位数,直接装载 signed 低位到 unsigned 。

举例1:

include <stdio.h>

//32位系统
int main(int argc, char* argv[])
{
unsigned char a = -1;
char b = a;
printf("%d %d", a, b);

return 0;

}
//-1(补码) = 0xFFFFFFFF;
//unsigned char a = 0xFF;(char 1 byte)
//char b = 0xFF;(unsigned -> signed)
//printf("%d %d", a, b)
//unsigned char a -> int a;(unsigned -> signed)
//int a = 0x00FF;(int 4 byte)
//char b -> int b
//int b = 0xFFFF;
//a = 255(十进制)
//b = -1(十进制)

举例2:

include <stdio.h>

//32位系统
int main(int argc, char* argv[])
{
unsigned short a = -1;
short b = a;
printf("%d %d", a, b);

return 0;

}
//-1(补码) = 0xFFFFFFFF;
//unsigned short a = 0xFFFF;(short 2 byte)
//short b = 0xFFFF;(unsigned -> signed)
//printf("%d %d", a, b);
//unsigned short a -> int a;(unsigned -> signed)
//int a = 0x0000FFFF;(int 4 byte)
//short b -> int b
//int b = 0xFFFFFFFF;
//a = 65535(十进制)
//b = -1(十进制)

举例3:

include <stdio.h>

//32位系统
int main(int argc, char *argv[])
{
unsigned int a = -1;
int b = a;
printf("%d %d", a, b);
printf("%u %u", a, b);

return 0;

}
//-1(补码) = 0xFFFFFFFF;
//unsigned int a = 0xFFFFFFFF;(int 4 byte)
//int b = 0xFFFFFFFF;(unsigned -> signed)
//printf("%d %d", a, b);
//unsigned int a -> int a;(unsigned -> signed)
//int a = 0xFFFFFFFF;(int 4 byte)
//int b = 0xFFFFFFFF;
//a = -1(十进制)
//b = -1(十进制)
//printf("%u %u", a, b);
//unsigned int a = 0xFFFFFFFF;
//int b -> unsigned int b;(signed -> unsigned)
//unsigned int b = 0xFFFFFFFF;
//a = 4294967295(十进制)
//b = 4294967295(十进制)

举例4:
int a = -1;
unsigned int b = -1;
printf("%d\n", a + b);
//-1(补码) = 0xFFFFFFFF;
//int a = 0xFFFFFFFF;(int 4 byte)
//unsigned int b = 0xFFFFFFFF;
//printf("%d\n", a + b);
//a + b = unsigned int a + unsigned int b;
//unsigned int a = 0xFFFFFFFF;(signed -> unsigned)
//unsigned int (a + b) = 0xFFFFFFFE;(溢出,保留后32位)
//int (a + b) = 0xFFFFFFFE;(unsigned -> signed)
//(a + b) = 4294967294(十进制);

标签:int,补码,unsigned,signed,C语言,ii,0xFFFFFFFF,printf,日志
From: https://www.cnblogs.com/robinly/p/18233146

相关文章

  • Day24.日志字典的使用
    1.settings.py文件中的代码配置 1"""2logging配置,settings文件中的代码配置3"""45importos67os.chdir(os.path.dirname(os.path.abspath(__file__)))89#1、定义三种日志输出格式,日志中可能用到的格式化串如下10#%(name)sLogger的名......
  • 零基础非科班也能掌握的C语言知识18 自定义类型
    自定义类型1.结构体1.1结构的声明1.2结构体变量的创建和初始化1.2.1普通声明1.2.2嵌套声明1.2.3不完全声明(匿名结构体)1.3结构成员访问操作符1.3.1结构体成员的直接访问1.3.2结构体成员的间接访问1.4结构体的自引用1.5结构体内存对齐1.5.1对齐规则1.5.2为什么存在内......
  • 实验6_C语言结构体、枚举应用编程
    实验任务4#include<stdio.h>#defineN10typedefstruct{charisbn[20];//isbn号charname[80];//书名charauthor[80];//作者doublesales_price;//售价intsales_count;//销售册数}Book;voi......
  • 6.C语言scanf及其他输入知识点
    C语言scanf相关用法及其他输入1—scanf输入的用法2—scanf注意的问题3—其他输入1—scanf输入的用法程序#include"stdio.h"intmain(){ intdata; intdata2; intdata3; printf("输入一个整数:\n"); scanf("%d",&data); printf("输入完毕\n"); printf(......
  • C语言基础——函数
             ʕ•ᴥ•ʔ       づ♡ど ......
  • 使用ADB查看安卓调试日志
    使用ADB查看安卓调试日志安装ADB工具‍官网下载地址:http://adbdownload.com/根据自己的操作系统选择下载对应的安装包,本文以Windows为例‍连接安卓设备将设备(如手机/平板)的USB调试打开,不同设备和不同版本的开启方式不同,根据实际情况处理.USB调试打开之后,将设备(如......
  • C语言入门 第三章 数据和变量
    目录3.1数据3.1.1整数3.1.2浮点数3.2变量与常量3.2.1定义变量 3.2.2变量分类3.2.3变量的作用域与生命周期 3.2.4常量 3.3基本数据类型 3.3.1int类型 3.3.2其他整数类型3.3.3char类型3.3.4_Bool类型 3.3.5float、double和longdouble类型 3.......
  • 使用ADB查看安卓调试日志
    使用ADB查看安卓调试日志安装ADB工具‍官网下载地址:http://adbdownload.com/根据自己的操作系统选择下载对应的安装包,本文以Windows为例‍连接安卓设备将设备(如手机/平板)的USB调试打开,不同设备和不同版本的开启方式不同,根据实际情况处理.USB调试打开之后,将设备(如......
  • 在Linux中,有哪些系统日志文件?
    在Linux系统中,系统日志文件是记录系统操作、运行状态、错误信息以及安全事件等的重要文件。以下是Linux中常见的系统日志文件及其简要描述:系统日志(SystemLogs):这些日志记录了系统整体运行情况、错误信息等。常见的系统日志文件包括/var/log/messages、/var/log/syslog等。这......
  • Day24.日志级别
    1.日志级别_日志配置#一:日志配置logging.basicConfig(  #1、日志输出位置:1、终端2、文件  #filename='access.log',#不指定,默认打印到终端  #2、日志格式  format='%(asctime)s-%(name)s-%(levelname)s-%(module)s: %(message)s',  #......