郝斌C语言_指针 ;字符串 ;动态内存分配 ; 结构体(笔记)

笔记目录

  • 前言
  • 一、指针_C语言的灵魂
    • 1.代码_指针变量
    • 2.指针作用
    • 3.指针的分类
    • 4.代码_指针错误1
    • 5.代码_指针错误2
    • 6.代码_输出一个地址
    • 7.代码_指针互换两个数字
    • 8.多级指针
    • 9.指针与一维数组
    • 10.指针与结构体
  • 二、字符串
    • 1.
    • 2.字符串结束标志(重点)
    • 3.字符串长度
    • 4.字符串输入与输出
      • 1.字符串输入
      • 2.字符串输出
    • 5.字符串处理函数
      • 1.字符串连接函数 strcat()
      • 2.字符串复制函数 strcpy()
      • 3.字符串比较函数 strcmp()
  • 三、动态内存分配
    • 1.传统数组的缺点
    • 2.malloc() 与 free()
    • 3.动态一维数组
  • 四、结构体
  • 总结


前言

郝斌 ; C语言 ; 指针 ; 笔记


一、指针_C语言的灵魂

指针 -> 地址 -> 内存单元的编号 -> 8个 bit(0/1) 一个byte(内存单元)  // 32位计算机, 32条线(0,1), 2^32 B = [0, 4G-1] // 寻址到字节
注 : 
1. 指针就是地址, 地址就是指针
2. 地址就是内存单元的编号 ~ 从零开始的非负整数 // 指针的本质就是操作受限的非负整数, 只能用于减法
3. 指针变量是存放地址的变量
4. 指针 与 指针变量 是两个不同的概念 // 叙述时会把指针变量 简称为 指针

1.代码_指针变量

# include 

int main(void)
{
	int *p; //p是变量名, int *表示 : p变量 存放的是 int类型变量的地址
	/*
		不表示定义了一个叫 *p 的变量

    */

	int i = 3;

	p = &i;
	/*
		1.p保存了i的地址, 因此, p指向i
		2.p不是i, i也不是p, 修改p的值不影响i的值, 修改i的值也不影响P的值
		3.如果一个指针变量指向了某个普通变量, 则 *指针变量 完全等同于 普通变量
		  // 所有出现 *p 的地方都可以替换成 i
		               i                    *p
    */


	//p = i; //error, 类型不一致
	//p = 55; //同上

	return 0;
}

// *p : 以p的内容为地址的变量

2.指针作用

  1. 表示一些复杂的数据结构
  2. 快速的传递数据
  3. 使函数返回一个以上的值
  4. 能直接访问硬件
  5. 能够方便的处理字符串
  6. 理解面向对象中 引用 的基础

3.指针的分类

  1. 基本类型指针
  2. 数组指针
  3. 结构体指针

4.代码_指针错误1

# include 

int main(void)
{
	int *p; // 其中为垃圾值

	int i = 5;

	*p = i; // 修改了程序外空间的数据

	printf("%d\n", *p);

	return 0;

}

5.代码_指针错误2

# include 

int main(void)
{
	int i =5;

	int *p;
	int *q;

	p = &i;

	//*q = p;  // 整形与地址不匹配
	//*p = *q; // q未赋值
	// p = q;  // q把垃圾值赋给p

	 printf("%d\n", *q);

	return 0;
}
*q 不能读取的原因 :
	q内部为垃圾值, 没有权限读取(r)读取该内存单元, 直接出错

6.代码_输出一个地址

# include 

int main(void)
{
	int a = 100;
	char str[20] = "A";

	printf("%#x, %#x\n", &a, str); // 十六进制输出

	return 0;
}

//0x19ff30, 0x19ff1c

7.代码_指针互换两个数字

通过被调函数修改主调函数相关变量的值 :
1. 实参必须为该变量的值
2. 形参必须为指针变量
3. *形参名 = ... 方式修改主调函数相关变量值
# include 

void swap(int * , int *); // 函数声明可不写形参

int main(void)
{

	int a = 3;
	int b = 5;

	swap(&a, &b);

	printf("a = %d, b = %d\n", a, b);

	return 0;
}

void swap(int *p, int *q)
{
	int t;
	 t = *p;
	*p = *q;
	*q =  t;

	return ;

}

8.多级指针

9.指针与一维数组

