<>1.typedef:类型重命名

一切合法的变量名的定义(普通变量、指针变量、数组变量、函数指针、结构体)都可以用typedef转换成类型名

加typedef之前
unsigned int UINT; //普通变量 int* PINT; //指针变量 int Array[10]; //数组变量 void (*pfun)(
); //函数指针 struct Student stu; //定义结构体变量stu struct Student *pstu;//定义结构体指针pstu
加上typedef之后
typedef unsigned int UINT; //UINT类型名 typedef int* PINT; //PINT指针类型名 typedef int
Array[10]; //Array数组类型名 typedef void (*pfun)(); //函数指针类型名 typedef struct
Student stu; //stu类型 //使用stu s1; typedef struct Student *pstu; //结构体指针类型
//使用:pstu p1 = NULL;
(1)给已有的类型名起别名
typedef unsigned char u_int8; typedef unsigned short u_int16; typedef unsigned
int u_int32; typedef unsigned double u_int64;
(2)对已有的声明,变量名的定义加上typedef 变成类型名
#include <stdio.h> typedef int Arr[10]; int main() { Arr a = { 1, 2, 3, 4, 5 };
for (int i = 0; i < 5; i++) { printf("%4d ", a[i]); } printf("\n"); }
结果:

结构体经典写法:
#include <stdio.h> struct Student { ...; }stu, *pstu;
//这样是定义了stu结构体变量和pstu结构体变量指针 //前面加上typedef后 typedef struct Student { ...; }stu,
*pstu; //stu便成了自定义的结构体类型 //pstu变成了自定义的结构体指针的类型 //从而可以使用该类型进行定义变量
<>2.请问p和q的类型
int* p, q;
结果:

*和变量名结合,不是与类型名结合,所以p是int指针类型,q是int类型;

结合1,想同时定义p和q两个指针:
#include <stdio.h> typedef int *PTR; int main() { PTR p,q; return 0; }
结果:

<>3.关键字sizeof

* sizeof是一个关键字,在编译期间确定类型和大小; #include <stdio.h> int main() { int a = 0; int x;
//在编译期确定 x = sizeof(++a); //等价于x = 4; printf("a = %d\n", a); return 0; } //结果a
= 0
* sizeof和strlen()的区别
*
调用时机不同:sizeof是关键字,编译期间确定类型和大小

​ strlen()是函数,在运行期间调用函数

*
功能不同:strlen()是专门计算字符串的长度;

​ sizeof在计算字符串所占用的空间大小;
char buff[] = {"helloworld"}; int len = strlen(buff); //len = 10; int size =
sizeof(buff); // size = 11;
<>4、进制数转换的贪心算法

博客

<>5、c/c++的常变量不同侧重点

vs2019的全局变量未初始化默认为0,局部变量未初始化是随机值,使用该值编译不通过

*
c中的常变量侧重与"变量",不能使用常变量定义数组,编译期不通过;

*
c++中的常变量侧重于"常",可以使用该常变量定义数组;

*
C++常变量类似于宏,却有不同与宏

* 编译时期不同
* 与宏有所不同:宏在预编译时进行宏替换;使用常变量定义数组是在编译期进行确定的;
* 是否存在类型和占用空间
* 宏不存在类型,不占用空间
* 常变量有类型,占用空间
* 安全性
* 宏不存在类型,没有类型检查,不安全
* 常变量有数据类型,有类型检查,比较安全
<>6、’ ’ 和" "

’ ‘是字符的定界符, 在’前面加上\后转义变成单引号字符–》\’

