C语言提高学习笔记

基础: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 真正用在以下两个方面:

  1. 对函数返回的限定;
  2. 对函数参数的限定;
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; //默认内部链接

内部链接和外部链接有什么区别?

  1. 如果变量是内部链接的话,那么此变量只能在当前文件内访问;
  2. 如果变量是外部链接的话,那么此变量可以被其他文件使用;

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个元素的数组。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值