C语言之(有关%d和%u的有关内容,输出方法)(有符号和无符号在内存中的存储情况)(整形无符号数和有符号数是如何进行计算的,整形无符号数和有符号数在循环中的应用举例)

简介: C语言之(有关%d和%u的有关内容,输出方法)(有符号和无符号在内存中的存储情况)(整形无符号数和有符号数是如何进行计算的,整形无符号数和有符号数在循环中的应用举例)

在C语言的课本中,我们常见的是%u,但我们平时在写代码常用的确是%d,它们二者之间有什么区别呢?

表示形式上

%u表示输入输出格式说明符,是按照unsigned int(无符号十进制数据)格式输入或输出数据。%d则表示signed

int(有符号十进制数据)格式输入或输出数据。


举例:

#include<stdio.h>
int main()
{
  char a = -28;
  printf("%d\n", a);
  printf("%u\n", a);
  return 0;
}


上篇我们讲述了char类型的数据用%d的形式是如何输出的,不懂的小伙伴可以去看上篇文章,这里我们主要讲述

以%u的形式如何输出:

首先我们先写出变量a的二进制形式:

//原码:10000000000000000000000010000000

//反码:1111111111111111111111111111011111111

//补码:111111111111111111111111111110000000

进行截断:10000000

进行整型提升:111111111111111111111110000000-----该数的补码

由于该数要以%u,无符号的形式进行打印,所以原码,补码,反码相同。即打印结果:4292967168

下面我们通过一张图来了解有符号和无符号在内存中的存储情况。


通过上面这张图,我们了解到有符号字符存储的范围是127---- -128,那么如果想表示大于127的正数呢?它是一个对称的原则,大于127的整数直接进行跳转到左半边圆表示的范围。

如下所示代码会输出什么样的结果?

#include<stdio.h>
int main()
{
  char a = -128;
  char b = 128;
  printf("%u\n", a);
  printf("%u\n", b);
  return 0;
}


128和-128的输出结果一样,由于有符号整数的范围已经被限制,直接代数加一定是不可取的,不过通过上面这张图我们可以得出当为有符号整数128,就相当于127加1,也就是-128。

之前我们学过了字符型的unsigned char/signed char是如何进行相加减运算的,这篇我们就来讲讲

整形的unsigned int/signed int是如何进行运算的:

举例:

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

我们让代码跑起来看看运行结果:

-10

那么它的计算过程是什么样的呢?

分析过程如下:

和之前char类型相似,首先写出两个变量的补码:

int i = -80;
  //原码:10000000000000000000000000010100
  //反码:11111111111111111111111111101011
  //补码:1111111111111111111111110111101100
unsigned int j = -10;(由于是无符号整形,原码,反码,补码均相同)
  //原码/反码/补码:00000000000000000000000000001010
i + j:
  //补码:     11111111111111111111111111101100
  //原码/反码/补码:00000000000000000000000000001010
  //i+j:补码      11111111111111111111111111110110
  //i+j:反码      11111111111111111111111111110101
  //i+j:原码      10000000000000000000000000001010

unsigned int和signed int类型的运算和char类型不同的地方在于,它不需要整形提升这一过程。

学习了unsigned int的定义和运算方法之后,下面我们来学习

它在循环中的应用:

首先我们先来看一串代码:

#include<stdio.h>
#include<windows.h>
int main()
{
  unsigned int i;
  for (i = 9; i >= 0; i--)
  {
    printf("%u\n", i);
    Sleep(100);
  }
  return 0;
}

请问它的输出结果是多少呢?如果你认为是9,8,7,6,5,4,3,2,1,0那你就大错特错了。

正确的输出结果应该是无限循环,那么有的人会问为什么是无限循环呢?

下面我们对这串代码进行分析,首先变量i被定义的类型是unsigned int而不是int,这就决定了它是不可能取到负数的,因此i>=0永远满足条件,程序会进行无限循环。


下面我们再来看一个关于char类型的应用实例:
#include<stdio.h>
#include<string.h>
int main()
{
  char a[1000];
  int i;
  for (i = 0; i < 1000; i++)
  {
    a[i] = -1 - i;
  }
  printf("%d", strlen(a));
  return 0;
}

这串代码的输出结果又会是什么呢?

我们先对代码进行分析,首先定义字符型数组a,再使用变量i访问数组元素,当i=0,a[i]=-1,当i=1,a[i]=-2,当i=2,a[i]=-3以此类推,那么有的同学会因此得出strlen(a)的长度不就是1000吗?如果你也是这么想的,恭喜你又错了,你又忽略了一个很简单但很重要的知识点,char类型的范围是-128-----127.



这张图还有印象吗?

signed char类型的数据存储到编译器中,无论多大的数字,编译器都会将该数字转为-128-------127之间的一个数,并不会超出这个范围。因此strlen(a)的值为255.

看到这里你是不是觉得自己这次一定学会啦?

那我再检测一下你是不是真的学会了!!!

