c基础03-运算符,变量与常量,赋值

一.运算符

🔔计算机存储数据的二进制补码形式

正数:原码 == 反码 == 补码
负数:补码 == 反码 + 1
        反码 == 原码符号位不变,其余位取反
        - 18 == 1 001 0010
         反码: 1 110 1101
        补码:1 110 1110
补码 -> 原码:
        1. 原码符号位不变,其余位取反再 + 1
        2. - 1 再原码符号位不变,其余位取反

1.位运算符号

1.1  &  按位与:

(看成*)

两个二进制操作数对应位同为 1 ,结果位才为 1 ,其余情况为 0。

eg:5&-2

        (1)先写出 5,-2 的补码 .

        

 5 的补码:00000000 00000000 00000000 00000101
 
-2 的原码:10000000 00000000 00000000 00000010
-2 的反码:11111111 11111111 11111111 11111101
-2 的补码:11111111 11111111 11111111 11111110

         (2)

​      5 的补码:00000000 00000000 00000000 00000101
     -2 的补码:11111111 11111111 11111111 11111110
 5 & -2 的补码:00000000 00000000 00000000 00000100

        (3)此时得到的是补码,要原码才能打印 

 5 &- 2 的原码:00000000 00000000 00000000 00000100 
 (正整数原、反、补相同)

此时打印结果是:4 

 1.2  |   按位或:

(看成+)

两个二进制操作数对应位只要有一个为 1 ,结果 位 就为 1 ,其余情况为 0 。

eg:5|-2

        (1)先写出 5,-2 的补码

​ 5 的补码:00000000 00000000 00000000 00000101
 
-2 的原码:10000000 00000000 00000000 00000010
-2 的反码:11111111 11111111 11111111 11111101
-2 的补码:11111111 11111111 11111111 11111110

        (2)

      5 的补码:00000000 00000000 00000000 00000101
     -2 的补码:11111111 11111111 11111111 11111110
 5 | -2 的补码:11111111 11111111 11111111 11111111

        (3) 

5 | -2 的补码:11111111 11111111 11111111 11111111
5 | -2 的反码:11111111 11111111 11111111 11111110
5 | -2 的原码:10000000 00000000 00000000 00000001

此时打印结果是:-1 

1.3  ^   按位异或

两个二进制操作数对应位相同为 0 ,不同为 1

eg:先写出 5,-2 的补码

        (1)

​ 5 的补码:00000000 00000000 00000000 00000101
 
-2 的原码:10000000 00000000 00000000 00000010
-2 的反码:11111111 11111111 11111111 11111101
-2 的补码:11111111 11111111 11111111 11111110

        (2) 

​      5 的补码:00000000 00000000 00000000 00000101
     -2 的补码:11111111 11111111 11111111 11111110
 5 ^ -2 的补码:11111111 11111111 11111111 11111011

        (3)

5 ^ -2 的补码:11111111 11111111 11111111 11111011
5 ^ -2 的反码:11111111 11111111 11111111 11111010
5 ^ -2 的原码:10000000 00000000 00000000 00000101
1.4  ~   取反 

一个二进制操作数,对应位为 0 ,结果位为 1 ;对应位为 1 ,结果位为 0.
作用是将每位二进制取反

 eg:先写出 5 的补码 

        (1)

​ 5 的补码:00000000 00000000 00000000 00000101

        (2) 

​ 5 的补码:00000000 00000000 00000000 00000101
     取反:11111111 11111111 11111111 11111010

        (3)此时得到的是补码,需要原码才能打印

取反后(补码):11111111 11111111 11111111 11111010
         反码:11111111 11111111 11111111 11111001
         原码:10000000 00000000 00000000 00000110

此时打印的结果是:-6 

 1.5  <<   左移运算符

 代码:

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

结果是 -10

规则:

正数:所有数据位向左移动n位,右边空位补0  

负数:所有数据位向左移动 n 位,右边空位补 0

eg:

(1)先写出 -5 的补码

原码:10000000 00000000 00000000 00000101 (最高位为1)
 
反码:11111111 11111111 11111111 11111010 (按位取反,符号位不变)
 
补码:11111111 11111111 11111111 11111011 (反码加1)

(2)补码向左移动一位,左边去掉,右边补0,如图:

(3)此时得到的是补码,还要反推原码才能打印

补码:11111111 11111111 11111111 11110110
 
