C语言笔记2:C语言数据类型和变量

文章目录

C语言笔记2:C语言数据类型和变量

一、数据类型介绍

C语言提供了不同的数据类型,编译器根据数据类型的不同,对一块数据进行不同的操作,比方说:对一个浮点数类型的数据进行加法运算和对一个整数类型的数据进行加法运算,其运算过程是肯定不一样的。

但是在我看来,其实内置类型只有整型和浮点类型两大类,字符型和布尔类型只不过是特殊的整型而已

1.字符型

c 复制代码
//[]表示可写可不写
[signed] char   //有符号的
 
unsigned char   //⽆符号的
 

char和int等整型不同,char是否能表示负数是未定义的,这是由编译器决定。而int默认就是signed int。

2.整型

c 复制代码
//短整型
[signed] short [int]
unsigned short [int]   
    
//整型    
[signed] int
unsigned int
    
//长整型
[signed] long [int]
unsigned long [int]
    
//更长的整型
[signed] long long [int]
unsigned long long [int]

为什么要有 long long 呢? 长整型和更长的整型区别在哪?

这其实和C语言标准制定有关

C语言标准:
类型 最小范围 对应位数
char -127到127 8位
short -32767到32767 16位
int -32767到32767 16位
long -2147483647到2147483647 32位
long long -9223372036854775807到9223372036854775807 64位

为什么是-127而不是-128呢?这是因为这是最小范围 ,早期有些机器使用原码或者反码来表示整数,这也就意味着需要有**+0,-0**。而现在大多数机器都是使用补码,所以现在实际范围大概率会是**-128到127**。
为什么C语言标准要规定最小范围,而不是直接定死一个固定的大小呢?设想一个场景,假设你的机器是16位的处理字长,此时int被编译器编译成最符合你机器的大小也就是16位,几年后,32位的机器出现了,你想把你写好的代码全部放在32位的机器上跑,可是32位机器上处理整型最快的大小应该是32位,所以为了提高程序运行速度,32位机器上的编译器把你的int数据定义成了32位也就是4个字节大小。这样,你的程序就完成了跨平台,并且在新平台上也能充分发挥新硬件的优势。
long long 的出现就是为了解决C语言long类型在某些平台上不够用的问题,由于long在windows操作系统上是4个字节大小,这导致了一些数据无法存储,但是又不能直接把long的大小改成8个字节,因为这会让编译器无法编译之前的代码,有些老程序不会轻易修改,但是新增某些模块还是需要的,所以干脆就定了一个新的数据类型long long 来解决问题。

3.浮点型

c 复制代码
float 
double
long double
    
    
float c = 0.0f;//f表示0.0是个float类型,0.0表示double类型,0.0L表示long double类型

4.布尔类型

C99才引入,包含头文件<stdbool.h>

5.各种数据类型的长度

sizeof操作符的返回值C语言标准没有规定,可能会返回unsigned intunsigned longunsigned long long,是的,这又带来了可移植性问题,为了解决标准不严格规定的问题,C语言又提供了一个别名size_t 类型,size_t 实际类型因系统而异,但是却保证了程序在系统A上能跑,在系统B上也不会报警告。

测试不同数据类型的大小(windows ,VS2022,x64):

c 复制代码
#include <stdio.h>
#include <stdbool.h>

int main()
{
	printf("%zd\n", sizeof(char));
	printf("%zd\n", sizeof(bool));
	printf("%zd\n", sizeof(short));
	printf("%zd\n", sizeof(int));
	printf("%zd\n", sizeof(long));
	printf("%zd\n", sizeof(long long));
	printf("%zd\n", sizeof(float));
	printf("%zd\n", sizeof(double));
	printf("%zd\n", sizeof(long double));

	return 0;
}

结果:

sizeof中的表达式不计算

c 复制代码
#include <stdio.h>

int main()
{
	short s = 2;
	int a = 3;
	printf("%zd\n",sizeof(s = a + 1));
	printf("%hd",s);
	return 0;
}

结果:

二、数据类型的取值范围

limits.h:这个头文件说明了整型类型的取值范围

float.h:这个头文件说明了浮点类型的取值范围

三、变量

c 复制代码
int age = 18;
char ch = 'w';
double weight = 48.0;
unsigned int height = 100;

在创建变量的时候赋值,叫做初始化,总是初始化变量是一个好的习惯,这会避免很多意想不到的错误

四、全局变量和局部变量

  • 全局变量:定义在大括号外
  • 局部变量:定义在大括号内

全局变量和局部变量命名冲突:

c 复制代码
#include <stdio.h>
int n = 5;

int main()
{
	int n = 10;
	printf("%d\n",n);
	return 0;
}

结果:

说明:局部变量和全局变量冲突时,优先使用局部变量
变量的存储位置

五、算术操作符

+、-、*这些运算符没什么好介绍的。

除法

除法:/

规则1:整数相除只会得到整数,并且向0截断,丢弃小数部分。

c 复制代码
#include <stdio.h>

int main()
{
	float x = 6/4;
	int y = 6/4;
	printf("x=%f,y=%d\n",x,y);
	return 0;
}

结果:

规则2:两个运算数中只要有一个是浮点数,那么结果也是浮点数

c 复制代码
#include <stdio.h>

int main()
{
	float x = 6.0/4;
	printf("%f\n",x);
	return 0;
}

结果:

模运算

规则1:取模运算只能用于整数

规则2:取模运算结果的正负性由第一个运算数的正负号决定

c 复制代码
#include <stdio.h>

