C语言操作符详解(下)

简介: 笔记

sizeof 和 数组


14.png

size of是操作符,不是函数,size of()的括号可以去除,但是在使用的时候建议加上()

15.png

#include <stdio.h>
void test1(int arr[])
{
  printf("%d\n", sizeof(arr));//(2)
}
void test2(char ch[])
{
  printf("%d\n", sizeof(ch));//(4)
}
int main()
{
  int arr[10] = { 0 };
  char ch[10] = { 0 };
  printf("%d\n", sizeof(arr));//(1)
  printf("%d\n", sizeof(ch));//(3)
  test1(arr);
  test2(ch);
  return 0;
}

++a与a++

16.png17.png

关系操作符


>

>=

<

<=

!=   用于测试“不相等”

==      用于测试“相等

比较字符串是否相等时不能用==,用strcmp函数,头文件是sting.h


逻辑操作符


&&     逻辑与

||          逻辑或

&& 左边为假,右边就不计算了

|| 左边为真,右边就不计算了

1.png

条件操作符


exp1 ? exp2 : exp3

逗号表达式


逗号表达式,就是用逗号隔开的多个表达式。

逗号表达式,从左向右依次执行。整个表达式的结果是最后一个表达式的结果。

2.png

下标引用、函数调用和结构成员


[ ] 下标引用操作符

操作数:一个数组名 + 一个索引值

3.png

arr[7]=7[arr]=*(arr+7)=*(7+arr) ,但是定义数组的时候不能把arr[10]写作10[arr]。

( ) 函数调用操作符

接受一个或者多个操作数:第一个操作数是函数名,剩余的操作数就是传递给函数的参数。

4.png

访问一个结构的成员

.结构体.成员名

->结构体指针->成员名

#include<stdio.h>
#include <string.h>
struct Stu                    //创建结构体类型
{
  char name[20];
  int age;
  double score;
};
void set_stu(struct Stu* ps)
{
  //strcpy((*ps).name, "zhangsan");
  //(*ps).age = 20;
  //(*ps).score = 100.0;
  strcpy(ps->name, "zhangsan");
  ps->age = 20;
  ps->score = 100.0;
}
void print_stu(struct Stu* ps)
{
  printf("%s %d %lf\n", ps->name, ps->age, ps->score);
}
int main()
{
  struct Stu s = { 0 };
  set_stu(&s);          //进行传参,这里采取了传地址
  print_stu(&s);        //同样进行传地址   
  return 0;
}

访问结构体有俩种形式.和->


表达式求值


表达式求值的顺序一部分是由操作符的优先级和结合性决定。


同样,有些表达式的操作数在求值的过程中可能需要转换为其他类型。


隐式类型转换

C的整型算术运算总是至少以缺省整型类型的精度来进行的。


为了获得这个精度,表达式中的字符和短整型操作数在使用之前被转换为普通整型,这种转换称为整型提升。


整型提升的意义:

表达式的整型运算要在CPU的相应运算器件内执行,CPU内整型运算器(ALU)的操作数的字节长度


一般就是int的字节长度,同时也是CPU的通用寄存器的长度。


因此,即使两个char类型的相加,在CPU执行时实际上也要先转换为CPU内整型操作数的标准长


度。


通用CPU(general-purpose CPU)是难以直接实现两个8比特字节直接相加运算(虽然机器指令


中可能有这种字节相加指令)。所以,表达式中各种长度可能小于int长度的整型值,都必须先转


换为int或unsigned int,然后才能送入CPU去执行运算。

5.png我们可以看到5+126结果为-125,这是因为发生了整形提升

6.png

所以这里可以看到C输出的是负数。这是因为char类型占一个字节8个比特位,而在运算的时候,CPU一般处理int类型,而int类型占四个字节,32个比特位,此时8个比特位显然不够,编译器会自动补充其余24个比特位,补充的内容为符号位,无符号整形高位补0

int main()
{
 char a = 0xb6;
 short b = 0xb600;
 int c = 0xb6000000;
 if(a==0xb6)
 printf("a");
 if(b==0xb600)
 printf("b");
 if(c==0xb6000000)
 printf("c");
 return 0; }

7.png

代码会打印C,这是因为a,b要进行整形提升,但是c不需要整形提升 a,b整形提升之后,变成了负数

8.png

c只要参与表达式运算,就会发生整形提升,表达式 +c ,就会发生提升,所以 sizeof(+c) 是4个字


节.


表达式 -c 也会发生整形提升,所以 sizeof(-c) 是4个字节,但是 sizeof(c) ,就是1个字节


算术转换


如果某个操作符的各个操作数属于不同的类型,那么除非其中一个操作数的转换为另一个操作数的类


型,否则操作就无法进行。下面的层次体系称为寻常算术转换


long double


double


float


unsigned long int


long int


unsigned int


int


优先级自上而下逐渐降低,但存在精度丢失的风险


操作符的属性


复杂表达式的求值有三个影响的因素。


1. 操作符的优先级


2. 操作符的结合性


3. 是否控制求值顺序。