反码:11111111 11111111 11111111 11110101(补码 -1 得到反码)
 
原码:10000000 00000000 00000000 00001010(按位取反得到原码)

 注:求原码也可以补码符号位不变,其余位取反再+1。

此时得到的原码就可以打印了,结果是 -10。

1.6  >>  右移运算符

代码:

#include<stdio.h>
int main()
{
	int a = -5;
	int b = a >> 1;
 
	printf("%d\n", a);
	printf("%d\n", b);
 
	return 0;
}
规则:
正数:所有数据位向右移动 n 位,左边空位补 0
负数:所有数据位向右移动 n 位,左边空位补 1
eg:
(1)先写出 -5 的补码
原码:10000000 00000000 00000000 00000101 (最高位为1)
 
反码:11111111 11111111 11111111 11111010 (按位取反,符号位不变)
 
补码:11111111 11111111 11111111 11111011 (反码加1)

(2)补码向右移动一位,右边丢弃,左边补符号位,如图:

(3)

补码:11111111 11111111 11111111 11111101
 
反码:11111111 11111111 11111111 11111100(补码 -1 得到反码)
 
原码:10000000 00000000 00000000 00000011(按位取反得到原码)

此时得到的原码就可以打印了,结果是 -3

🔔不能移动数位是负数的。

2.赋值运算符

= += -= *= /= %= >>= <<= &= |= ^=
a = 18;
a += 18 == a = a+18;
a = 20;
a + 5;
printf("a=%d\n",a);//a==20

3.递增递减运算符

前缀++ 后缀++ 前缀-- 后缀--
a = 18;
a++;//18->19
++a;//19->20
a--;//20->19
--a;//19->18
a = 18;
a++ + 5 == 23;//a+5 a+=1
a = 18;
++a + 5 == 24;//a+=1 a+5
前缀++:先自身的值加1再参与运算
后缀++:先参与运算再自身的值加1

🔔:a++与a--,是复制一个自己,用复制的自己去参与运算。

4.地址运算符

&
不同程序直接变量名可以重复,但是地址编号是唯一的
&变量名得到变量的存储地址编号
printf("&a=%p\n",&a);
printf("&b=%p\n",&b);

5.逗号运算符

表达式 , 表达式 , 表达式 , 表达式 ...
从左至右所有表达式依次运算,取最后的表达式结果为 整体逗号运算结果。
int a = (3+5,5*3,7+4,9-
4);//8,15,11,5
printf("a=%d\n",a);//a==5
a = (a+=1,a*=2,a-3);//6,12,9
printf("a=%d\n",a);//a==9

6.sizeof运算符

sizeof :计算数据类型字节大小

7.条件运算符

表达式 ? 表达式 1(true) : 表达式 2(false)

8.短路法则

&& || 中存在短路法则,当运算符左值结果已经能决定整体运算结果时不会再运算右值。
0&& ==0 1|| ==1 ,其中 0 1 已经决定了最终结 果,?不再运算。

二.数据类型

1.基本数据类型

signed:有符号数,不写时默认

unsigned:无符号数,需要指定

2.char 字符型 1个字节

取值范围:0~255

                -125~127

3.int 整型 4个字节

取值范围:0~2^32-1

                -2^31~2^31-1

4.short 短整型 2个字节

取值范围:0~65535

                -32768~32767

5.long长整型 8个字节

取值范围:0~2^64-1

                -2^63~2^63-1

6.float 4个字节 单精度浮点型,double 8个字节 双精度浮点型

double使用两个存储单元,所以在64和32位系统中都是8个字节

浮点:他们小数点最后一位是上下浮动的。

三.常量和变量

1.常量

程序运行期间数值不发生变化

1.整型常量:13

2.字符常量:a

3.浮点常量:1.34

4.字符串常量:“abcd”

5.标识符常量:是指用标识符替代常量使用的一种常量,其名称统称是一个标识符。

与变量的区别:一般使用大写英文字母表示,表示常量在使用前必须预先定义。

放在main外面:  #define 标识符常量名 常量;

#define X 10

#define X 10
#define Y X+15 //10+15
#define z X*Y //10*10+15

int main(int argc, char *argv[])
{
int a = z;
printf("a=%d\n",a);//115
return;
}

🔔标识符常量是严格的同义替换,不会提前计算 。

2.变量