int main()
{
	printf("%d\n",6%4);		//+
	printf("%d\n",-6%4);	//-
	printf("%d\n",6%-4);	//+
	printf("%d\n",-6%-4);	//-
	return 0;
}

结果:

六、++ 和 - -

前置++:先++,再使用

c 复制代码
#include <stdio.h>

int main()
{
	int a = 1;
	printf("%d\n",++a);
	printf("%d\n",a);
	return 0;
}

结果:


后置++:先使用,再++

c 复制代码
#include <stdio.h>

int main()
{
	int a = 1;
	printf("%d\n",a++);
	printf("%d\n",a);
	return 0;
}

结果:

七、scanf 和 printf

常见占位符列举:

字符:
  • %c:字符 //char
整型:
  • %d:整型//int
  • %hd:短整型//short [int]
  • %ld:长整型//long [int]
  • %lld:长长整型//long long [int]
  • %u:无符号整型//unsigned int
  • %hu:无符号短整型//unsigned short [int]
  • %lu:无符号长整型//unsigned long [int]
  • %llu:无符号长长整型//unsigned long long [int]
小数:
  • %f:小数//float
  • %lf:小数//double
  • %Lf:long double类型浮点数
特殊:
  • %p:指针
  • %s:字符串
  • %x:十六进制整型
  • %o:八进制整型
  • %zd:size_t类型

定制格式

设置宽度

整型:

c 复制代码
#include <stdio.h>

int main()
{
	printf("%5d,%5d\n",123,45);
	return 0;
}

结果:

浮点型:

c 复制代码
#include <stdio.h>

int main()
{
	printf("%12f",123.45);
	return 0;
}

结果:

设置对齐
c 复制代码
#include <stdio.h>

int main()
{
	printf("%-5d,%-5d\n",123,45);
	return 0;
}

结果:

设置填充
c 复制代码
#include <stdio.h>

int main()
{
	printf("%05d,%05d\n",123,45);
	return 0;
}

结果:

填充和设置左对齐没办法一起用,因为左对齐了之后,后面填充0岂不是平白增加位数。简记:开头可加0或-

设置正号显示
c 复制代码
#include <stdio.h>

int main()
{
	printf("%+d\n",10);
	return 0;
}

结果:显示+10

设置小数位数
c 复制代码
#include <stdio.h>

int main()
{
	printf("%012.2f",123.45);
	return 0;
}

.为分界线,左边是宽度,后边是小数位数。

结果:

占位符参数
c 复制代码
#include <stdio.h>

int main()
{
	printf("%0*.*f",12,2,123.45);
	return 0;
}

*表示要传递参数。

结果:

指定输出的字符串长度
c 复制代码
#include <stdio.h>

int main()
{
	char word[128] = "hello world";
	printf("%.5s\n",word);
	
	return 0;
}

结果:

不管传入多大的字符串,我最多只输出5个。

scanf

基本用法:
c 复制代码
#include <stdio.h>

int main()
{
	int i = 0;
	int j = 0;
	float k = 0.0f;
	long double n = 0.0L;
	
	scanf("%d%d%f%Lf",&i,&j,&k,&n);
	
	printf("%d,%d,%f,%.7Lf\n",i,j,k,n);
	
	return 0;
}

结果:

其实scanf的工作就是检查用户输入的字符串,提取其中内容填充到占位符中,比如用户输入" 1 2###3.14???6.666",从前向后要填充到%d,%d,%f,%.7Lf,中去,它会先扫描跳过前面的空白字符,然后读取1,然后读到空格,发现空格不属于整型类型的字符,于是第一个占位符就被填好了,依次类推。

scanf的返回值
c 复制代码
#include <stdio.h>

int main()
{
	int a = 0;
	int b = 0;
	float c = 0.0f;//f表示0.0是个float类型,0.0表示double类型,0.0L表示long double类型
	int r = scanf("%d %d %f",&a,&b,&c);
	printf("a=%d,b=%d,c=%f\n,r=%d\n",a,b,c,r);
	
	return 0;
}

结果1(只输入两个数据就退出):

结果2(什么都不输入直接退出):

结果3(输入了一堆无关紧要的值):

说明:scanf返回成功读取到的数据

返回-1(EOF)的情况:

  • 什么都没读取到就退出
  • 读到文件末尾

返回0的情况:

  • 没有数据匹配得上,尽管读取到了数据,但是写不进占位符里
相关推荐
何中应9 小时前
@Autowrited和@Resource注解的区别及使用场景
java·开发语言·spring boot·后端·spring
源代码•宸9 小时前
Golang语法进阶(Context)
开发语言·后端·算法·golang·context·withvalue·withcancel
一条咸鱼_SaltyFish9 小时前
[Day16] Bug 排查记录:若依框架二次开发中的经验与教训 contract-security-ruoyi
java·开发语言·经验分享·微服务·架构·bug·开源软件
源代码•宸9 小时前
Golang语法进阶(Sync、Select)
开发语言·经验分享·后端·算法·golang·select·pool
一勺菠萝丶9 小时前
Java 对接 PLC 实战:西门子 PLC 与永宏 PLC 通讯方式全面对比
java·开发语言·python
吴声子夜歌9 小时前
Java数据结构与算法——数论问题
java·开发语言
Miketutu9 小时前
Flutter - 布局
开发语言·javascript·ecmascript
栈与堆9 小时前
数据结构篇(1) - 5000字细嗦什么是数组!!!
java·开发语言·数据结构·python·算法·leetcode·柔性数组
yuanmenghao9 小时前
自动驾驶中间件iceoryx - 同步与通知机制(一)
开发语言·网络·驱动开发·中间件·自动驾驶