C语言学习笔记(一):程序编译执行过程及指针基础

C语言学习笔记(一):程序编译执行过程及指针基础

1、程序编译执行的过程

	1、预处理:宏定义展开、头文件展开、条件编译等,通过是将代码中的注释删除,这里并不会检查语法
	2、编译:检查语法,将预处理后的文件编译生成汇编文件
	3、汇编:将汇编文件生成目标文件(二进制文件)
	4、链接:C语言写的程序是需要依赖各种库的,所以编译之后还需要把库链接到最终的可执行程序中去

编译执行过程图

2、程序在存储空间中的流转

	之后详细学习内存及cpu的内部结构

流转

3、cpu与内存

	1、64与32位系统的区别 如下图

在这里插入图片描述

	2、寄存器、缓存、内存三者关系 如下图

在这里插入图片描述

4、指针

1、指针基础
//指针的定义 :
int a=10;
int* p=&a;
*p=20;

其中变量 a 指针p都是有自己的内存空间比如a的内存空间为0xff00,指针p的内存空间为0xff04。
int a=10 的操作表示开辟内存空间地址为0xff00并在里面存储了一个int类型的值10,
int* p=&a;的操作表示开辟内存空间地址为0xff04并在里面存储变量a的内存空间地址0xff00
*p=20;的操作表示 将变量a的内存里面的值变更为20;
其中 星号表示取指针指向的内存空间里面的值(用于指针),&表示取内存空间的地址。
无论是什么类型的指针,里面存的都是地址,内存地址都时是无符号的整型,所以都是4(在32位系统中为4,在64位系统中为8个字节)个字节大小

2、野指针、空指针、万能指针

内存中0-255的控件是系统保留的 不能读也不能写。

野指针是指向的一个位置的内存空间 可能在读写的时候出现错误。

int* p;
p=NULL;
*p = 100;

空指针就是指向内存空间编号为0的空间,操作空指针程序同样会报错
上面定义了一个指针 并且给指针赋值为空,然后给空指针指向的内存赋值100,这样程序会挂掉。
一般空指针是用来进行判断的,比如我们申请一块内存空间 并将内存空间的地址赋值给空指针,然后判断空指针的值是否为空,从而来判断申请内存空间的操作有没有成功。

万能指针如下:

int main(){
int arr[10] = {0};//创建数组里面10个值 全为0
void* p=arr;//这里没有用取地址符号&,是因为数组的变量名指向的就是数组的首地址
*(int*)p = 100;//void*表示万能指针 若想给指针指向的内存赋值 得先将指针转换为指定的类型(int*)表示将万能指针变量p转换为整型指针变量
*(int*)p+1=200; //表示给arr[1]赋值

}
3、const修饰指针
const int a =10;
int* p =&a;
*p =100;

在程序中const常量 我们是不希望他的值发生变化的,但是上面代码中利用指针 竟然改变了const常量 a的值,这种情况是不安全的。

 int a =10;
const int* p =&a;
*p =100; //程序在这里就会报错

用const修饰指针变量的情况下 这个指针指向的内存空间里的值就不能被改变了,但是指针本身内存空间里的值是可以改变的,不然 的话上面代码第二行就会报错。

在这里插入图片描述
上图中用方框 框起来的代码都是会报错的,const可以认为是一把锁 锁在谁的前面 谁就不能动。
比如锁在指针变量p的前面( int* const p),那么指针变量p 自己的内存空间就无法修改,也就是p=&a;会报错。
比如锁在int前面 也在p前面 (const int const p=&a)这样p=&b,*p=100 这两个操作都无法进行,也就是说 再也无法通过指针p去操作变量a 所在的内存空间的值,且指针p永远指向变量a的内存空间。

4、指针实现冒泡排序
#include<stdio.h>
#include<string.h>
#include<stdlib.h>

void bubble(int* p, int len)
{
	for (int i = 0; i < len - 1; i++)
	{
		for (int j = 0; j < len - 1 - i; j++)
		{
			if (*(p + j) < *(p + j + 1))
			{
				int temp = *(p + j);
				*(p + j) = *(p + j + 1);
				*(p + j + 1) = temp;
			}
		}
	}
}
int main()
{
	int arr[10] = { 4,9,10,3,5,7,1,8,2,6 };
	int* p = arr;
	int len = sizeof(arr) / sizeof(int);
	bubble(p, len);
	for (int i = 0; i < 10; i++)
	{
		printf("%d\n", arr[i]);
	}
}
5、实现strchr函数
#include<stdio.h>
#include<string.h>
#include<stdlib.h>

char* mystrchr(char* p, char ch)
{
	int index = 0;
	while (*p!='\0')
	{
		if (*p=='o')
		{
			return p;
		}
		p++;
	}
	return NULL;
}
int main02()
{
	char arr1[] = "hello world";
	char ch = 'o';
	char* p = mystrchr(arr1, ch);

	printf("%s\n", p);
	/*printf("%c\n", *(p+sizeof(char)));
	printf("%c\n", *(p + 1));
	printf("%c\n", *(p + 2));*/
	return 0;
}
6、实现字符串反转
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
void reconvert(char* arr)
{
	int len = strlen(arr);
	char* p1 = arr;
	char* p2 = &arr[len - 1];
	while (p1 < p2)
	{
		char temp = *p1;
		*p1 = *p2;
		*p2 = temp;
		p1++;
		p2--;
	}

}
int main03()
{
	char arr[] = "hello world";
	reconvert(arr);
	printf("%s\n", arr);
	return 0;
}
7、指针数组
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
int main04()
{
	int a = 10;
	int b = 20;
	int c = 30;
	int* arr[] = {&a,&b,&c};
	*arr[0] = 100;
	printf("%d\n", a);
	printf("%d\n", b);
	printf("%d\n", c);
	return 0;
}
int main()
{
	char* arr[] = { "hello","world1","nihao12","baobei22" };//指针数组arr里面存的是 各个字符串的首地址
	int len = strlen(arr[1]);
	printf("%d\n", len);
	printf("%c\n", *(arr[1] + 2));
}
8、多级指针

n级指针的值为n-1级指针的内存地址。
由程序的运行结果来看 二级指针的值为一级指针地址的时候,*pp:指向的是一级指针的值;**pp:指向的是 一级指针指向的地址里面存的值。

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

int main()
{
	int a = 10;
	int* p = &a;
	int** pp = &p;
	/**pp = 20;*/
	printf("a的值:%d\n", a);
	printf("a的地址:%p\n", &a);

	printf("p的值:%p\n", p);
	printf("p的地址:%p\n", &p);

	printf("pp的值:%p\n", pp);
	printf("pp的地址:%p\n", &pp);
	printf("--------------------------------------\n");
	printf("*pp指向的值:%p\n", *pp);
	printf("**pp指向的值:%d\n", **pp);
	return 0;	
}

总结:*pp==p==&a **pp==*p==a=10

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值