1、字符串
字符串总是以’\0’作为结尾,所以’\0’也被称为字符串结束符,字符数组没有/o
两种字符串
char* s = “sss ” 字符指针指向字符串的第一个字符,只读不能修改
string s = “sss”,该字符串使用的strin类,c++中是可以使用类函数修改我都
定义一个字符指针,指向hello
char *y = "hello"; 字符串常量在内存中是只读的,因此不能修改这个字符串的内容
定义一个字符数组,数组中存放字符串
charz[] = "hello" 字符数组可以修改数组中的内容
char str[] = {'h', 'e', 'l', 'l', 'o'}; // 字符数组,逐个字符初始化
定义一个字符指针数组,里面存放的是指向字符串常量的指针,但是可以直接打印出内容
char* a[] = { "BEIJING", "SHENZHEN", "SHANGHAI", "GUANGZHOU" };
printf("%s", a[0]); // 输出 "BEIJING"
计算字符长度
sizeof 计算字节大小会包含/0
strlen 计算字符个数,找到/0就结束
字符串像是“hello”,编译器会在后面名加个/o
char str[] = {'h', 'e', 'l', 'l', 'o'}; ,这种不会再后面添加/o
print 函数%s,表示以字符串打印,遇到/o就结束打印
注意
char* a[] = { "BEIJING", "SHENZHEN", "SHANGHAI", "GUANGZHOU" };
printf("%s", a[0]); // 输出 "BEIJING"
a[0]存放了指向B的字符指针,
a[0]
指向的是 "BEIJING" 字符串的开始位置,而%s
告诉printf
继续打印直到字符串结束(即遇到\0
2、数组
1、一维数组
arr 数组名表示数组的首地址
定义
int arr[] = {1, 2, 3, 4, 5}; // 省略了数组大小,根据初始化列表确定大小为5
int arr[5] = {1,2,3,4,5} 定义的时候,写了元素个数,注意arr[5] 不存在,下标从0开始
数组名作为函数的形参,arr[2] 写成ar[] 就可以,参数没有意义,实参写成arr
- void fun(int arr[], int n)
- {
- int s = sizeof(arr);
- printf("arr所占字节数为:%d\n", s);
- }
- int main()
- {
- int brr[10];
- fun(brr, 10);
- return 0;
-
- }
arr[] =int*`arr 数组名表示数组首地址
数组存放字符串与字符的区别
- char charArray[] = "Hello"; // 实际上存储的是 {'H', 'e', 'l', 'l', 'o', '\0'}
-
2、二维数组
a[2[[4] a[0] 表示第一行元素的首地址
形参需要写上列 arr[][2] 实参arr
二维数组有时候可以将一行元素作为一个对象,如下,实际上是将每行首地址赋值
int arr[2][4]=
int *p[4]={arr[0]、arr[1]、arr[2]、arr[3]}
一、一维数组
静态 int array[100]; 定义了数组array,并未对数组进行初始化
静态 int array[100] = {1,2}; 定义并初始化了数组array
动态 int* array = new int[100]; delete []array; 分配了长度为100的数组array
动态 int* array = new int[100](1,2); delete []array; 为长度为100的数组array初始化前两个元素
二、二维数组静态 int array[10][10]; 定义了数组,并未初始化
静态 int array[10][10] = { {1,1} , {2,2} }; 数组初始化了array[0][0,1]及array[1][0,1]
动态 int (*array)[n] = new int[m][n]; delete []array;
动态 int** array = new int*[m]; for(i) array[i] = new int[n]; for(i) delete []array[i]; delete []array; 多次析构
动态 int* array = new int[m][n]; delete []array; 数组按行存储
三、***数组int* array = new int[m][3][4]; 只有第一维可以是变量,其他维数必须是常量,否则会报错
delete []array; 必须进行内存释放,否则内存将泄漏
四、数组作为函数形参传递
一维数组传递:
void func(int* array);
void func(int array[]);
二维数组传递:
void func(int** array);
void func(int (*array)[n]);
数组名作为函数形参时,在函数体内,其失去了本身的内涵,仅仅只是一个指针,而且在其失去其内涵的同时,它还失去了其常量特性,可以作自增、自减等操作,可以被修改。五、字符数组
char类型的数组被常委字符数组,在字符数组中最后一位为转移字符'\0'(也被成为空字符),该字符表示字符串已结束。在C++中定义了string类,在Visual C++中定义了Cstring类。
字符串中每一个字符占用一个字节,再加上最后一个空字符。如:
char array[10] = "cnblogs";
虽然只有7个字节,但是字符串长度为8个字节。
也可以不用定义字符串长度,如:
char array[] = "cnblogs"
3、链表
指针是一个地址,指针指向地址代表的空间
上一个节点想要连接到下一个节点,需要将下一个节点的地址存放到上一个节点中next域
//头插法
// 把地址给那个变量,就是让那个指针变量指向自己
// 注意左边是指针,右边是地址
//传入头节点、数据域
void headInsert(Node* list, int data) {
Node* newnode = (Node*)malloc(sizeof(Node));//开辟一个空间返回一个地址,新的节点指针node指向这个空间
newnode->data = data;//将数据给新开辟的空间节点
newnode->next = list->next;//让头节点下一个地址赋给newnode的next指针,也就是newnode的next指针指向第二个节点
list-> next = newnode;//将头节点的next指针指向node节点
list->data++;//代表了头节点插入了一个元素
4、栈
单端操作(入栈与出栈在同一侧)
入栈 1,2,3,4,5
出栈 5,4,3,2,1
5、队列
入队与出队在不同侧)
入队1,2,3,4
出队1,2,3,4
gcc是编译器套件
一个将各种高级语言翻译成二进制机器语言的套件
- // gcc -o 输出可执行文件名 输入源代码文件名
-
- gcc -o build 001.c //相当于先调用gcc -s 、gcc -c 、gcc -o
注意:我们的输入文件的后缀名什么重要,gcc套件会根据后缀名的不同调用不同的翻译官去翻译源代码
头文件要与运行文件在同一目录下才可以找到
预处理错误:
一般是头文件无法找到
编译错误:
语法错误 ;{}
链接错误:
链接就是将很多.o文件聚合在一起
原材料不够,undefined reference to fun
多了
我们定义了人多个函数,但是是使用一个函数,我们链接器就不知道该用那个 multiple definition of fun
文件包含
#include 包含头文件
<>表示去系统路径下去包含文件,用尖括号表示在包含文件目录中去查找(包含目录是由用户在设置环境时 设置的
“” 先去当前目录查找,没到就去系统指定目录
如果想在指定路径下检索头文件,可加选项-I。如我的/home/Desktop目录下有个头文件local1.h,在编译包含local1.h的test.c文件时,可用:gcc test.c -o test -I /root/Desktop。
宏定义
#define 宏名 宏内容 将宏名替换为宏内容
条件编译
#ifdef ABC //要是 ABC被定义了,也就是说这个if是true,就会执行下面的,将代码加入编译
#else
#endif
只有当ifdef是真才会将下面的代码加入编译
gcc -DABC -o build 001.c == #define ABC 就是人为使得条件编译加入
预定义宏(操作系统自带的宏定义)
_FUNCTION_ 函数名
_LINE_ 行号
_FILE_ 文件名
宏展开下的#、##
# 字符串化
## 连接符号
- #define ABC(x) #x x就相当于'x'
-
- #define ABC(x) day##x x相当于 dayx
新的数据类型
在c语言中我们会把官方定的数据类型,重定义为其他名字便于理解
这个在stm32、Linux系统中都是这样已经默认了
重定义
#define
auto
默认分配的内存
register
变量存放在寄存器中
作用:定义一些快速访问的变量
register int a;
static
变量存放在静态区
extern
外部声明
const
常量定义(不能改变)
volatile
告知编译器编译方法的关键字,不优化编译
<< 左移 :乘法 *2 二进制下移位
- 4 : 0 0 1 0 0
-
- 8 : 0 1 0 0 0
位运算
&
A & 0 --> 0
|
A | 0 == A
指针:给我们找到资源的内存空间,就是内存空间的地址(盒子)
int* p1 操作系统就会在获取内存中数据是时候以4个字节为单位
char*p1 操作系统就会在获取内存中数据是时候以1个字节为单位
指针+修饰符
const 修饰p,就可以在p左右出现,p指针指向的空间不可以改变==硬件资源地址
- char* const p;
-
- char* p const;
const 修饰char 就可以在char左右出现,指针所指向的空间的内容不可以改变==字符串
- const char*p;
-
- char const *p;
voliatile
防止优化指向内存空间
指针+运算符
变量名[] [] 标签 ID
指针在定义变量类型的时候,就是确定指针一次读取范围的限定
多级指针
int *p
盒子里面存放的地址是一个空间的地址
int **p
盒子里面存放的是一个盒子的地址
内存与内存之间的关系,
int main(int argc,char ** argv)
{
}
将输入的数据的地址,按照顺序存放起来,便于管理
数据类型 数组名[m] m的作用域是在申请的时候
字符串会在最后面自动加一个/o
int a [100] 表示连续内存中最小单位是int
指针数组
char *a[100] *表示数组中存放是是指针,char表示指针指向的内存空间的数据类型
指针数组的话是好多个指针指向不同的块,
数组指针
int (*p)[5] //
一个指针一次性读取五个块,加一个括号就是一个指针读取多个块
数组指针指向一个整形数组p[5]首地址
容易混淆的还有
指针数组int *p[5]
指针
3、结构体、共有体
4、内存分布图
5、段错误分析
代码复用
三要素
1、函数名(地址)
2、输入参数
3、返回值
我们函数参数之前已经告诉电脑了,后面就不需要再说参数类型了