两个相邻的操作符先执行哪个?取决于他们的优先级。如果两者的优先级相同,取决于他们的结合性。


操作符优先级

9.png

#include<stdio.h>
int main()
{
  int a = 1;
  int b = 2;
  int c = 3;
  int d = 4;
  int e = 5;
  int f = 6;
    int h=a * b + c * d + e * f;
    printf("%d", h);
  return 0;
}

这种运算方式,只能保证,*的计算是比+早,但是优先级并不 能决定第三个*比第一个+早执行


c + --c;  


操作符的优先级只能决定自减--的运算在+的运算的前面,但是我们并没有办法得


知,+操作符的左操作数的获取在右操作数之前还是之后求值,所以结果是不可预测的,是有歧义的。(先算--c,然后算加法的时候不能保证C是--c之前的值还是--c之后的值)

#include<stdio.h>
int main()
    {
      int a = 1;
      int b = (++a) + (++a) + (++a);
      printf("%d\n", b);
      return 0; 
        }

不能保证先算哪个括号里面的,还有无法确定先算哪一个+

int main()
{
 int i = 10;
 i = i-- - --i * ( i = -3 ) * i++ + ++i;
 printf("i = %d\n", i);
 return 0; }

编译器会凌乱

int fun()
{
     static int count = 1;
     return ++count; }
int main()
{
     int answer;
     answer = fun() - fun() * fun();
     printf( "%d\n", answer);//输出多少?
     return 0; }

但是上述代码 answer = fun() - fun() * fun(); 中我们只能通过操作符的优先级得知:先算乘法, 再算减法。 函数的调用先后顺序无法通过操作符的优先级确定。


下面代码的结果是:

#include <stdio.h>
int i;
int main()
{
    i--;
    if (i > sizeof(i))
    {
        printf(">\n");
    }
    else
    {
        printf("<\n");
    }
    return 0; 
}

全局变量,静态变量都是放在静态区,不初始化,会默认为0,局部变量不初始化默认值为随机值,局部变量在栈区


i一开始为0,i--为-1,-1>4为假,走else,但这样想是错的,因为sizeof这个操作符计算返回结果是无符号整形,size_t类型,所以这里是int和unsigned int进行比较,int转为unsigned int 此时i为一个非常大的正数,-1原码为10000000000000000000000000000001,补码为11111111111111111111111111111110,由于是无符号整形,所以计算机会把这个数字当正数看待


关于表达式求值说法不正确的是

A.表达式求值先看是否存在整形提升或算术转换,再进行计算


B.表达式真正计算的时候先看相邻操作符的优先级决定先算谁


C.相邻操作符的优先级相同的情况下,看操作符的结合性决定计算顺序


D.只要有了优先级和结合性,表达式就能求出唯一值


A:正确


B:正确


C:正确


D: 错误,有了优先级和结核性,表达式也有可能有不同的计算机路径,导致计算结果的差异。


BC68-X形图案

#include<stdio.h>
int main()
{
    int a;
    int i,j;
    while( scanf("%d",&a)!=EOF)
    {
        getchar();
    for(i=0;i<a;i++)
    {
        for(j=0;j<a;j++)
        {
            if(i==j||i+j==a-1)
                printf("*");
            else
                printf(" ");
        }
        printf("\n");
    }
    }
    return 0;
}
相关文章
|
6天前
|
C语言
C语言之操作符1
C语言之操作符1
22 0
|
6天前
|
编译器 C语言
操作符详解(C语言基础深入解析)
操作符详解(C语言基础深入解析)
|
6天前
|
存储 编译器 C语言
爱上C语言:操作符详解(下)
爱上C语言:操作符详解(下)
|
6天前
|
算法 测试技术 C语言
【C语言】异或(^)操作符
【C语言】异或(^)操作符
18 0
|
6天前
|
存储 算法 编译器
【c 语言 】移位操作符详解
【c 语言 】移位操作符详解
47 0
|
6天前
|
存储 算法 程序员
【c 语言 】位操作符详解
【c 语言 】位操作符详解
61 0
|
6天前
|
存储 编译器 Linux
操作符详解【c语言】
操作符详解【c语言】
|
6天前
|
存储 编译器 程序员
c语言从入门到实战——操作符详解
C语言操作符指的是程序中用来进行各种计算、逻辑和条件操作的符号或符号组合。 操作符是编程中用于执行特定操作或比较数据的符号。它们根据操作类型分为算术、比较、逻辑和位操作符。算术操作符执行加、减、乘、除等数学运算;比较操作符比较两个值的大小或相等性;逻辑操作符连接多个条件,形成更复杂的逻辑判断;位操作符则直接对整数的二进制位进行操作。了解各种操作符的特性和用法,对于编写高效、准确的代码至关重要。
56 0
|
6天前
|
存储 编译器 程序员
C语言第十六弹---操作符(下)
C语言第十六弹---操作符(下)
|
1天前
|
存储 Linux C语言
C语言初阶⑥(操作符详解)编程作业(算数转换)(下)
C语言初阶⑥(操作符详解)编程作业(算数转换)
5 1