一些遗漏和易错的知识点

一些遗漏和易错的知识点

1.每种具体类型的默认值
• 每种具体类型都有不同的默认值;
• 当没有为一个属性变量赋值时,会根据类型为其赋值为默认值;
• 注意: char 的默认值是\u0000,等同于一个空字符; boolean 的默认值是 false
static 静态变量的初始值是JVM默认的初始值,定义一个静态变量的时候都会有一个初始默认值;
类型默认值
byte0
short0
int0
long0
float0.0
double0.0
char“空字符”(\u0000)
booleanfalse
2. 基本数据类型的显式和隐式转换
• 虽然类型之间可以进行强制的隐式转换,但是也需要有一定的前提;
• 数值类型和 boolean 类型之间就不能转换;强制也不可以;
    
 byte b=1;
 boolean b2=false;
// "风马牛不相及"的boolean和数值类型,强制也不能转换;
 b2=b; (编译错误)
 b2=(boolean)b; (编译错误)
3.基本数据类型的赋值和比较运算
• 用“=”可以为任何一种基本数据类型的变量赋值;
• 赋值时主要不要超过表示范围,否则将出现编译错误;
//用=可以直接使用数值赋值为数值型类型赋值,但是不能超出其数据类型的表示范围
byte b1=127;
byte b2=129;//超出byte的表示范围,编译错误(-128~127)char类型使用’’引用单个字符赋值;也可以使用非负整数迚行赋值;
//用''引用单个字符为char赋值,也可以是非负整数
char c1='a';
char c2=12;
char c3='ab';//编译错误
char c4=12.8;//编译错误
char c5=-199;//编译错误
• Java中默认的整数类型是 int ,默认的小数类型是 double ;
• 使用f/F后缀显式表示 float 类型;使用d/D后缀显式使用  double 类型;
//小数默认为double类型;使用f或F后缀可以表示该小数是float型;
float f1=1;
float f2=1.0;//编译错误
float f3=(float)1.0
float f4=1.0f;
//小数默认为double类型;使用d或D后缀可以显式表示该小数是double型;
double d1=1.0;
double d2=1.0d;
可以使用==、!=><>=<=对基本数据类型的数值迚行比较运算;比较的是其二进制的值;
4. 引用类型的赋值和比较运算
• 在Java语言言中,除了上节学习到的 8种基本数据类型,其他类型都是引用类型;
• 也可以说,任何一个对象都是引用类型;
• 引用类型使用=赋值;
• 除了 String 、包装器类(共8个)外,都需要使用 new 关键字;
• 引用类型可以使用==、!=进行比较,比较的是引用类型的地址,不是内容;(之前关于string的一个问题有说明)
• 引用类型不能使用>>=<=<进行比较;
• 当只声明了一个引用类型变量,却没有为其赋值,则此时该变量为null;
5. Java中字符串final特性
• 这个类型在实际编程中使用非常非常非常多;
• 这个类使用了 final 修饰,意思是不能被扩展,不能被修改;
6.字符串常量池
• 字符串可以用两种方式赋值有一个非常重要的特征,即不可变性(immutable);
• 不可变的意思是:一旦一个字符串被创建后,它的值就不能被修改;
String s1="Hello";
s1="World";
并不是把Hello改为了World,而是重新分配空间存储World;
s1的值发生了改变,指向了新的空间;

在这里插入图片描述

• 为了能够重用这些不变的字符串,Java使用了字符串常量池;
• 凡是用=直接赋值的方式得到的字符串,都存储在常量池中;相同的共用一个具体字符串;
• 使用new创建的字符串不适用常量池,每次都分配新的内存空间;(这个很重要)
String s2="Hello";
String s3="Hello";
String s4=new String("Hello");
String s5=new String("Hello");

在这里插入图片描述

• s1不s2使用=赋值,所以使用到常量池,指向同一个Hello;
• s3不s4使用new创建,没有用常量池,每次都分配新的空间,指向一个新的Hello;

• 输出结果如下,能验证论:
System.out.println("s2==s3"+(s2==s3));
System.out.println("s4==s5"+(s4==s5));
System.out.println("s2==s4"+(s2==s4));
s2==s3 true
s4==s5 false
s2==s4 false 
7. String、StringBuffer、StringBuilder的区别
• Java语言中的有一个 StringBuffer 类,称为字符串缓冲区;所表示的也是一个字符序列;
• 这个类型必须用new创建对象,和 String 相反,它是可变的类;
    
StringBuffer sbf1=new StringBuffer ("Etc");
StringBuffer sbf2=new StringBuffer (" Java");
sbf1.append(sbf2);
System.out.println(sbf1);//Etc Java
• 证明: StringBuffer 是一个可变的字符串类;
• Java语言言中的还有一个 StringBuilder 类,与StringBuffer 兼容,但是不保证线程同步;
8.关于float和double的精度问题
:为什么下面两种情况下输出的结果不一样?
double d3=0.3d;
float d4=0.3f;
System.out.println("d3==d4 "+(d3==d4));//fals

