探索C语言中的运算符

简介: 深入探索C语言中运算符的内容,对各类运算符含义、优先级以及一些易混点做了简单的梳理。还浅谈了关于前置++,后置++,三目运算符等内容,欢迎朋友们来赐教指正。
  • 运算符的种类

C语言的运算符有赋值运算符、逻辑运算符、条件运算符、算数运算符、以及位运算符。关于位运算符的内容有些复杂,我开了个博文单独讨论它

  • 赋值运算符

赋值运算符 的符号是 “=”,在C语言中,它不同于我们数学中的“等于”,“等于”在C语言中使用“==”表示,接下来会提到。赋值运算符的含义是: 将 "=" 右边的数值或者变量甚至地址赋值给 "=" 左边的变量。为了便于下面的理解,在这里,我们介绍两个概念:左值 和 右值

左值,一般认为就是能够表示一块内存的名称或者表达式(如指针表达式);一般的左值的值都是可以修改的,但是c语言中有 const 这个关键字,它声明的左值是常量,其值不可被修改。这就存在了可修改的左值和不可修改的左值。左值可以放在赋值符号左侧,也可以放在赋值符号右侧,但是:只有可修改的左值才能放在赋值符号的左侧!
右值,C Primer Plus上给的解释是:可以赋值给可修改左值的量,但本身不是左值。其实它就是那些本身不表示任何内存的常量或变量或者可以表示求值的表达式甚至函数,它只能放在赋值符号右侧。
我们来举个例子:

int num = 5;
double temp;
double count;
const int price = 200;
temp = 7.5;
count = (num - temp)*3;

上面这段代码中num,temp,count都是可修改的左值,price是不可修改的左值(注意,const int price = 200中的 =初始化,不是赋值符号!),常量 5 , 200 , 7.5 ,以及表达式(num - temp)*5都是右值,它们不表示特定的内存。

  • 算数运算符

算术运算符 顾名思义,就是进行算数运算的运算符,根据算术运算符运算需要的值(或变量)的个数,有以下几类:

一元运算符 ++ 、 --
二元运算符 +、-、*、/、%

一元运算符只能单个值进行运算,而且进行运算的必须是可修改的左值(这就意味这多重自增如++(a++);等不成立)。
二元运算符至少需要两个值。这没什么可说的,我们这里重点讨论递增运算符 “++”。
递增(减)运算符可以放在值的前面和后面,如num++++numnum++++num 的运算结果都是 num + 1; ,但它们内部的运算过程是完全不同的。我们试着运行下面这两段代码:
第一段代码

void main()
{
    int num = 5;
    if(num ++ >= 6)
    {
      printf("num++判断成功");
    }
      printf("num = %d",num);
}

运行结果为:
num = 6

第二段代码

void main()
{
    int num = 5;
    if(++num >= 6)
    {
      printf("++num判断成功\n");
    }
      printf("num = %d",num);
}

运行结果为:

++num判断成功
  num = 6

我们可以看到,只有++num通过了条件判断,而num++则被阻拦在了条件语句之外。但它们最终都实现了num的递增运算。这可以看出++num是先执行自增,再进行判断,而num++是先进行了判断,再执行自增。我们用下面这段代码来探索它内部的运作机制

void main ()
{  int num1 = 5;
     int num2 = 5;   
     num1 = num1 ++;
     num2 = ++num2;
     printf("num1 = %d\n",num1);
     printf("num2 = %d\n",num2);
}

运行结果为

num1 = 5
num2 = 6

为什么会出现这种情况?细心的朋友在编译的时候会发现,编译器在警告我们后置++的num1这个变量未声明(实际上前置++的num2也会报错,似乎是编译器的问题)。事实上,赋值符号左侧的num1已经不是我们之前声明的那个变量了,相当于一个同名的变量占用了原来变量的内存,你完全可以重新定义一个变量来接受自增的结果,会得到同样的值。我们可以这样理解:
num1 ++ 是 先将num1 的值赋值给一个临时变量temp,然后将num1的值加1,如果有后续运算的话,就都使用temp来运算。本例中就是将temp复制给新的num1变量。
实际上,变量的值在运算前是存储在栈中的,前置++是将num变量自增后的num+1直接压入num栈中,而后置++是先将变量num压入num的栈中,然后再将变量自增后的num+1再押入num的栈中,num+1会堆在num的上方,会优先被取出。
更详细的原理可参考某位不知名大佬的博文,原文没找到,只有这篇转载文前置++和后置++ 运算的详解及实例代码

  • 关系运算符

关系运算符有 > 、< 、 <= 、>= 、== 、!=
它可以对两个变量、数值、字符、甚至表达式进行比较,一般在条件语句中,用来作为条件判断。
它的运算结果是一个数字,0表示假,非0表示真。(类似于_Bool类型,不过_Bool类型只能表示1个位(0和1),它会将任何非0的数值自动转成1)。我们尝试思考一下下面这段代码的运行结果:

void main()
 {
  int num = 0;
  if(num = 0)
    {
     printf("武林至尊,宝刀屠龙");    
    }
   else if(num =3)
    {
      printf(“号令天下,莫敢不从”);
    }
   else
    {
       printf("倚天不出,谁与争锋");
    }
   }

运行结果为:

screenshot

