人生漫长。开始学就行,慢慢就越学越好。这是一个学习log,可能错误很多,请谨慎辨别
目录
#include
#include是一个预处理命令,用于包含或插入指定头文件的内容到当前位置。这个命令 告诉编译器在实际编译之前需要做的工作。使用#include可以将头文件的内容插入到源文件中,使得函数声明或宏定义可以在多个文件之间共享。
- #include <stdio.h>
- #include "myHeader.h"
在上述代码中,<stdio.h>是标准输入输出头文件,而"myHeader.h"是用户自定义的头文件。使用尖括号<>和双引号""有不同的搜索路径。尖括号告诉编译器在系统路径下查找头文件,而双引号则首先在当前目录下查找,如果未找到,再在系统路径下查找1。
#define
在C语言中,#define指令是一种预处理命令,用于创建宏定义。这些宏定义可以是常量、表达式、代码片段甚至是基于条件的编译指令。
宏的主要作用包括自动化频繁使用的序列、提供抽象能力以及方便代码的复用和维护。
宏的主要优点是它不占用内存空间,因为它只是一个临时的符号,预编译后这个符号就不存在了。
#define的基本语法如下:
#define 标识符 常量(宏定义的内容)
这里的标识符是宏的名称,常量可以是数字、表达式或一段代码。例如:
#define PI 3.14159 //定义一个表示圆周率的宏
#define MAX(a, b) ((a) > (b) ? (a) : (b))
float radius = 5.0f;
float area = PI * radius * radius; //代码中使用宏
在例子中,PI是一个代表圆周率的宏。如果你在代码中使用PI,预处理器会将其替换为3.14159。而MAX是一个带参数的宏,用于计算两个值中的最大值。
宏展开:预处理器会在编译过程中将宏展开成其定义时的文本内容。宏的主要作用包括自动化频繁使用的序列、提供抽象能力以及方便代码的复用和维护。
宏与函数的区别,虽然宏可以像函数一样使用,但它们之间有几个关键区别:
-
宏在每次使用时都会在程序中插入一份代码,这可能会增加程序的长度。
-
宏不进行类型检查,因此它们是类型无关的,可以用于任何合法的参数类型。
-
宏可能会引起运算符优先级的问题,因此建议在宏定义中多使用括号。
struct
参考链接:struct 结构 - 《阮一峰《C 语言教程》》 - 书栈网 · BookStack
允许自定义复合数据类型,将不同类型的值组合在一起。这样不仅为编程提供方便,也有利于增强代码的可读性。C 语言没有其他语言的对象(object)和类(class)的概念,struct 结构很大程度上提供了对象和类的功能。
下面是struct
自定义数据类型的一个例子,然后声明该类型的变量。
声明了一个struct fraction
类型的变量f1
,这时编译器就会为f1
分配内存,接着就可以为f1
的不同属性赋值。
struct fraction {
int numerator;
int denominator;
};
struct fraction f1;
声明f1.numerator = 22;
赋值。f1.denominator = 7;
赋值。
struct 的数据类型声明语句与变量的声明语句,可以合并为一个语句。
struct book {
char title[500];
char author[100];
float value;
} b1;
上面的语句同时声明了数据类型book
和该类型的变量b1
。如果类型标识符book
只用在这一个地方,后面不再用到,这里可以将类型名省略。
指针变量也可以指向struct
结构。
// 常写成两个语句
struct book {
char title[500];
char author[100];
float value;
};
struct book* b1;
上面示例中,变量b1
是一个指针,指向的数据是struct book
类型的实例。
百度百科:
一个指针当用来指向一个结构体、对象时,称之为结构体指针或对象指针。
struct 结构体类型名 *指针名; //结构体指针
#include <iostream>
#include <string>
using namespace std;
class C
{
public:
int num;
string name;
};
int main(void)
{
C obj;
C *p = &obj;
p->num = 5;
p->name = "Tony";
cout << p->num << p->name << endl;
return 0;
}
- > 是C语言和C++语言的一个运算符,叫做指向结构体成员运算符,用处是使用一个指向结构体或对象的指针访问其内成员。
- > 和 . 的区别
1、指向不同
一般情况下用“.”,只需要声明一个结构体。格式是,结构体类型名+结构体名。然后用结构体名加“.”加域名就可以引用域 了。因为自动分配了结构体的内存。如同 int a;一样。
而用“->”,则要声明一个结构体的指针,还要手动开辟一个该结构体的内存,然后把返回的指针给声明的结构体指针,才能用“->”正确引用。
typedef struct AWB 这个例子是我自己编的,气死!时隔几个月返回来看,发现还编错了。
{
float rg;
float bg;
}awb;
struct AWB *ctx = (struct AWB *)malloc(sizeof(struct AWB));
--------将malloc()返回的 void 指针,强制转换成了结构体指针
if (ctx == NULL) { ------检查分配内存是否成功
return NULL;
}
memset(ctx, 0, sizeof(struct AWB)); -----内存初始化为0
sub1 = ctx->rg;
sub2 = awb.bg;
free(ctx); -------释放内存
否则内存中只分配了指针的内存,没有分配结构体的内存,导致想要的结构体实际上是不存在。这时候用“->”引用自然出错了,因为没有结构体,自然没有结构体的域了。
2、读法不同
(*a).b 等价于 a->b。"."一般情况下读作"的”。
“->”一般读作"指向的结构体的"。
3、作用的不同
在“结构”一单元中出现的->运算符成为“右箭头选择”,在使用中可以用new_node->value = 10;来代替(*new_code).value = 10;
也就是说在结构中,运算符->是运算符*和运算符.的结合,在上述语句中,他先对new_node间接寻址以定位所指向的结构,然后再选择结构的成员value。
函数
函数是一段可以重复执行的代码。它可以接受不同的参数,完成对应的操作。下面的例子就是一个函数。
int plus_one(int n) {
return n + 1;
}
上面的代码声明了一个函数plus_one()
。
函数声明的语法有以下几点,需要注意。
(1)返回值类型。函数声明时,首先需要给出返回值的类型,上例是int
,表示函数plus_one()
返回一个整数。
(2)参数。函数名后面的圆括号里面,需要声明参数的类型和参数名,plus_one(int n)
表示这个函数有一个整数参数 n
。
(3)函数体。函数体要写在大括号里面,后面(即大括号外面)不需要加分号。大括号的起始位置,可以跟函数名在同一行,也可以另起一行,本书采用同一行的写法。
(4)return
语句。return
语句给出函数的返回值,程序运行到这一行,就会跳出函数体,结束函数的调用。如果函数没有返回值,可以省略return
语句,或者写成return;
。
调用函数时,只要在函数名后面加上圆括号就可以了,实际的参数放在圆括号里面,就像下面这样。
int a = plus_one(13);
// a 等于 14
for 循环
for
语句是最常用的循环结构,通常用于精确控制循环次数。
1.一般形式为:
{
中间循环体;
}
for (initialization; continuation; action)
statement;
上面代码中,for
语句的条件部分(即圆括号里面的部分)有三个表达式。
initialization
:初始化表达式,用于初始化循环变量,只执行一次。continuation
:判断表达式,只要为true
,就会不断执行循环体。action
:循环变量处理表达式,每轮循环结束后执行,使得循环变量发生变化。
循环体部分的statement
可以是一条语句,也可以是放在大括号里面的复合语句。下面是一个例子。
for (int i = 10; i > 0; i--)
printf("i is %d\n", i);-------
一条语句
执行过程为:
- 求解表达式1;
- 求解表达式2。若其值为真,则执行 for 语句中指定的内嵌语句,然后执行第3步;若表达式2值为假,则结束循环,转到第5步;
- 求解表达式3;
- 转回上面第2步继续执行;
- 循环结束,执行 for 语句下面的语句。
执行过程中,“表达式1”只执行一次,循环是在“表达式2”“表达式3”和“内嵌语句”之间进行的。
变量
变量名区分大小写,star
、Star
、STAR
都是不同的变量。
有些词在 C 语言里面有特殊含义(比如int
),另一些词是命令(比如continue
),它们都称为关键字,不能用作变量名。
C 语言的变量,必须先声明后使用。声明变量时,必须把变量的类型告诉编译器。
int height;
上面代码声明了变量height
,并且指定类型为int
(整数)。
int num = 42; //
变量的声明和赋值,写在一行。int x = 1, y = 2; //
多个相同类型变量的赋值,可以写在同一行。
不能用变量声明之前定义的常量。
#define a 120 //define 常量
int a; //这是错误的
变量的作用域
作用域(scope)指的是变量生效的范围。
C 语言的变量作用域主要有两种:文件作用域(file scope)和块作用域(block scope)。
文件作用域(file scope)指的是,在源码文件 .c (C 语言的源代码文件,通常以后缀名.c
结尾)顶层声明的变量,从声明的位置到文件结束都有效。------全局变量
int x = 1;
int main(void) {
printf("%i\n", x);
}
上面示例中,变量x
是在文件顶层声明的,从声明位置开始的整个当前文件都是它的作用域,可以在这个范围的任何地方读取这个变量,比如函数main()
内部就可以读取这个变量。其它函数也可以
块作用域(block scope)指的是由大括号{}
组成的代码块,它形成一个单独的作用域。凡是在块作用域里面声明的变量,只在当前代码块有效,代码块外部不可见。---------局部变量
int a = 12;
if (a == 12) {
int b = 99;
printf("%d %d\n", a, b); // 12 99
}
printf("%d\n", a); // 12
printf("%d\n", b); // 出错
上面例子中,变量b
是在if
代码块里面声明的,所以对于大括号外面的代码,这个变量是不存在。
如果同一个名字,既在全局声明了变量,又在函数块里声明了变量,那以最小作用域为准。
全局变量: 在所有函数的外部声明的变量,包括main 函数以外。
静态变量
static 变量为静态变量,当某一个静态变量声明在函数内部时,其初始化只在第一次执行时起作用,随后的执行过程中,变量值将保持上一次执行后的值。
typedef
typedef
命令用来为某个类型起别名。
typedef type name;
- typedef float float32_t;
float
类型占用4个字节(32位),其中8位存放指数的值和符号,剩下24位存放小数的值和符号。
上面代码中,type
代表类型名,name
代表别名。