
❄专栏传送门:《C语言》、《数据结构与算法》、C语言刷题12天IO强训、LeetCode代码强化刷题
🍉学习方向:C/C++方向
⭐️人生格言:为天地立心,为生民立命,为往圣继绝学,为万世开太平

**前言:**我们在学习过程中会碰到很多很多问题,本系列文章不会博主不会额外再创建一个新的专栏来收录,因为这一系列文章创作的初心主要是针对回顾知识点(遵循遗忘曲线并且根据自身的实际情况可以做出一些计划,回顾知识点很重要)、缓解学习过程中的可能出现的焦虑等等。主包就不另外开一个专栏了,uu们可以把本系列的文章作为【C语言】专栏的后日谈来看。
主包学习能力比较一般,学起语言、算法无论是花费的时间精力还是取得的成效和大佬们完全无法比。主包起步也比较晚,主包正儿八经开始学C++是从今年的4月24号开始的,主包学习能力真的很一般,C语言这个基础也不扎实,看主包文章的诸位一定是比主包要强的,但主包学习过程中碰到的麻烦、思考、和做的知识点回顾对大家还是有用的。
目录
[(1)逻辑反操作 !](#(1)逻辑反操作 !)
[(2)负值 - 和正值 +](#(2)负值 - 和正值 +)
[(3)取地址 &](#(3)取地址 &)
[(4)类型长度 sizeof](#(4)类型长度 sizeof)
[(5)按位取反 ~](#(5)按位取反 ~)
[(6)自增 ++ 和自减 --](#(6)自增 ++ 和自减 --)
[(7)解引用操作符 *](#(7)解引用操作符 *)
正文
三、知识点回顾
(八)操作符(运算符)
3、单目操作符
单目操作符:++、- -、+(正)、-(负)。

前置和后置------
cpp
int a = 10;
int b = a--;//后置--,先使用再-1,b=10,a=9
int b = --a;//前置--,先-1再使用,b=9,a=9
int b = a++;//后置++,先使用,后+1,b=10,a=11
int b = ++a;//前置++,先+1,再使用,b=11,a=11
单目操作符的使用和示例
单目操作符是指仅需要一个操作数的操作符。在C语言中,单目操作符包括逻辑反操作
!
、负值-
、正值+
、取地址&
、类型长度sizeof
、按位取反~
、自增++
和自减--
操作符等。这些操作符通常用于对单一操作数进行特定的操作。
大家来看一个综合实例:
cpp
#include <stdio.h>
int main()
{
int a = 5;
int b = -a; // 使用负号操作符
printf("b = %d\n", b); // 输出: b = -5
int count = 0;
printf("count++ = %d\n", count++); // 输出0,然后count变为1
printf("++count = %d\n", ++count); // count先变为2,然后输出2
int flag = 0;
if (!flag)
{
printf("flag is false\n");
}
return 0;
}
(1)逻辑反操作 !
逻辑反操作符 !
用于将一个布尔值取反。如果操作数为真(非零),则结果为假(0);如果操作数为假(0),则结果为真(1)。常用于条件语句中,例如**if(!a)**表示当 a 为假时执行某段代码。
cpp
int a = 5;
int result = !a; // result 的值为 0
(2)负值 - 和正值 +
负值操作符 - 用于将操作数的符号取反,而正值操作符 + 则保持操作数的符号不变。例如:
cpp
int a = 5;
int b = -a; // b 的值为 -5
int c = +a; // c 的值为 5
(3)取地址 &
取地址操作符 & 用于获取变量的内存地址。例如:
cpp
int a = 10;
int *ptr = &a; // ptr 指向 a 的内存地址
我们和解引用操作符结合一下举个例子(见下文)。
(4)类型长度 sizeof
**sizeof
**操作符用于获取数据类型或变量所占用的内存大小(以字节为单位)。例如:
cpp
int a;
size_t size = sizeof(a); // 获取 int 类型的大小
(5)按位取反 ~
按位取反操作符 ~ 用于将操作数的每一位取反。例如看这两个例子:
cpp
int a = 5; // 二进制表示为 00000101
int b = ~a; // b 的值为 -6(二进制表示为 11111010)
cpp
unsigned char num = 0b00001111; // 15
unsigned char result = ~num; // 0b11110000 → 240
(6)自增 ++ 和自减 --
自增操作符 ++ 用于将操作数的值增加1,而自减操作符 -- 用于将操作数的值减少1。这些操作符可以是前置或后置的。例如:
cpp
int a = 5;
int b = ++a; // 前置自增,a 的值变为 6,b 的值为 6
int c = a--; // 后置自减,c 的值为 6,a 的值变为 5
(7)解引用操作符 *
解引用操作符 * 用于访问指针所指向的内存地址中的值。例如:
cpp
int a = 10;
int *ptr = &a;
int b = *ptr; // b 的值为 10
我们和取地址结合一下举个例子:
cpp
int var = 42;
int *ptr = &var; // ptr保存var的内存地址
int val = *ptr; // val = 42(通过地址取值)
(8)强制类型转换(类型)
强制类型转换操作符(类型)用于将操作数转换为指定的数据类型。例如:
cpp
double a = 3.14;
int b = (int)a; // 将 double 类型转换为 int 类型,b 的值为 3
应用场景示例
cpp
#include <stdio.h>
int main()
{
int counter = 0;
// 循环计数(后置自增)
while (counter < 5)
{
printf("%d ", counter++); // 输出: 0 1 2 3 4
}
// 指针遍历数组
int arr[] = {10, 20, 30};
int *p = arr;
printf("\n%d", *p++); // 输出10(先取*p,再p++)
printf("\n%d", *(p)); // 输出20
}
提示:单目操作符在循环控制、指针操作、状态翻转等场景高频使用,但需严格遵循操作数单一性原则
总结------关键注意事项
单目操作符是只需要一个操作数就能完成运算的操作符。在编程语言中,常见的单目操作符包括**正号(+)、负号(-)、逻辑非(!)、按位取反(~)、自增(++)、自减(--)、取地址(&)、取值(*)、类型转换(如(int))**等。例如,在C语言中:
cpp
int a = 10;
int b = -a; // 使用负号单目操作符,b的值为-10
int c = !a; // 使用逻辑非单目操作符,c的值为0(因为a非0,逻辑非后为假)
int d = ~a; // 使用按位取反单目操作符,d的值为~10(二进制按位取反后的值)
展示一些主要的单目操作符------
cpp
#include <stdio.h>
int main()
{
int a = 10;
int *p = &a; // 使用 & 获取 a 的地址
printf("The value of a is: %d\n", a);
printf("The address of a is: %p\n", (void*)&a); // 打印 a 的地址
printf("The size of int is: %lu bytes\n", sizeof(int)); // 显示 int 类型的大小
printf("The bitwise NOT of a is: %d\n", ~a); // 对 a 进行按位取反
printf("The logical NOT of a is: %d\n", !a); // 对 a 进行逻辑非操作
return 0;
}
关键注意事项:
(1)副作用控制
自增/自减会改变操作数本身,需警惕在复杂表达式中的副作用:
cpp
int i = 1;
int j = (i++) + (++i); // 未定义行为!结果不可预测[^3]
推荐拆分为独立语句:
cpp
i++; // i=2
j = i++; // j=2, i=3
(2)操作符优先级
单目操作符优先级通常高于算术操作符:
cpp
int k = 10;
int m = -k * 2; // 等价于 (-k)*2 = -20
(3)类型一致性
自增/自减要求操作数为左值(如变量):
cpp
int *arr = malloc(10 * sizeof(int));
arr++; // 合法:移动指针
// 5++; // 非法!常量不是左值
4、强制类型转换
在编程中,强制类型转换(Explicit Type Conversion)是指程序员显式地将一种数据类型转换为另一种数据类型。这种转换通常用于表达式的值需要与变量的类型匹配的情况。以下是关于如何进行强制类型转换、常见问题及解决方法的详细说明。
cpp
#include<stdio.h>
int main()
{
int a = (int)3.14;
printf("%d\n", a);
return 0;
}
这里我们把double类型的3.14强转成int:
3.14 --> 3
强制类型转换,即取浮点型的整数部分。
强制类型转换一般不要使用,所谓**"强扭的瓜不甜"**,我们不到万不得已不建议使用。
C语言的强制类型转换给大家推荐几篇文章:
猿享天开大佬的学懂C语言(三十一):C语言 强制类型转换
怀中猫ᝰ大佬的孤篇压全唐:C语言强制类型转换
C强制类型转换总结写的比较详实,可以借鉴一下。
还有总结了C语言和C++的强转的强制转换。
强制类型转换的基本语法:
在 C/C++ 中,强制类型转换使用类型转换运算符(type)来完成。其基本形式如下:
cpp
(type) expression;
例如,像上面那样把3.14强转成3就是将一个int 类型的值转换为double类型:
cpp
int sum = 17, count = 5;
double mean = (double) sum / count; // 将 sum 转换为 double 类型再进行除法运算[^2]
强制类型转换的常见问题及解决方法:
(1)整数除法导致精度丢失
当两个整数相除时,结果会被截断为整数部分,这可能导致精度丢失。例如:
cpp
int sum = 17, count = 5;
double mean = sum / count; // 结果为 3.0,而不是期望的 3.4
解决方法:在进行除法之前,将其中一个操作数强制转换为浮点类型:
cpp
double mean = (double) sum / count; // 正确的结果是 3.4[^2]
(2)指针类型转换带来的地址计算错误
在处理指针时,强制类型转换可能会导致地址计算错误。例如,&a+1和a+1的行为不同,前者是基于指针类型的加法,而后者是普通的数值加法。
cpp
int a = 0x001bfc18;
int *p = &a;
printf("%p\n", p + 1); // 输出 0x001bfc1c(假设 int 占 4 字节)
printf("%p\n", &a + 1); // 输出 0x001bfc28[^3]
解决方法:理解指针算术和普通数值算术的区别,避免对指针进行不恰当的类型转换。如果需要进行地址偏移,可以先将指针转换为char*类型,再进行偏移:
cpp
char *cp = (char *)&a;
cp += 1;
int *ip = (int *)cp;
(3)结构体或数组的强制类型转换导致未定义行为
当对结构体或数组进行强制类型转换时,如果目标类型与原始类型不兼容,可能会导致未定义行为。例如:
cpp
int a[10];
int *p = (int *)((char *)a + 1); // 将 a 的地址加上 1 后转换为 int*
此时,p指向的地址可能不是int类型的对齐地址,导致访问时出现未定义行为。
解决方法:确保转换后的指针指向的地址是对齐的。可以使用memcpy或者通过联合体(union)来安全地进行类型转换。
(4)浮点数到整数的转换导致截断
将浮点数转换为整数时,默认情况下会丢弃小数部分,只保留整数部分。例如:
cpp
double d = 3.9;
int i = (int)d; // i 的值为 3
解决方法:如果希望进行四舍五入,可以使用标准库函数如 round():
cpp
#include <math.h>
int i = (int)round(d); // i 的值为 4
(5)类型不匹配导致编译器警告或错误
在某些情况下,强制类型转换可能导致编译器发出警告或错误,尤其是在不同大小的指针类型之间转换时。
解决方法 :使用更明确的类型转换方式,或者考虑重构代码以避免不必要的类型转换。例如,在 C++ 中可以使用**static_cast、``reinterpret_cast
**等更安全的转换方式。
以上这五点就是强制类型转换的常见问题及其解决方法了。
结尾
只要是主动学习,只要你有兴趣,只要你喜欢学,到处是时间。
往期回顾:
【计算机语言选择规划】全是干货!从难度、就业、岗位选择、薪酬待遇、未来发展等方面详解第一门主流语言学习的选择
**结语:**本篇文章内容回顾到这里就结束了,希望对大家伙有所帮助。如果大家觉得文章有帮助的话,记得一键四连------点赞、收藏、关注、评论!谢谢uu们的支持!