C语言笔记第五天

本文深入探讨了C语言的内存分区,包括未运行和运行中的可执行程序内存布局,如bss区、data区、text区、堆区和栈区。详细解释了各种变量和函数的作用域、生命周期及存储位置。此外,还介绍了冒泡排序和字符串逆序的实现,通过实例展示了函数的调用和指针的使用。
摘要由CSDN通过智能技术生成

目录

内存分区

未运行的可执行程序内存分区

运行中的可执行程序内存分区

普通局部变量,普通全局变量,普通函数,静态局部变量,静态全局变量,静态函数

普通局部变量

普通全局变量

静态局部变量

静态全局变量

普通函数

静态函数

函数

冒泡排序

字符串逆序


内存分区

大部分人都说内存分区这块了解一下就好,但是个人感觉这块是最重要的啊,C语言玩的就是内存啊.

未运行的可执行程序内存分区

bss区:未初始化的全局变量 静态变量

data区:以初始化的全局变量 静态变量

text区:二进制指令

运行中的可执行程序内存分区

堆区:由malloc ralloc calloc 定义的变量

栈区:局部变量 形参 返回值

        返回值:字节数较大的返回值会在栈区,小的会在寄存器上,具体大小好像是4B,不过个人简单的认为内置类型在寄存器上,自定义类型在栈上.

全局区:

        bss区:未初始化的全局变量 静态变量

        data区:以初始化的全局变量 静态变量

        文字常量区:字符串常量 字符常量

代码区(text区):二进制指令

普通局部变量,普通全局变量,普通函数,静态局部变量,静态全局变量,静态函数

普通局部变量

        定义在{}内的普通变量

        普通局部变量同名是会采用就近原则(少写非人类的代码)

        不初始化时值为垃圾值.

作用区域:当前{}内有效

生命周期:

        当前{}内

        离开{}自动回收空间

存储区域:栈区

普通全局变量

        定义在{}外的普通变量

        其他文件想要使用需要声明(extern 类型 变量名)

        不初始化时自动初始化为0

作用区域:当前文件内有效(其他文件想要使用需要声明)

生命周期:

        当前进程(程序)

        进程结束后自动回收空间

存储区域:全局区

静态局部变量

        定义在{}内,前加static的变量

        不初始化时自动初始化为0

作用区域:当前{}内有效

生命周期:

        当前进程(程序)

        进程结束后自动回收空间

存储区域:全局区

静态全局变量

        定义在{}外,前加static的变量

        不初始化时自动初始化为0

        其他文件不能使用

作用区域:当前文件内有效

生命周期:

        当前进程(程序)

        进程结束后自动回收空间

存储区域:全局区

普通函数

其他文件想要使用需要加extern声明

静态函数

前加static的函数

其他文件不能使用,只在当前文件内有效.

如果非要在其他文件中使用,可以在当前文件中定义普通函数,再去调用静态函数

函数

#include <stdio.h>

void func()
{
	printf("hello world\n");
}

int main(int argc,char * argv[])
{
	//其实函数书写的顺序应该是 调用->声明->定义(实现) 这样写可以有效的避免代码的重复毕竟那是一件很蠢的事情
	//函数名就是函数的首地址,我用的是VS没办法演示

	func();

	//函数指针,这个之后在说,但是指针现在也没说....
	//反正意思差不多,函数名就是函数的首地址
	void(*p)() = func;
	p();

	return 0;
}

//哦,忘记说一点,当实参传入形参的时候相当于
//形参 = 实参 赋值操作(会发生自动类型转换,创值的时候不会修改实参)
//函数位调用时形参并不会开辟空间

冒泡排序

#include <stdio.h>
#include <time.h>
#include <stdlib.h>

//交换变量
void swap(int* num, int* num2);

//冒泡排序
void bubbleSort(int arr[], int len);

//遍历数组
void showArr(int arr[], int len);

int main(int argc,char * argv[])
{
	int arr[10] = { 0 };

	//以当前系统时间作为随机数种子(记得好像是这样,这个不重要)
	//如果不加,每次运行得到的随机数都一样
	//srand在头文件stdlib.h中
	//time在头文件time.h中
	srand((unsigned)time(NULL));

	for (int i = 0; i < 10; ++i)
	{
		//初始化数组arr
		//rand在头文件stdlib.h中
		//rand取随机数
		//rand() % 100 取[0,100) 后面 +1 表示 [1,100]
		arr[i] = rand() % 100 + 1;
	}

	//求数组长度
	int len = sizeof(arr) / sizeof(arr[0]);

	showArr(arr, len);

	bubbleSort(arr, len);

	showArr(arr, len);

	return 0;
}

//交换变量,因为值传递不会改变实参,相当于赋值操作(形参 = 实参,num = arr[0])
//指针传递的是地址,操作地址,可以改变原变量.(其实也是赋值操作,两个地址指向一个实体(int变量)) 这个文字描述实在无力啊
//总之改变变量需要指针,改变一级指针需要二级指针
void swap(int* num, int* num2)
{
	//这个之前说过
	*num ^= *num2;
	*num2 ^= *num;
	*num ^= *num2;
}

//冒泡排序
void bubbleSort(int arr[], int len)
{
	//len个元素排序,需要排序len - 1次
	//也可以理解成如果只有一个元素不需要排序
	//其实实际上就是越界,需要从最后一个元素开始到第一个元素,或从第一个元素开始到最后一个元素
	for (int i = 0; i < len - 1; ++i)
	{
		//一次循环排序一个,排完一次减少一个
		for (int j = 0; j < len - 1 - i; ++j)
		{
			if (arr[j] > arr[j + 1])
			{
				//前一个元素大于后一个元素交换,则循环一次最大值会交换到最后一个元素
				swap(&arr[j], &arr[j + 1]);
			}
		}
	}

	如果从最后一个元素开始到第一个元素,需要这么写
	//for (int i = 0; i < len - 1; ++i)
	//{
	//	//一次循环排序一个,排完一次减少一个
	//	for (int j = len - 1; j > i; --j)
	//	{
	//		if (arr[j] < arr[j - 1])
	//		{
	//			//如果这么写,前一个元素大于后一个元素交换,则循环一次最小值会交换到第一个元素
	//			swap(&arr[j], &arr[j + 1]);
	//		}
	//	}
	//}
}

//遍历数组
void showArr(int arr[], int len)
{
	for (int i = 0; i < len; ++i)
	{
		printf("%d ", arr[i]);
	}

	printf("\n");
}

字符串逆序

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>

void stringReversed(char str[], int len);

void swap(char* ch, char* ch2);

int main(int argc,char * argv[])
{
	srand((unsigned)time(NULL));

	char str[10] = "";

	//减1是为了存储'\0'
	for (int i = 0; i < sizeof(str) - 1; ++i)
	{
		//初始化成小写字母 [0,26) 加97(97 ASCII码对应a)[97,122]
		//发生隐式类型转换(自动类型转换)
		str[i] = rand() % 26 + 97;
	}

	printf("%s\n",str);

	stringReversed(str, strlen(str));

	printf("%s\n",str);

	return 0;
}

void stringReversed(char str[], int len)
{
	int front = 0;	//第一个元素下标
	int back = len - 1;	//最后一个元素下标

	//相等时不需要交换,说明是中间的元素
	while (back > front)
	{
		swap(&str[front], &str[back]);
		--back;
		++front;
	}
}

void swap(char* ch, char* ch2)
{
	*ch ^= *ch2;
	*ch2 ^= *ch;
	*ch ^= *ch2;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值