基础:C/C++(封装、继承、多态)、数据结构(了解思想)、系统编程(操作系统)
提升:日志库、配置文件、IPC库、socket、数据库统一访问库
跳跃:项目
1. c语言概述
1.1 ANSI C/C89标准:不能用变量定义数组 int a=1;int array[a]; (错误)
1.2 C99标准:可以用变量定义数组
2. 内存分区
2.1 数据类型的基本概念
数据类型是为了更好进行内存的管理,让编译器能确定分配多少内存。
2.2 数据类型的别名
typedef unsigned int u32;
2.3 void数据类型
void 字面意思是“无类型”,void* 无类型指针,无类型指针可以指向任何类型的数据。
void 定义变量是没有意义的,当你定义 void a,编译器会报错。
void 真正用在以下两个方面:
- 对函数返回的限定;
- 对函数参数的限定;
void test1(void)
{
printf("hello world");
}
2.4 变量的间接赋值
int a = 10;
//直接赋值
a = 100;
//间接赋值
int *p = &a;
*p = 200;
2.5 堆栈
堆是一个大容器,用于动态内存分配,一般由程序员释放,若程序员不释放,程序结束时由操作系统回收。
参数区、栈区、堆区、可读区(bss,data)、只读区(rodata)、文本段
2.6 extern 和 static区别
extern int a = 10; //默认外部链接
static int b = 20; //默认内部链接
内部链接和外部链接有什么区别?
- 如果变量是内部链接的话,那么此变量只能在当前文件内访问;
- 如果变量是外部链接的话,那么此变量可以被其他文件使用;
2.7 calloc 和 realloc区别
void *calloc(size_t nmemb, size_t size);
calloc(10,sizeof(int))
功能:在内存动态存储区中分配nmemb块长度为size字节的连续区域。calloc自动将分配的内存置0。
void *realloc(void *ptr, size_t size);
功能:重新分配用malloc或者calloc函数在堆中分配内存空间的大小。
- realloc不会自动清理增加的内存,需要手动清理;
- 如果指定的地址后面有连续的空间,那么就会在已有地址基础上增加内存;
- 如果没有空间,会重新分配空间,把旧内存的值拷贝到新内存,同时释放旧内存。
3. 字符串
3.1 sprintf( char *str, const char *format, ... )
str:字符串首地址
format:字符串格式,用法和printf()一样
返回值:
成功:实际格式化的字符个数
失败:-1
void test()
{
char buf[1024]={0};
sprintf(buf,"hello,%s,welcome!","John");
printf("buf:%s\n",buf);
}
4. 指针易错点
4.1 越界
char buf[3]="abc";
4.2 指针叠加会不断改变指针指向
char *p = (char *)malloc(50);
p++;
指针要一直指向首地址,不然free会出错。
4.3 返回局部变量地址
char *get_str()
{
char str[] = "abcdefg"; // 栈区
printf("[get_str]str = %s\n",str);
return str;
}
malloc内存地址,可以返回。
4.4 同一块内存释放多次
void test()
{
char *p = NULL;
p = (char *)malloc(50);
strcpy(p,"abcdefg");
if( p != NULL )
{
free(p);
}
}
free()函数的功能只是告诉系统p指向的内存可以回收了,也就是说,p指向的内存使用权还给系统,但是,p的值还是原来的值(野指针),p还是指向原来的内存。
*p = NULL;
5. 数组
5.1 一维数组名
请问指针和数组是等价的吗?
答案是否定的。数组名在表达式中使用的时候,编译器才会产生一个指针常量。那么数组在什么情况下不能作为指针常量呢?在以下两种情况下:
- 数组名作为sizeof操作符的操作时的时候,此时sizeof返回的是整个数组的长度,而不是指针数组指针的长度。
- 当数组作为&操作符的操作时的时候,此时返回的是一个指向数组的指针,而不是指向某个数组元素的指针常量。
void test()
{
int arr[] = {1,2,3,4};
//1.sizeof 2.对数组名取地址&arr
//以上两种情况下,数组名不是指向首元素的指针
printf("sizeof(arr): %d\n",sizeof(arr));
printf("&arr addr: %d\n",&arr);
printf("&arr+1 addr: %d\n",&arr+1);
}
sizeof(arr): 16
&arr addr: 7208104
&arr+1 addr: 7208120
以上两种情况下,数组名是数组类型。
除了以上两点之外,数组名在其他任何情况下都是指向首元素的指针
5.2 多维数组
int arr[3][10] = {0};
这是一个一维数组,包含三个元素,只是每个元素恰好是包含10个元素的数组。