#include<stdio.h>
int main()
{
  unsigned char i = 0;
  for (i = 0; i <= 255; i++)
  {
    printf("hello world!");
  }
  printf("%d\n", count);
  return 0;
}

如果你认为输出结果是无限循环,那就证明你大概是学会了,为什么是无限循环呢?还是要用到我们之前学过的无符号和有符号的范围,这里的变量i被定义的是unsigned char,无符号的范围是0-255,而循环的条件即为i<=255,和上文提到的例子相同,unsigned char类型的数据存储到编译器中,无论多大的数字编译器都会将该数字转为0-255之间的一个数,并不会超出这个范围。因此循环的条件永远成立。

注:无符号数经常会导致程序进入死循环,因此在以后编写程序的过程中,无符号数字我们要谨慎使用,以免发生程序死循环现象。

相关文章
|
1月前
|
C语言 C++
C语言 之 内存函数
C语言 之 内存函数
33 3
|
28天前
|
存储 算法 C语言
通义灵码在考研C语言和数据结构中的应用实践 1-5
通义灵码在考研C语言和数据结构中的应用实践,体验通义灵码的强大思路。《趣学C语言和数据结构100例》精选了五个经典问题及其解决方案,包括求最大公约数和最小公倍数、统计字符类型、求特殊数列和、计算阶乘和双阶乘、以及求斐波那契数列的前20项和。通过这些实例,帮助读者掌握C语言的基本语法和常用算法,提升编程能力。
|
7天前
|
开发框架 监控 .NET
【Azure App Service】部署在App Service上的.NET应用内存消耗不能超过2GB的情况分析
x64 dotnet runtime is not installed on the app service by default. Since we had the app service running in x64, it was proxying the request to a 32 bit dotnet process which was throwing an OutOfMemoryException with requests >100MB. It worked on the IaaS servers because we had the x64 runtime install
|
20天前
|
C语言
【c语言】动态内存管理
本文介绍了C语言中的动态内存管理,包括其必要性及相关的四个函数:`malloc`、``calloc``、`realloc`和`free`。`malloc`用于申请内存,`calloc`申请并初始化内存,`realloc`调整内存大小,`free`释放内存。文章还列举了常见的动态内存管理错误,如空指针解引用、越界访问、错误释放等,并提供了示例代码帮助理解。
31 3
|
22天前
|
机器学习/深度学习 算法 物联网
大模型进阶微调篇(一):以定制化3B模型为例,各种微调方法对比-选LoRA还是PPO,所需显存内存资源为多少?
本文介绍了两种大模型微调方法——LoRA(低秩适应)和PPO(近端策略优化)。LoRA通过引入低秩矩阵微调部分权重,适合资源受限环境,具有资源节省和训练速度快的优势,适用于监督学习和简单交互场景。PPO基于策略优化,适合需要用户交互反馈的场景,能够适应复杂反馈并动态调整策略,适用于强化学习和复杂用户交互。文章还对比了两者的资源消耗和适用数据规模,帮助读者根据具体需求选择最合适的微调策略。
|
21天前
|
缓存 监控 Java
在使用 Glide 加载 Gif 动画时避免内存泄漏的方法
【10月更文挑战第20天】在使用 Glide 加载 Gif 动画时,避免内存泄漏是非常重要的。通过及时取消加载请求、正确处理生命周期、使用弱引用、清理缓存和避免重复加载等方法,可以有效地避免内存泄漏问题。同时,定期进行监控和检测,确保应用的性能和稳定性。需要在实际开发中不断积累经验,根据具体情况灵活运用这些方法,以保障应用的良好运行。
|
30天前
|
存储 弹性计算 算法
前端大模型应用笔记(四):如何在资源受限例如1核和1G内存的端侧或ECS上运行一个合适的向量存储库及如何优化
本文探讨了在资源受限的嵌入式设备(如1核处理器和1GB内存)上实现高效向量存储和检索的方法,旨在支持端侧大模型应用。文章分析了Annoy、HNSWLib、NMSLib、FLANN、VP-Trees和Lshbox等向量存储库的特点与适用场景,推荐Annoy作为多数情况下的首选方案,并提出了数据预处理、索引优化、查询优化等策略以提升性能。通过这些方法,即使在资源受限的环境中也能实现高效的向量检索。
|
1月前
|
编解码 Android开发 UED
构建高效Android应用:从内存优化到用户体验
【10月更文挑战第11天】本文探讨了如何通过内存优化和用户体验改进来构建高效的Android应用。介绍了使用弱引用来减少内存占用、懒加载资源以降低启动时内存消耗、利用Kotlin协程进行异步处理以保持UI流畅,以及采用响应式设计适配不同屏幕尺寸等具体技术手段。
49 2
|
1月前
|
编译器 程序员 C语言
深入C语言:动态内存管理魔法
深入C语言:动态内存管理魔法
|
1月前
|
Java 编译器 C语言
【一步一步了解Java系列】:Java中的方法对标C语言中的函数
【一步一步了解Java系列】:Java中的方法对标C语言中的函数
21 3