C/C++知识补充

发布时间 2023-11-13 22:29:35作者: zlgwzy

运算符

  • 算术运算符

  • 关系运算符

  • 逻辑运算符

  • 位运算符

  • 赋值运算符

  • 杂项运算符

运算符描述实例
+ 把两个操作数相加 A + B 将得到 30
- 从第一个操作数中减去第二个操作数 A - B 将得到 -10
* 把两个操作数相乘 A * B 将得到 200
/ 分子除以分母 B / A 将得到 2
% 取模运算符,整除后的余数 B % A 将得到 0
++ 自增运算符,整数值增加 1 A++ 将得到 11
-- 自减运算符,整数值减少 1 A-- 将得到 9

下表显示了 C 语言支持的所有关系运算符。假设变量 A 的值为 10,变量 B 的值为 20,则:

运算符描述实例
== 检查两个操作数的值是否相等,如果相等则条件为真。 (A == B) 为假。
!= 检查两个操作数的值是否相等,如果不相等则条件为真。 (A != B) 为真。
> 检查左操作数的值是否大于右操作数的值,如果是则条件为真。 (A > B) 为假。
< 检查左操作数的值是否小于右操作数的值,如果是则条件为真。 (A < B) 为真。
>= 检查左操作数的值是否大于或等于右操作数的值,如果是则条件为真。 (A >= B) 为假。
<= 检查左操作数的值是否小于或等于右操作数的值,如果是则条件为真。 (A <= B) 为真。

 

下表显示了 C 语言支持的所有关系逻辑运算符。假设变量 A 的值为 1,变量 B 的值为 0,则:

运算符描述实例
&& 称为逻辑与运算符。如果两个操作数都非零,则条件为真。 (A && B) 为假。
|| 称为逻辑或运算符。如果两个操作数中有任意一个非零,则条件为真。 (A || B) 为真。
! 称为逻辑非运算符。用来逆转操作数的逻辑状态。如果条件为真则逻辑非运算符将使其为假。 !(A && B) 为真。

 

位运算符

位运算符作用于位,并逐位执行操作。&、 | 和 ^ 的真值表如下所示:

pqp & qp | qp ^ q
0 0 0 0 0
0 1 0 1 1
1 1 1 1 0
1 0 0 1 1

下表列出了 C 语言支持的赋值运算符

运算符描述实例
= 简单的赋值运算符,把右边操作数的值赋给左边操作数 C = A + B 将把 A + B 的值赋给 C
+= 加且赋值运算符,把右边操作数加上左边操作数的结果赋值给左边操作数 C += A 相当于 C = C + A
-= 减且赋值运算符,把左边操作数减去右边操作数的结果赋值给左边操作数 C -= A 相当于 C = C - A
*= 乘且赋值运算符,把右边操作数乘以左边操作数的结果赋值给左边操作数 C *= A 相当于 C = C * A
/= 除且赋值运算符,把左边操作数除以右边操作数的结果赋值给左边操作数 C /= A 相当于 C = C / A
%= 求模且赋值运算符,求两个操作数的模赋值给左边操作数 C %= A 相当于 C = C % A
<<= 左移且赋值运算符 C <<= 2 等同于 C = C << 2
>>= 右移且赋值运算符 C >>= 2 等同于 C = C >> 2
&= 按位与且赋值运算符 C &= 2 等同于 C = C & 2
^= 按位异或且赋值运算符 C ^= 2 等同于 C = C ^ 2
|= 按位或且赋值运算符 C |= 2 等同于 C = C | 2

下表列出了 C 语言支持的其他一些重要的运算符,包括 sizeof 和 ? :

运算符描述实例
sizeof() 返回变量的大小。 sizeof(a) 将返回 4,其中 a 是整数。
& 返回变量的地址。 &a; 将给出变量的实际地址。
* 指向一个变量。 *a; 将指向一个变量。
? : 条件表达式 如果条件为真 ? 则值为 X : 否则值为 Y

 do...while 循环与 while 循环类似,但是 do...while 循环会确保至少执行一次循环.

如果条件为真,控制流会跳转回上面的 do,然后重新执行循环中的 statement(s)。这个过程会不断重复,直到给定条件变为假为止。

排序算法

堆排序、快速排序、希尔排序、直接选择排序是不稳定的排序算法,而基数排序、冒泡排序、直接插入排序、折半插入排序、归并排序是稳定的排序算法。

 函数的实参和形参:

形参(形式参数)

在函数定义中出现的参数可以看做是一个占位符,它没有数据,只能等到函数被调用时接收传递进来的数据,所以称为形式参数,简称形参

实参(实际参数)

函数被调用时给出的参数包含了实实在在的数据,会被函数内部的代码使用,所以称为实际参数,简称实参

