C语言学习04

数组

有\0结尾的称为字符串 没有\0结尾的称为字符数组

字符数组strd 在算字符个数strlen时需要读到\0才算结束 但是在未定义大小的数组中初始化为字符时结尾是不给开辟\0存储空间的 所以结果不一定准确, -> 不要定义字符数组

int* ar[5]: (数组指针) 数组有五个元素构成 每个元素的类型是指针 是整型类型的指针 可以存放整型变量的地址

int(*pa)[5] (指针变量 存储数组的地址)是一个可以存放数组地址的指针 该数组开辟了五个空间或有五个元素的数组 每个元素是整型类型

int a = 1, b = 2, c = 3, d = 4;

int* ar[5] = {&a, &b, &c, &d};

指针: 四字节(与指针类型无关) 两个值 指针变量自身的值(存储的是地址)  指针变量所指的实体(解引用)

类型名与标识符中的*是 声明 int* ip

int* ip = &a;

*ip => a

&取地址

*解引用(钥匙)

值传递    传地址                                                                                                                                 

实参给形参 结合 从右向左

野指针: 未初始化的指针 系统会给它赋一个随机值 (不一定指向哪里) 之后一旦给它赋值 会把其他区的值改变 危险!! 

所以初始化时 要给未知指向的指针赋空 int* s = NULL;(空指针) -> 不能对空指针解引用、赋值.

定义指针时一定要初始化!!! 函数中形参如果是指针需要对其进行判空

int* fun(){   }  // 返回值为 整型指针

只有编译链接成功后生成可执行文件才谈论生存期

不要将函数中的局部变量赋值给指针,函数结束后再通过该指针读取变量(eg.返回一个指针 该指针指向局部变量的地址) 因为函数结束后系统会将该栈帧回收再分配下一个函数使用,所以地址里面存放的值会相应的改变

数据区.data在程序结束后才还给系统 所以函数中可以定义静态变量(存放在.data) 指针指向静态变量的地址 就可以在函数外读取函数静态变量存放的值了

 

 

 指针类型对指针变量的作用 1. 指针变量加一的能力(指针加一=>加sizeof(指针类型))  2. 解析存储单元的大小

 

 x = *p++;  //  从右向左结合 将p取出与*结合 将其*p的值赋值给x  再将p进行+1

x = ++*p;   //  从右向左结合 将p与*结合 取到p中存放地址对应的值 再++将其里面对应的值进行+1

指针的运算只有加减

*(解引用)和&(取地址)

int a = 10, b = 20;

const int *p1 = &a;

// 约束指向 约束* 所以不能改变*p1的值

//  int const *p1 = &a; 等价

*p1 = 100; // error

p1 = &b;

int a = 10, b = 20;

int * const p2 = &a;

// 约束自身  *没有被约束所以可以改变*p2

*p2 = 100;

p2 = &b; // error

int a = 10,b = 20;

int* ip = &a; // ip 自由

*ip = 100;

ip = &b;

*ip = 200;

int a = 10, b = 20;

const int * const p3 = &a; // 约束自身与指向

 // int const * const p3 = &a; 等价

*p3 = 100; // error

p3 = &b; // error

指针有两个值 -> 自身&指向

const在*左边 是(指向)常性指针 不能通过解引用*p改变里面a的值,但是可以改变p的指向

const在*右边 是(自身)常性指针 不可以改变p的指向 可以通过*p改变指向对应的值

数组名 被看作该数组的第一个元素在内存中的首地址,但在sizeof中除外,sizeof(ar)是给出数组所占内存大小

ar[ i ] -> 编译成 *(ar + i)   下标方案编译成指针方案 i[ ar ] -> *(i + ar)也是可以的

 当数组作为函数的形参是,数组名会退化成指针 ar[] -> *ar 所以形参也需要添加数组长度

多文件结构 #include #ifndef #endif

#include 本质是拷贝    有#的大情况都是在预编译时处理

头文件只参与预编译过程 在头文件内容被拷贝 .i 文件中

#include< > #include" "

使用尖括号< > 编译器会到系统路径下查找头文件

使用双引号" " 编译器首先在当前执行目录下查找头文件, 如果没有找到, 再到系统路径下查找

#ifndef A_H  // A_H是否被定义过 没有的话进入

#define A_H

是否参与编译

#endif  防止头文件被重复引入

为了避免头文件被重复引入 也可以在.h中只写函数声明(加extern) 在同名.c/.cpp文件中写函数定义

fflush(stdin); // 清空缓冲区

rewind(stdin); // 将文件位置指示器移动到文件首位

 断言assert

assert(br!=NULL); // 出错的话终止程序

定义函数: 函数名 功能描述 形参描述 返回值

看见指针一定要判空

函数 形参中有数组名 但函数中不要求对数组/字符串进行改变 可以在形参前加const 第一行需要放断言判空

字符串 <string.h>

字符串常量存放在数据区的只读区域   

.c中可以用指针定义初始化字符串常量 char* str = "str";

.cpp中必须用常指针定义初始化字符串常量 const char* str = "abc";

字符串的长度是由" "定界,但是strlen 计算字符串长度 是遇到\0截止

char strb[30];      strb = "HELLO"; // 不能赋值成功的原因是strb代表数组首地址

strcpy(strb, "HELLO"); // 拷贝赋值

strdup 申请字符串副本 在堆区.heap申请空间 malloc free 原字符串存在于数据区是只读字符串,堆区的副本字符串可读可改  free(str); str = NULL; 释放str后指针str失效 要将失效指针置空

两个同类型指针,指向连续空间可以相减,相减后的结果是数据元素的大小

当且仅当两个同类型指针变量指向同一数组中的元素时,可以用关系运算符> == !=等进行比较,比较规则是指向后面元素的指针高,指向同一元素的相等

void* p; 无类型指针不能解引用

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值