例如:
char ch = '''; //error ''是定界符,想使用单引号字符需要转义 char ch = '\''; //true
""是字符串的定界符

<>7、ascii码值

<>8、转义字符

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IgEV0wBA-1635073955443)(C:\Users\小小怪咯\AppData\Roaming\Typora\typora-user-images\image-20211023164550726.png)]

<>9、关于0 ‘0’ ‘\0’

int main() { char cha = 0; //ASCII值为0对应的字符就是空字符 char chb = '0';
//字符0对应的ASCII值48 char chc = '\0'; //等于cha == 》空字符 char chd = ' ';
//空格字符ascii值是32 return 0; }
<>10、关于\000 和\xff

\000将八进制数000转换成十进制对应的ascii码值,码值对应的字符;

* 其中八进制数有效范围000~377,因为char一字节最大取值255,其对应的八进制数就是377;八进制数超出该范围编译器就会报错 char str[]
= {"pzj\141hello"}; //八进制的141转换成十进制的97 //pzjahello //如果是"pzj\1411hello"
//pzja1hello //如果是"pzj\148hello" //只会转义\14因为8超出0~7 //如果是"pzj\889hello"
//此时的\就会被省略 int len = strlen(str); //len = 9
\x00将十六进制的00转换成十进制对应的ASCII码值,码值对应的字符;

*
其中十六进制数的有效范围是0~ff,因为char最大255,对应的十六进制数就是ff;十六进制数超出该范围也会报错
char str[] = {"hello\61xworld"}; //helloaworld
<>10、字符串与\0

字符串的printf("%s")打印、strcpy拷贝、strcat连接、等函数都是以字符串的\0作为结束条件
char str[] = {"hello\0world"}; int size = sizeof(str); //size = 12 int len =
strlen(str); //len = 5 printf("%s\n", str); //hello
<>11、宏和字符串
#define MAX 1000 int main() { char str[] = {"helloMAX"}; printf("%s\n", str);
//helloMAX }
* 原因:MAX是字符串的一部分,不是标识符,不会被宏替换
<>12、char ch = 'abcd’问题

C++有一个叫做“多字符文字”的东西。'1234'就是一个例子。他们有类型int,它是实现–定义了它们所具有的值以及它们可以包含多少字符。

那算不了什么直接与字符被表示为整数的事实有关,但在实现中,很有可能'1234'定义为:
'1' + 256 * '2' + 256 * 256 * '3' + 256 * 256 * 256 * '4'
或:
'4' + 256 * '3' + 256 * 256 * '2' + 256 * 256 * 256 * '1'
<>13、作用域(可见性)和生存期

* 作用域:针对的是编译和链接的过程
* 函数、全局变量从定义起(整个文件可见)全局可见,没有局部函数一说
* 生存期(生命期):针对的是程序的执行过程
* 局部变量的生存周期:函数被调用开始,函数执行结束时消亡,释放存储空间。存储在.stack区
* 全局变量的生存期:从程序开始运行时开始,到程序执行结束时结束。存储在.data区
*
动态生命期(堆区空间):标识符由特定的函数调用或运算来创建和释放,如果调用malloc()为变量分配存储空间开始,free()释放存储空间结束。存储在堆区.heap
编译错误:g_value未定的标识符
#include <stdio.h> void Test() { int a = g_value; } int g_value = 10; int main(
) { Test(); return 0; }
错误理解:误认为程序一边编译一边运行,g_value存在于.data段

<>14、C语言运算符优先级

优先级运算符名称或含义使用形式结合方向说明
1[]数组下标数组名[常量表达式]左到右
()圆括号(表达式) 函数名(形参表)
.成员选择(对象)对象.成员名
->成员选择(指针)对象指针->成员名
2-负号运算符-表达式右到左单目运算符
(类型)强制类型转换(数据类型)表达式
++自增运算符++变量名 变量名++单目运算符
–自减运算符–变量名 变量名–单目运算符
*取值运算符*指针变量单目运算符
&取地址运算符&变量名单目运算符
!逻辑非运算符!表达式单目运算符
~按位取反运算符~表达式单目运算符
sizeof长度运算符sizeof(表达式)
3/除表达式 / 表达式左到右双目运算符
*乘表达式*表达式双目运算符
%余数(取模)整型表达式%整型表达式双目运算符
4+加表达式+表达式左到右双目运算符
-减表达式-表达式双目运算符
5<<左移变量<<表达式左到右双目运算符
>>右移变量>>表达式双目运算符
6>大于表达式>表达式左到右双目运算符
>=大于等于表达式>=表达式双目运算符
<小于表达式<表达式双目运算符
<=小于等于表达式<=表达式双目运算符
7==等于表达式==表达式左到右双目运算符
!=不等于表达式!= 表达式双目运算符
8&按位与表达式&表达式左到右双目运算符
9^按位异或表达式^表达式左到右双目运算符
10|按位或表达式|表达式左到右双目运算符
11&&逻辑与表达式&&表达式左到右双目运算符
12||逻辑或表达式||表达式左到右双目运算符
13?:条件运算符表达式1? 表达式2: 表达式3右到左三目运算符
14=赋值运算符变量=表达式右到左
/=除后赋值变量/=表达式
*=乘后赋值变量*=表达式
%=取模后赋值变量%=表达式
+=加后赋值变量+=表达式
-=减后赋值变量-=表达式
<<=左移后赋值变量<<=表达式
>>=右移后赋值变量>>=表达式
&=按位与后赋值变量&=表达式
^=按位异或后赋值变量^=表达式
|=按位或后赋值变量|=表达式
15,逗号运算符表达式,表达式,…左到右
易错点:
int main() { int a = 1, b = 2; a *= b + 5; //+的优先级高于 *= 所以 a = a * (b + 5) -->
a = 7 printf("%d\n", a); //7 }
<>15、指针存储——小端存储

小端存储:高位数存放在高地址,低位数存放在低地址;

数值存储和地址存储都遵循小端存储

<>16、标准输入文件0、标准输出文件1、标准错误输出文件2

当一个程序开始运行时,默认会打开这三个文件;

*
标准输入文件stdin:对应的文件描述符为0,通过某种映射关系将键盘输入映射成标准输入文件;stdin在内存上是有行缓冲区的,当遇到换行(’\n’)才会输入到缓冲区;
*
标准输出文件stdout:对应的文件描述符为1,通过某种映射关系将屏幕输出映射成标准输出文件;stdout在内存上是有行缓冲区的,当遇到换行(’\n’)才会输出到屏幕;
* 标准错误文件stderr:对应的文件描述符为2,是无缓冲区的,是直接输出在屏幕上;
程序案例:从键盘获取字符输出字符个数

<>17、宏和typedef
#define PINT int* //宏替换,不考虑类型和大小 typedef int* TINT; //类型重命名,会进行类型和大小识别 int main
() { PING a, b; //int* a, b; TINT p, q; //int* p; int* q; }
<>18、extern关键字

extern用在全局变量或者函数的声明之前,用来说明“此变量、函数是在别处定义的,要在此处引用”;

使用情景:同一个工程下的不同文件

文件fun.c
int g_max = 10; void fun() { g_max +=10; printf("%d\n", g_max); }
文件main.c
#include <stdio.h> extern int g_max; extern void fun(); int main() { int a =
g_max; fun(); }
C++中的extern的其他用法;

<>19、static关键字的使用

记忆函数:该函数中含有静态局部变量;

静态局部变量:当函数第一次被调用,函数中的局部静态变量被初始化,当这个函数被再次调用时,不会对该静态变量进行初始化,会保留上次函数执行结束后局部变量的值(作用域不变,生存期改变)

*
注意:C语言的静态局部变量只能用常量进行初始化一次;

​ C++可以用常量和变量进行初始化一次

问题解答:

*
形参能否加上static

答:加上,编译通过,但是该变量是一个“坏”存储类;

所以形参不加static

*
记忆函数是怎样实现第一次初始化的时候调用,后面不调用?

答:在编译阶段,编译器将记忆函数中的静态局部变量存放在.data段中并给该变量一个记录值val =
1,当程序执行到定义静态局部变量的语句时,先对记录值进行判断,如果val == 1说明第一次调用,执行完毕后val–;否则val == 0 ,则跳过这条语句;

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-adZpltRu-1635073955445)(C:\Users\小小怪咯\AppData\Roaming\Typora\typora-user-images\image-20211024161744487.png)]

* 注意:static int a = 10;
在多线程中需要考虑线程安全,多个线程同时执行该条语句,该值其中的val值会被同时拿到,这样就可能会多次执行该语句。单例模式的问题就需要考虑线程安全
静态全局变量:静态全局变量只能在当前文件中使用(作用域受限制,生存期不变)

*
注意1:当全局变量、函数加上static后,作用域受限于本文件,其他文件无法访问;就算其他文件加上extern关键字声明也无法使用

main.c文件
#include <stdio.h> extern int g_max; extern void fun(); int main() { int a =
g_max; //编译报错,无法解析的命令g_max fun(); return 0; } fun.c文件 static int g_max = 10;
static void fun() { printf("%d\n", g_max); }
注意2:希望fun.c文件中的const int a = 10;
常变量被其他文件调用,就在该变量定义前加上extern,同时使用的文件也要加上该变量的extern声明

main.c文件
#include <stdio.h> extern int g_max; int main() { int a = g_max; printf("%d\n",
a); return 0; }
fun.c文件
extern const int g_max = 10; //外部可见的常变量
​ //extern static int g_max = 10;
​ //extern外部可见与static本文件可见矛盾

静态函数:static说明的函数字可以在当前c文件中使用(作用域受限,生存期不变)

<>20、4G的虚拟空间

<>21、数据在内存中存放的位置
#include <stdio.h> int g_maxa = 10 int g_maxb; int g_maxc = 0; static int
g_maxd; //默认是0 static int g_maxe = 0; static int g_maxf = 10; int main() { int
maxa= 10 int maxb; int maxc = 0; static int maxd; static int maxe = 0; static
int maxf = 10; }
<>22、const修饰定义的变量和#define宏替换的区别(见5)

*
处理对象不同:const修饰的是定义的变量,而宏替换定义的是常量

*
处理时期不同:const修饰的变量是在编译期间确定,宏替换是在预编译期进行替换;

*
是否占用空间和有类型:const修饰的变量有大小和类型,宏替换的常量不占空间、不具有类型检查

<>23、浅谈宏函数

就是单纯的替换
#include <stdio.h> #define SUM(x, y) x*y int main() { int a = 3, b = 4; int c =
SUM(a + 1, b + 2); //int c = a+1*b+2 printf("%d\n", c); return 0; } // 解决方案 / #
define SUM(x, y) (x)*(y)
哼哼~啊啊啊啊啊~结束啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦!!!!!!!!!!!!!!!!!!!!!!!!!!!

技术
©2019-2020 Toolsou All rights reserved,
[数据结构]八大排序算法(C语言)总结G1垃圾收集器面试题Android中使用微信H5支付时支付结果刷新问题32-jdbc工具类大学里要参加竞赛吗?都有哪些竞赛可以参加?震惊!!C++居然可以发出声音!C语言之链表入门(超详解)Java实现一个疫情人数管理系统如何用python实现斐波那契数列的前100个MyBatis循环Map(高级用法)