1.变量名由用户根据其用途任意命名,变量名命名遵从标

识符的起名规则。
2.定义:  存储类型 数据类型 变量名;
   存储类型:
                auto:自动存储类型
                extern:外部调用类型引用在其它文件中函数体外部说明的变量
                register:寄存器类型
                static:静态存储类型
                                (1). 延长变量生命周期
                                (2). 只会被初始化一次
                                (3). 限定作用域在本文件之中
3.变量初始化:定义的同时进行赋值。
🔔 只定义变量没有赋值,存储的是随机数
2.1局部变量
定义在模块内部的变量
生命周期:随模块结束而结束
作用域:仅模块内部使用
只定义不赋值时是随机数
2.2全局变量
生命周期:随程序结束而结束
作用域:所有模块都可以使用
只定义不赋值时是 0

3.强制类型转换

1.强制数据类型的转换是指采用某种方式将某种数据类型强制转换成指定的数据类型。
  (数据类型)表达式 ;
2.强制类型转换符后面的表达式如存在复杂运算,就一定要用小括号括起来
3.强制类型转换符是一种不安全的转换,一般都是将高级类型转换成低级类型,要丢失数据的精度;
4.强制类型转换并不改变表达式中变量的数据类型和其值。

四.输入输出

4.1字符输出函数 putchar

int putchar ( int c );
把字符 c 输出到终端上
返回值:输出的字符 c
int a = 78;
char b = '*';
char d = putchar(a);
printf("d:%c\n",d);
putchar(b);
putchar(97);
putchar('A');
putchar(10);//打印10的字符'\n'

4.2字符输入函数 getchar

int getchar ( void );
从终端获取字符
返回值 : 获取到的一个字符
char a = getchar();
printf("%c\n",a);

🔔🔔🔔查看问题汇总---(1)。

4.3标准输出函数 printf

int printf ( const char * format , ...);
        format : 格式控制串 = 格式控制串 + 普通字符
        
                格式控制符:
                        % d i -- 十进制整数
                        % c -- 字符
                        % f -- 浮点型小数 % s -- 字符串
                        % p -- 地址
                        % o -- 八进制
                        % x , X -- 十六进制
                        % u -- 无符号十进制
                        % e -- 指数形式
                        % g -- e f 中较短的一种
                        %% -- % 本身
                修饰符:
                        m:输出域宽,输出数据位数小于m时左补空格,否则无效
                        . n :对小数使用指定小数点个数对字符串使用指定字符串字符个数
                        - :左对齐方式
                        #:在八进制和十六进制前显示0和 0x
                        0 :左面不使用的空格替换为 0
                        + :在有符号正数前显示 +
                        l:提升输出精度变为long / double
                普通字符:原样输出
                输出表:输出的数据列表

4.4标准输入函数 scanf

int scanf ( const char * format , ...);
        格式控制串:格式控制串
                格式控制串:
                        格式控制符:
                                %d -- 十进制整数
                                %c -- 字符
                                %s -- 字符串
                                %f -- 浮点型小数
                                %e -- 指数形式
                                %o -- 八进制数
                                %x -- 十六进制数
                                %u -- 无符号十进制整数
                        修饰符:
                                m:输入域宽为m
                                h:降低数据精度
                                l:提升数据精度
                                *:抑制符
         地址表:获取的数据存放的地址

代码演示:

int a;
scanf("%d",&a);
4.4.1.scanf结束条件:
                空白符结束一次数据的获取
                回车结束一个scanf函数
4.4.2.scanf对不同类型输入的处理方式:

希望读者记住scanf函数在读取除字符之外的输入的时候会遵守以下原则

scanf函数每次读取一个字符,跳过所有的空白字符,直到遇到第一个非空白字符的时候才开始读取。(同时也说明sanf不可以加\n)

 (1).整数%d

对于整型数据的输入,也就是说"%d"类型的输入,scanf默认的分割符是所有的空白字符(空格,换行符\n、制表符以及回车\r)。也就是说如果一个scanf函数中出现scanf("%d%d",&a,&b),那么用任何一个空白字符来分隔两个整数a,b的值,变量a,b都可以接收到正确的输入。

eg:

scanf("%d %d",&a,&b);

输入1:
7 3
输出:7 3

输入2:
7    3:
输出:7 3