形参和实参的功能是传递数据,发生函数调用时,实参的值会传递给形参。

1) 形参变量只有在函数被调用时才会分配内存,调用结束后,立刻释放内存,所以形参变量只有在函数内部有效,不能在函数外部使用。

2) 实参可以是常量、变量、表达式、函数等,无论实参是何种类型的数据,在进行函数调用时,它们都必须有确定的值,以便把这些值传送给形参,所以应该提前用赋值、输入等办法使实参获得确定值。

3) 实参和形参在数量上、类型上、顺序上必须严格一致,否则会发生“类型不匹配”的错误。当然,如果能够进行自动类型转换,或者进行了强制类型转换,那么实参类型也可以不同于形参类型。

4) 函数调用中发生的数据传递是单向的,只能把实参的值传递给形参,而不能把形参的值反向地传递给实参;换句话说,一旦完成数据的传递,实参和形参就再也没有瓜葛了,所以,在函数调用过程中,形参的值发生改变并不会影响实参。

5) 形参和实参虽然可以同名,但它们之间是相互独立的,互不影响,因为实参在函数外部有效,而形参在函数内部有效。

文件读写

打开文件

您可以使用 fopen( ) 函数来创建一个新的文件或者打开一个已有的文件,这个调用会初始化类型 FILE 的一个对象,类型 FILE 包含了所有用来控制流的必要的信息。

关闭文件

为了关闭文件,请使用 fclose( ) 函数。函数的原型如下:

 int fclose( FILE *fp );

如果成功关闭文件,fclose( ) 函数返回零,如果关闭文件时发生错误,函数返回 EOF。这个函数实际上,会清空缓冲区中的数据,关闭文件,并释放用于该文件的所有内存。

写入文件

下面是把字符写入到流中的最简单的函数:

int fputc( int c, FILE *fp );

函数 fputc() 把参数 c 的字符值写入到 fp 所指向的输出流中。如果写入成功,它会返回写入的字符,如果发生错误,则会返回 EOF。您可以使用下面的函数来把一个以 null 结尾的字符串写入到流中:

int fputs( const char *s, FILE *fp );

函数 fputs() 把字符串 s 写入到 fp 所指向的输出流中。如果写入成功,它会返回一个非负值,如果发生错误,则会返回 EOF

只要遇到一个空格,scanf() 就会停止读取

位段不能跨字节存储,不能跨类型存储

类型存储大小值范围
char 1 字节 -128 到 127 或 0 到 255
unsigned char 1 字节 0 到 255
signed char 1 字节 -128 到 127
int 2 或 4 字节 -32,768 到 32,767 或 -2,147,483,648 到 2,147,483,647
unsigned int 2 或 4 字节 0 到 65,535 或 0 到 4,294,967,295
short 2 字节 -32,768 到 32,767
unsigned short 2 字节 0 到 65,535
long 4 字节 -2,147,483,648 到 2,147,483,647
unsigned long 4 字节 0 到 4,294,967,295

 

类型存储大小值范围精度
float 4 字节 1.2E-38 到 3.4E+38 6 位有效位
double 8 字节 2.3E-308 到 1.7E+308 15 位有效位
long double 16 字节 3.4E-4932 到 1.1E+4932 19 位有效位

 

  •  a,默认为10进制 ,10 ,20。
  •  b,以0开头为8进制,045,021。
  •  c.,以0b开头为2进制,0b11101101。
  •  d,以0x开头为16进制,0x21458adf。

预处理

C++的预处理功能主要有三种:

1、文件包含处理

2、宏定义

3、条件编译

宏定义:

不带参数的宏定义:用一个简单的名字来替换一个长的字符串

#define 标识符 字符串

  

带参数的宏定义:

#define 标识符(参数列表)字符串

  

#define S(a,b) a*b 定义一个宏S,它带有两个形参a、b

Area=S(2,3)相当于area=2*3

  

条件编译:(可以用来解决由于文件包含而出现的变量重名的问题)

当满足条件时对一组语句进行编译,当不满足时编译另外一组语句。

#ifdef(或者ifndef) 标识符

       程序段1

#else

       程序段2

#endif

  

指令描述
#define 定义宏
#include 包含一个源代码文件
#undef 取消已定义的宏
#ifdef 如果宏已经定义,则返回真
#ifndef 如果宏没有定义,则返回真
#if 如果给定条件为真,则编译下面代码
#else #if 的替代方案
#elif 如果前面的 #if 给定条件不为真,当前条件为真,则编译下面代码
#endif 结束一个 #if……#else 条件编译块
#error 当遇到标准错误时,输出错误消息
#pragma 使用标准化方法,向编译器发布特殊的命令到编译器中

 