double d3 = 0.5d;//0.25 0.5 0.0625 这样的值
float d4 = 0.5f; //0.25 0.5 0.0625这样的值
System.out.println("d3==d4 " + (d3 == d4));//true
• 这题其实和二进制有关,我们要先知道十进制的小数怎么转换成二进制;
• 十进制的小数转换为二进制,主要是小数部分乘以 2,取整数部分依次从左往右放在小数点后,直至小数点后为0(乘二取整法)。例如十进制的0.125,要转换为二进制的小数:

    0.125*2=0.250
    0.25*2=0.50
    0.5*2=1.01
    即为二进制为 0.001

• 这边再顺便说下二进制的小数转换为十进制:
	二进制的小数转换为十进制主要是乘以 2 的负次方,从小数点后开始,依次乘以2的负一次方,2的负二次方,2的负三次方等。例如二进制数0.001转换为十进制;
	一个有限位数的整数一定能转换成有限位数的二进制。但是小数部分就不一定了,一个有限位数的小数并不一定能转换成有限位数的二进制,只有末位是 5 的小数才有可能转换成有限位数的二进制,其它的小数都不行。这边又要提到精度问题;

floatdouble 的尾数部分是有限的,固然不能容纳无限的二进制;即使小数能够转换成有限的二进制,也有可能会超出尾数部分的长度,此时也不能容纳。这样就必须“四舍五入”,将多余的二进制“处理掉”,只保留有效长度的二进制,这就涉及到了精度的问题。也就是说,浮点数不一定能保存真实的小数,很有可能保存的是一个近似值。
    
floatdouble 的范围是由指数的位数来决定的; 
float 的指数位有8位,而 double 的指数位有 11位,分布如下: 
1bit(符号位) 
8bits(指数位) 
23bits(尾数位) 

double: 
1bit(符号位)
11bits(指数位) 
52bits(尾数位) 

计算机相关的数字(浮点数)问题的表述中,有一个基本表达法:

 (浮点)数值 = 尾数 × 底数 ^ 指数  (附加正负号)

指数部分是有符号的,占一个字节,那么按照补码的表示规则,自然就是-128127。于是,float的范围为-2^128 ~ +2^128,也即-3.40E+38 ~ +3.40E+38double的范围为-2^1024 ~ +2^1024,也即-1.79E+308 ~ +1.79E+308
floatdouble 的精度是由尾数的位数来决定的;

对于 float,尾数部分有 23 位,再加上一个隐含的整数 1,一共是 24 位。最后一位可能是精确数字,也可能是近似数字(由四舍五入、向零舍入等不同方式得到);除此以外,剩余的23位都是精确数字。从二进制的角度看,这种浮点格式的小数,最多有 24 位有效数字,但是能保证的是 23 位;也就是说,整体的精度为 23~24 位。如果转换成十进制,224 = 16777216,一共8位;也就是说,最多有 8 位有效数字,但是能保证的是 7 位,从而得出整体精度为 7~8 位。
    