1. 地址一般以十六进制保存
2. 一维数组名是个指针变量, 存放的是一维数组第一个元素地址
3. 

10.指针与结构体


二、字符串

1.

1. C语言中,没有string类型,用一个字符数组来存放一个字符串
	char c[30]={'c', '  ', 'p', 'r', 'o', 'g', 'r', 'a','m'};
3. C语言规定,可以将字符串直接赋值给字符数组
	char str[30] = {"C.YuYan"}; //定义时才能将整个字符串一次性地赋值
	char str[  ] = "C.YuYan";   //这种形式更加简洁,实际开发中常用

2.字符串结束标志(重点)

1. '\0' : 字符串结束符;
2. '\0'是 ASCII 码表中的第 0 个字符,英文称为 NUL,中文称为“空字符”。该字符既不能显示,也没有控制功能,输出该字符不会有任何效果,它在C语言中唯一的作用就是作为字符串结束标志.
3. 由" "包围的字符串会自动在末尾添加'\0'. // 注意给'\0'留个位置
4. 字符串长度大于数组长度时,有些较老或者不严格的编译器并不会报错. // 要注意
# include 

int main(void)
{
    char str[30] = {0};  //将所有元素都初始化为 0,或者说 '\0'
    char c;
    int i;
   
	for(c = 65, i = 0; c <= 90; c++, i++)
	{
        str[i] = c;
    }

    printf("%s\n", str);
	printf("%c", str[29]); // 为'\0', 非'0'
   
    return 0;
}

3.字符串长度

# include 

long len = strlen(str); // 不包括'\0'

4.字符串输入与输出

1.字符串输入

  • scanf() : // 数组和字符串不用加 &
    读取字符串时以空格为分隔,遇到空格就认为当前字符串结束了,所以无法读取含有空格的字符串。
  • gets() :
    认为空格也是字符串的一部分,只有遇到回车键时才认为字符串输入结束, 只要不按下回车键,对 gets() 来说就是一个完整的字符串。

2.字符串输出

  • printf() :
    通过格式控制符%s输出字符串,不能自动换行。
  • puts() :
    输出字符串并自动换行,该函数只能输出字符串。

5.字符串处理函数

1.字符串连接函数 strcat()

# include 

strcat(arrayName1, arrayName2);
strcat() 将把 arrayName2 连接到 arrayName1 后面,并删除原来 arrayName1 最后的结束标志'\0'。
这意味着,arrayName1 必须足够长,要能够同时容纳 arrayName1 和 arrayName2,否则会越界(超出范围)。
strcat() 的返回值为 arrayName1 的地址。

2.字符串复制函数 strcpy()

strcpy() 会把 arrayName2 中的字符串拷贝到 arrayName1 中,字符串结束标志'\0'也一同拷贝。

3.字符串比较函数 strcmp()

字符本身没有大小之分,strcmp() 以各个字符对应的 ASCII 码值进行比较。
strcmp() 从两个字符串的第 0 个字符开始比较,如果它们相等,就继续比较下一个字符,
直到遇见不同的字符,或者到字符串的末尾。

返回值:若 arrayName1 和 arrayName2 相同,则返回0;
若 arrayName1 大于 arrayName2,则返回大于 0 的值;
若 arrayName1 小于 arrayName2,则返回小于0 的值。

三、动态内存分配

1.传统数组的缺点

1. 数组长度必须事先制定, 且只能是常整数, 不能是变量
	int a[5]; // ok
	int len = 5; int a[len]; //error
2. 数组占用内存程序员无法手动释放, 函数运行完毕时, 数组空间才会被系统释放
3. 数组长度不能更改
4. A函数中定义的数组, 在A函数运行期间可以被其他函数使用; A函数执行完毕后,无法被其他函数使用

2.malloc() 与 free()

为什么需要动态分配内存 :
动态数组很好的解决了传统数组的4个缺陷, 传统数组也叫静态数组
1. 要使用malloc函数, 必须添加 malloc.h 头文件
2. malloc 函数只有 1个形参, 且形参为整型
3. n表示请求系统为本程序分配n个字节
4. malloc函数只能返回第1个字节的地址
5. 最终分配 n+4个字节 // p变量, 静态占4个字节
char *                200个变量
int *					 50个变量
double *			 25个变量
(           )malloc(200);

3.动态一维数组

四、结构体


总结

23/05/23 - 未完结

你可能感兴趣的:(C,c语言,笔记,算法)