存储类

变量的存储类型:

局部变量:在函数或者块内定义的变量

全局变量:在块作用域中,可以通过作用域运算符::来引用与局部变量同名的全局变量

动态变量:在定义变量时分配存储空间,执行到该变量的作用域结束时,收回为其分配的存储空间。

静态变量:在程序开始执行的时候就分配存储空间。

存储类型:(存储类型)<类型><变量名表>;

 

auto 存储类

auto 存储类是所有局部变量默认的存储类。

定义在函数中的变量默认为 auto 存储类,这意味着它们在函数开始时被创建,在函数结束时被销毁。

register 存储类

register 存储类用于定义存储在寄存器中而不是 RAM 中的局部变量。这意味着变量的最大尺寸等于寄存器的大小(通常是一个字),且不能对它应用一元的 '&' 运算符(因为它没有内存位置)。

动态局部变量,存储在CPU的寄存器中,存取速度快,可以提高程序的运行速度。寄存器变量常被用作循环控制变量。

static 存储类

可以分为静态局部变量静态全局变量

静态局部变量和自动类型的局部变量不同。当调用定义该变量的函数结束后,系统并不收回这些变量占用的内存空间,当再次进行调用时,变量仍使用相同的内存空间。但是虽然静态局部变量在函数调用后仍然存在,但是它不能被其他函数引用,只能由定义它的函数引用。

#include<stdio.h>
using namespace std;
void f(int x,int y)
{
    int m=0;
    static int n=0;
    m+=x+y;
    n+=x+y;
    printf("m=%d,n=%d\n",m,n);
}
int main()
{
    int i=5,j=10,k;
    for(int k=1;k<=3;k++)
    {
        f(i,j);
    }
    return 0;
}
m=15,n=15
m=15,n=30
m=15,n=45

  

 

 1 #include <stdio.h>
 2  
 3 /* 函数声明 */
 4 void func1(void);
 5  
 6 static int count=10;        /* 全局变量 - static 是默认的 */
 7  
 8 int main()
 9 {
10   while (count--) {
11       func1();
12   }
13   return 0;
14 }
15  
16 void func1(void)
17 {
18 /* 'thingy' 是 'func1' 的局部变量 - 只初始化一次
19  * 每次调用函数 'func1' 'thingy' 值不会被重置。
20  */                
21   static int thingy=5;
22   thingy++;
23   printf(" thingy 为 %d , count 为 %d\n", thingy, count);
24 }

实例中 count 作为全局变量可以在函数内使用,thingy 使用 static 修饰后,不会在每次调用时重置。

extern 存储类

extern 存储类用于定义在其他文件中声明的全局变量或函数。当使用 extern 关键字时,不会为变量分配任何存储空间,而只是指示编译器该变量在其他文件中定义。

#include <stdio.h>
 
int count ;
extern void write_extern();
 
int main()
{
   count = 5;
   write_extern();
}
#include <stdio.h>
 
extern int count;
 
void write_extern(void)
{
   printf("count is %d\n", count);
}

 

内联函数(inline)

就是在编译时把函数体直接插入调用处,而不是在执行中发生调用函数的控制转移,可以缩短程序的运行时间。内联函数体内一般不含有循环、Switch分支和复杂嵌套的if语句。

inline <类型> <函数名>(<形式参数表>)

  

函数的重载:

指用重名函数完成不同的功能的函数运算。编译器根据不同的参数去调用不同的重载函数。

new运算符和delete运算符

new运算符用于动态分配存储空间,并将分配内存的地址赋给指针变量

<指针变量> = new <类型>;

int *pi=new int;

<指针变量> = new <类型>(value) 这里的value为初始值,容易和下面的混淆

<指针变量> = new <类型>[<表达式>];分配指定类型的数组空间

float *p=new float[n];分配n个float类型的内存单元

  

delete运算符

delete <指针变量>

delete [<表达式>] <指针变量> 例如:delete []p;

  

引用类型变量

<类型>&<引用变量名>=<变量名>;

引用了类型主要用于函数之间传递数据

对于需要返回两个或两个以上运算结果的函数,使用引用变量。引用类型变量是已定义变量的别名;变量与引用类型共用同一存储空间。可以解决函数返回多个运算结果的问题。

#include<stdio.h>
void swap(int &rx,int &ry)
{
    int temp;
    temp=rx;
    rx=ry;
    ry=temp;
}
int main()
{
    int x=3,y=5;
    swap(x,y);
    printf("x=%d,y=%d\n",x,y);
    return 0;
}

这里形参rx,ry被定义为整型引用类型。在调用swap(x,y)函数过程中,参数的传递过程相当于执行下面的引用类型变量的语句

int &rx=x;

int &ry=y;