输入3:
7
3
输出:7 3

        输入队列中的7和3以及中间的空格,制表符或者回车符都会被送入缓冲区,但是scanf只接受非空白字符,因此无论以上三种格式输入都不会改变输入结果,理由是scanf会跳过所有的空白字符,将其丢在缓冲区内。所以,程序在下一次读取输入的时候会首先读取到的是被丢弃在缓冲区中的空白字符。

        如果接下来的转换说明是%c,或者%s,将会直接读取该空白字符而不是跳过,空白字符会从打印队列中显示出来。

eg:

#include <stdio.h>
void main()
{
int a;
char c;
scanf("%d%c",&a,&c);
printf("a=%d c=%c",a,c);
}
---------------------------------------------------------------------------------------

输入:5          //这里的输入是5然后按下enter键(也就是换行符)

输出:a=5 c=

                                                                                     //这里多出来的空白一行就是输入的\n
---------------------------------------------------------------------------------------

(2).字符串%s

如果使用%s转换说明,scanf会读取除了空白以外的所有字符。

scanf在读取字符串时,在遇到第一个空白的时候会停止不再读取输入。第一个空白字符后的所有字符都会被保留在缓冲区中,直到缓冲区被刷新或者被scanf读取走。

(3).字符%c

        scanf在处理对字符数据的输入时,既不会忽略前导空白字符,默认也没有任何分隔字符。所有的字符,包括空白字符都会被当成输入字符。(被称为脏字符:只有在获取%c字符的时候才出现,其它不会出现)

脏字符解决方案:

1.抑制符

char a,b;
scanf("%c%*c%c",&a,&b);

输入;a b                此时,你输入的 (空格)会被第二个%*c代替。
                         也可以代替回车,Tap。
输出a b

2.用空白符吸收

char a,b;
scanf("%c %c",&a,&b);

输入;a b                此时,你输入的 (空格)会被第空格代替
输出a b

3.使用getchar吸收

getchar是用在scanf与scanf之间,getchar()吸收回车键。

scanf("%c",&a);
getchar();
scanf("%c",&b)

4.5字符串输入输出函数

由一个或多个字符组成,用""包含,由‘\0’结尾。

4.5.1puts

调用puts()函数实现字符串的输出。

puts(字符数组);

功能:将字符数组起始地址开始的一个字符串(以’\0’结束的字符序列)输出到终端,并将字符串结束标志’\0’转化成’\n’,自动输出一个换行符

三种方式:
puts("hello");//输出字符串

puts("");//实现换行


char c[ ]= "How\nare\nyou!";

puts(c);

输出结果:

How

are

you!
4.5.2gets

功能:从终端输入一个字符串(包括空格)赋给从字符数组起始的存储单元中,直到读入一个回车符为止。回车符读入后,不作为字符串的内容,系统将自动用’\0’替换,作为字符串结束的标志。

int main(int argc, char *argv[])
 {
     char c[20];
     gets(c);
     printf("%s",c);
     return 0;
  } 

hqyj@ubuntu:~/c/day5$ ./demo5
hello word
hello wordhqyj@ubuntu:~/c/day5$ ^C


同时,puts可以和gets联合使用,代码如下:

 #include <stdio.h> 
int main(int argc, char *argv[])
{
     char c[20];
     gets(c);
     puts(c);
     return 0;
} 

hqyj@ubuntu:~/c/day5$ ./demo5
hello word
hello word
hqyj@ubuntu:~/c/day5$ 

两段代码对比:此时可以看出puts可以代替printf输出字符串,不再需用写%s。

 🔔求方程的根 函数:sqrt();

注意:
        头文件要加math库
        在编译是要加上-lm:gcc sqrt.c -lm
eg:
计算三角周长s,面积all
#include <stdio.h>
#include <math.h>
int main(int argc, char *argv[])
{ 
    float a,b,c,all,s;
    scanf("%f %f %f",&a,&b,&c);
    s = (a+b+c)/2.0;
    all = sqrt(s*(s-a)*(s-b)*(s-c));
    printf("ZC:%.2f\nMJ:%.2f\n",s,all);


    return 0;
} 

hqyj@ubuntu:~/c/day5$ gcc demo3.c -o demo3 -lm
hqyj@ubuntu:~/c/day5$ ./demo3
2 2 2
ZC:3.00
MJ:1.73
hqyj@ubuntu:~/c/day5$ 

  • 56
    点赞
  • 40
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值