对于 double,同理可得,二进制形式的精度为 52~53 位,十进制形式的精度为 15~16 位。
回到这题上:
0.5的二进制刚好是0.1 ,小数点就一位,所以 floatdouble 的精度就没有差别了;
0.3的二进制有 53, float 的精度只有 24,所以25后的都会被省略掉,所以0.3的为false;
<think>嗯,用户想要一份详细的C语言知识点总结,列出30个重要的点。首先,我得回忆一下C语言的核心内容。C语言的基础包括数据类型、运算符、控制结构这些基本概念。然后是指针、数组、字符串处理,这些都是重点也是难点。接下来是函数、结构体、联合体,内存管理相关的malloc和free,文件操作也不能少。还有预处理器、位运算、动态内存分配,这些可能用户容易忽略但同样重要。 用户提到参考了引用[1]里的内容,里面解释了指针数组、数组指针这些概念,用语文的方式来理解。所以我要确保在总结这些知识点时,用简单易懂的语言,比如“指针数组是数组,元素是指针”,这样用户更容易理解。可能需要把指针相关的知识点详细分点,比如指针基础、指针运算、指针与数组的关系,以及函数指针和指针函数的不同。 然后考虑用户可能的水平,如果是初学者,可能需要更基础的知识点,比如变量声明、作用域、static关键字等。而如果是准备考试,可能需要重点强调易点,比如类型转换、运算符优先级、递归函数的使用注意事项。另外,像内存对齐、结构体位域这些进阶内容也不能遗漏。 需要检查是否有重复的知识点,比如指针和数组的关系可能会在不同的点中提到,要确保每个知识点独立且明确。例如,把数组和指针的区别单独作为一点,而指针运算作为另一点。同时,动态内存分配要涵盖malloc、calloc、realloc和free的使用,以及内存泄漏的问题。 可能还需要包含一些标准库函数,比如stdio.h中的输入输出函数,string.h的字符串处理函数,stdlib.h的内存管理和转换函数。另外,预处理指令如#define、#include、条件编译也是必须的。 考虑到用户要求30个点,我需要逐一列出,确保覆盖全面。从基础到进阶,每个知识点简明扼要,但足够详细。例如,结构体和联合体的区别,枚举类型的使用场景,typedef的作用,这些都需要单独列出。 还要注意格式问题,按照用户的要求,行内数学公式用$...$,独立公式用$$...$$。不过C语言知识点可能涉及代码示例,所以需要用代码块包裹,比如指针的示例代码。同时,每个知识点可能需要举例说明,比如结构体的定义和使用。 最后,生成的相关问题需要与C语言相关,可能涉及学习资源、调试技巧、内存管理常见误、指针应用等,帮助用户进一步深入学习。需要确保问题有针对性,能够引导用户探索更多内容。 总结下来,我需要组织30知识点,每个点简洁明了,涵盖语法、概念、应用和常见问题,同时引用参考中的指针相关解释,确保内容准确且易于理解。</think>### C语言30个重要知识点总结 1. **数据类型分类** 基本类型:$int$、$float$、$double$、$char$ 派生类型:数组、指针、结构体、联合体 空类型:$void$ 2. **指针与地址** 指针变量存储内存地址,声明方式:$int *p$[^1] 示例:`int a=5; int *p=&a;`,`*p`访问a的值 3. **数组与指针关系** 数组名是首元素地址,`arr[i]`等价于`*(arr+i)` 区别:数组大小固定,指针可重新赋值 4. **指针运算** 支持加减整数运算(按数据类型步长移动),例如:`p++`移动$sizeof(int)$字节 5. **动态内存分配** `malloc`分配未初始化内存,`calloc`初始化为0,`realloc`调整大小,`free`释放内存 示例:`int *arr = (int*)malloc(10*sizeof(int));` 6. **函数指针** 指向函数的指针,声明:`int (*func)(int, int)` 应用:回调函数、策略模式实现 7. **结构体与联合体** 结构体各成员独立内存,联合体共享内存 示例: ```c struct Student { char name[20]; int age; }; union Data { int i; float f; }; ``` 8. **预处理器指令** `#define`定义宏,`#include`包含头文件,`#ifdef`条件编译 示例:`#define PI 3.1415926` 9. **位运算** 按位与(&)、或(|)、异或(^)、左移(<<)、右移(>>) 应用:权限控制、数据压缩 10. **文件操作** `FILE *fp = fopen("file.txt", "r");` `fprintf`/`fscanf`格式化读写,`fclose`关闭文件 11. **作用域规则** 局部变量(函数内)、全局变量(文件内)、静态变量(`static`修饰) 12. **递归函数** 函数调用自身,需设置终止条件 示例:阶乘计算 ```c int factorial(int n) { if(n <= 1) return 1; return n * factorial(n-1); } ``` 13. **类型转换** 隐式转换(如$int$转$float$),显式强制转换:`(float)num` 14. **运算符优先级** 最高:`[]`、`()`、`.`、`->`,最低:逗号运算符 15. **字符串处理** `strcpy`复制,`strcat`拼接,`strlen`长度,`strcmp`比较 16. **内存对齐** 结构体成员按最大类型对齐,可用`#pragma pack`修改对齐方式 17. **可变参数函数** `stdarg.h`中的宏`va_start`、`va_arg`、`va_end` 示例:实现自定义`printf` 18. **头文件作用** 声明函数原型、宏定义、类型定义,避免重复包含使用`#ifndef` 19. **指针数组与数组指针** - 指针数组:`int *arr[10]`(数组元素是指针) - 数组指针:`int (*arr)[10]`(指向数组的指针) 20. **typedef用法** 为类型定义别名,示例:`typedef unsigned int UINT32;` 21. **枚举类型** 定义命名常量集合: ```c enum Color { RED, GREEN=5, BLUE }; ``` 22. **const关键字** `const int *p`(指针指向常量),`int* const p`(常量指针) 23. **volatile关键字** 告知编译器变量可能被外部修改,禁止优化 24. **结构体位域** 节省内存空间,定义位级字段: ```c struct { unsigned int flag : 1; } status; ``` 25. **命令行参数** `int main(int argc, char *argv[])`,`argv[0]`为程序名 26. **多文件编程** 使用头文件声明接口,`.c`文件实现具体功能 27. **内存泄漏检测** 通过工具(如Valgrind)或手动记录`malloc`/`free`调用 28. **回调函数** 通过函数指针将函数作为参数传递 29. **联合体应用场景** 网络协议解析、类型转换(如浮点转字节) 30. **静态库与动态库** `.a`静态库编译时链接,`.so`动态库运行时加载
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值