if结构是根据条件语句中的运算值来决定是否执行语句块的,如果为0,就表示假,跳过后面的语句块。非0就表示条件语句为真,执行后面的语句块。
但这似乎只在c语言中行得通,java中的boolean类型的值是ture和false,编译器不会通过这种if条件中是数值的语句。

条件运算符的补充 - 三目运算符

运算符的目,是根据参与运算的数的个数来区分的,条件运算符是惟一有3个操作数的运算符。它相当于一个if语句,对条件进行判断,然后给出两种不同情况的值。比如:
num = 5 > 6 ? 20 : 30

这个运算的含义是:先判断5>6是否为真,如果为真,那么结果为20,否则,结果为30;然后将右边的值赋值给左边的num。

但三目运算符更常用于下面这类判断:
printf("%s\n",sex = 0?"女":"男");
值为0,打印“女”,否则打印“男”;可以在统计中使用。

  • 逻辑运算符

运算符 表达式 说明
&&而且 条件1 && 条件2 条件1和条件2同时为真,结果才为真;否则,结果为假
|| 或者 条件1 || 条件2 条件1或条件2为真,结果就为真;否则,结果为假
! 非 ! 条件 条件为真时,结果为假;反之,结果为真

逻辑运算符 || 和 && 来进行多个条件判断,当一个条件难以满足时,就可以使用逻辑运算符,可以避免使用多个if语句来嵌套。某些情况下,问题从正面难以处理时,就可以使用 ! 运算符从问题的反面来考虑。值得注意的时,|| 运算符在前一个条件为真时,就不会执行下一个条件语句。同理,&&运算符在第一个条件为假时也不会继续执行,这就是所谓的短路运算。我们看下面这个例子:

int main()
{
  int num = 5;
  if(num > 4 || ++ num > 3)
  {
  }
  printf("num = %d",num);
}

运行结果为:

num = 5

条件1满足后条件2就会被短路,虽然条件2也满足,但并未执行,所以++num操作没有成功。

  • 运算符的优先级

我们上面讲了常用的四种运算符,那在具体运算中,究竟该先进行哪种运算呢?
单目运算符优先级最高: ! 、~(按位非,位运算符) 、 ++ 、-- 、 sizeof()、当然还有( ),使用括号可以调整运算优先级。

第二序列是 算术运算符 > 条件运算符 > 逻辑运算符。
优先级最低的是 赋值运算符。

目录
相关文章
|
15天前
|
存储 C语言 C++
【c语言】运算符汇总(万字解析)
今天博主跟大家分享了c语言中各种操作符的功能、使用方法以及优先级和结合性,并且与大家深入探讨了表达式求值的两个重要规则--算数转换和整形提升。学习这些知识对我们的C语言和C++学习都有着极大的帮助。
69 2
|
27天前
|
C语言
c语言运算符
C的运算符有以下几种: 算术运算符:+、-、*、/、% 结合方向自左向右 关系运算符:>、<、==、>=、<=、!= 逻辑运算符:!、&&、|| 位运算符<<、>>、~、|、^、& 赋值运算符:=及符号扩展赋值运算符(+=、-=、*=、/=) 条件运算符:? : 逗号运算符:, 指针运算符:*、& 求字节运算符:sizeof 强制类型转换运算符:((类型)) 分量运算符:.、-> 下标运算符:[]
31 4
|
4月前
|
存储 C语言
C语言数据类型、变量和运算符以及printf相关问题
C语言数据类型、变量和运算符以及printf相关问题
|
10天前
|
C语言
【C语言】条件运算符详解 - 《 A ? B : C 》
条件运算符(也称为三元运算符)是C语言中唯一的三元运算符。它通常用于替代简单的 `if-else` 语句。
46 6
|
3月前
|
C语言
C语言判断和运算符联系
在 C 语言中,判断与运算符紧密相关,主要体现在条件表达式的使用上。
197 87
|
3月前
|
安全 C语言
C语言运算符的使用注意点
在C语言中,正确使用运算符能提升代码的可读性和效率。本文介绍了八大注意事项:运算符优先级和结合性影响运算顺序;自增/自减运算符分前缀和后缀形式;逻辑运算符有短路特性;位运算符直接操作二进制位需谨慎;条件运算符简洁但避免复杂嵌套;类型转换避免意外结果;使用括号明确运算顺序。掌握这些要点有助于编写更安全高效的代码。
203 72
|
2月前
|
存储 Java C语言
【一步一步了解Java系列】:了解Java与C语言的运算符的“大同小异”
【一步一步了解Java系列】:了解Java与C语言的运算符的“大同小异”
42 3
|
2月前
|
C语言
C语言条件运算符详解
C语言条件运算符,也称为三元运算符,是一种简化if-else语句的表达式,形式为:条件?表达式1:表达式2。当条件为真时,计算并返回表达式1的值;否则计算并返回表达式2的值。它可用于快速实现简单的条件分支逻辑。
|
3月前
|
安全 C语言
在C语言中,正确使用运算符能提升代码的可读性和效率
在C语言中,运算符的使用需要注意优先级、结合性、自增自减的形式、逻辑运算的短路特性、位运算的类型、条件运算的可读性、类型转换以及使用括号来明确运算顺序。掌握这些注意事项可以帮助编写出更安全和高效的代码。
56 4
|
7月前
|
C语言
C语言中的条件运算符和条件表达式详解
C语言中的条件运算符和条件表达式详解
653 0