(Linux)嵌入式打卡第十天

指针与数组

数组名

数组名是数组首元素的地址,数组名是一个常量不可以进行修改·。
数组名的地址 == 数组的首元素地址 == 整个数组的地址;(地址的值是相当的,但意义是不同的)
注意:
    数组名在 sizeof(数组名);  eg: sizeof(arr);
    数组名在&数组名; eg &arr;
    在这两种情况下数组名代表的是整个数组;其他情况下数组名代表的都是数组的首元素地址。
数组名不可以++ , 但是指针变量可以 p++; 
#include <stdio.h>

int main(int argc, const char *argv[])
{
	//定义一个数组
	int arr[5] = {1,2,3,4,5};//arr 数组名

	printf("数组首元素地址:%p\n",&arr[0]);
	printf("数组名arr = %p\n",arr);
	//数组名的值是一个地址,地址的值与数组的首元素的值是一样的

	//通过*取出数组名里面的值
	printf("*arr = %d\n",*arr);//arr是一个地址, *运算符

	//获取整个数组的地址
	printf("&arr = %p\n",&arr);

	return 0;
}
结果:
数组首元素地址:0x7ffe98e777a0
数组名arr = 0x7ffe98e777a0
*arr = 1
&arr = 0x7ffe98e777a0

课堂练习

要求:使用 * 运算符 配合数组名称,遍历下面的数组。
    int arr[10] = {1,2,3,4,5,6,7,8,9,10};
代码:
#include <stdio.h>

int main(int argc, const char *argv[])
{
	//定义一个数组
	int arr[10] = {1,4,2,5,3,6,7,9,8,0};

	//通过数组名遍历数组
	for(int i = 0;i < 10; i++)
	{
		//arr + 0 是数组的首元素的地址,下一个元素arr + 1
		//printf("%d ",*(arr + i)); √
		//printf("%d ",*arr + i); ×
		//printf("%d ",*(arr++)); × 含义:arr++ ==> arr=arr+1
								//常量不可以被赋值
		
		printf("%d ",arr[i]);//√ 通过下标进行访问

		//总结:arr[i] 与 *(arr + 1)都可以访问
		//[]运算符:下标运算符 实现方式:变量名[下标] = *(变量名 + 下标);
	}
	putchar(10);
	return 0;
}
结果:
1 4 2 5 3 6 7 9 8 0 

指针与一维数组

数组名 是数组的首元素地址;通过指针保存数组的地址;

#include <stdio.h>

int main(int argc, const char *argv[])
{
	//定义一个一维数组
	int arr[10] = {1,2,3,4,0,9,8,7,6,5};
	
	//数组名是数组的首元素地址
	int *p = arr;

	//通过针对对数组进行遍历
	for(int i = 0;i < 10;i++)
	{
		//printf("%d",*(p + i));//p 是一个指针 指针+1 移动到下一位
		//printf("%d",p[i]);//[i] <==> *(+i)
		printf("%d ",*p++);//单目运算符从右向左进行运算 先运算++
						  //++是后置运算符,后生效
	}
	putchar(10);

	return 0;
}
结果:
1 2 3 4 0 9 8 7 6 5 

数组越界问题

数组里面进行赋值的时候,超过了数组所申请的个数;

int arr[5] = {1,2,3,4,5,6};//error越界

//遍历数组
int arr[5] = {1,2,3,4,5};
for(int i = 0;i < 10;i++)
{}

越界:
    在代码编译的过程中,编译器是不会检测到越界问题,检测越界问题需要耗费的资源太大;
    越界写:越界写有可能会报错,也有可能不报错·;
    越界读:一般不会发生错误,除非有些区域禁止阅读。

指针与字符串

字符串表示方法:
    (1)使用数组的形式记录字符串:char mystr[128] = "hello world";
    (2)使用指针的形式记录字符串:char *mystr = "hello world";
                                "hello world"内存中 .ro段
                               
                mystr在内存中 栈区:内存中定义了一个指针类型变量,
                变量里面的内容是 .ro段里面"hello world"字符串的
                地址。

计算机内存

在linux虚拟机里,虚拟硬件中内存的大小:4G (0x00000000 ~ 0xffffffff)的空间。
#include <stdio.h>

int main(int argc, const char *argv[])
{
	//定义一个变量
	int number = 10;//变量number定义在内存中

	//打印变量在内存中的地址
	printf("number 的地址: %p\n",&number);//物理内存4G 0x00000000~0xffffffff

	return 0;
}
结果:
number 的地址: 0x7ffff761f774

虚拟内存

C语言中,所有能够接触到的地址,全部都是虚拟地址,不是真正意义上的物理内存的地址。

虚拟地址的优点:

(1)在物理意义上防止了野指针的问题

(2)每一个人的计算机内存大小不一样(4G,8G,16G),统一使用4G的虚拟内存可以方便管理。

(3)0G ~ 3G 每一程序都会有独立的用户空间。

3G ~ 4G所有程序共用一个内核空间。

虚拟内存与物理内存映射

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

int a;
int b = 10;
static int c = 10;

void function()
{
	int d = 10;
	printf("hello world\n");
}

int main(int argc, const char *argv[])
{
	char *f = "hello world";
	char g[20] = "hello";

	int *h = malloc(20);//malloc的返回值是一个指针

	return 0;
}
上述代码中:分别存到哪一个区域
a :未初始化的全局变量:.bss段
b :初始化的全局变量:.data段
c :static修饰的全局变量:.data段
d :初始化的局部变量:栈区
function :.text段
f :局部变量:栈区
*f :相当于字符串“hello world” 存在.ro段
g :局部变量:栈区
*g :char g[20] = "hello";在栈区中申请20个字节空间,空间里面存放的是h e l l o
h :h是一个局部变量,所以在栈区
*h :malloc申请的空间 :堆区

数组与函数传递参数问题

数组名作为函数参数传递的时候:会降级为指针

所以在函数定义的时候,如果需要传输数组,函数的参数就是指针类型。

#include <stdio.h>

//定义函数
void show(int *arr,int size)//数组类型作为参数的时候,会降级为指针
{							//int arr[10] 降级为 int *arr 指针
	for(int i = 0;i < size;i++)
	{
		printf("arr[%d] = %d\n",i,arr[i]);
	}
}

int main(int argc, const char *argv[])
{
	//定义一个数组
	int array[10] = {1,2,3,4,5,0,9,8,7,6};

	//定义一个函数,遍历数组
	show(array,10);

	return 0;
}
结果:
arr[0] = 1
arr[1] = 2
arr[2] = 3
arr[3] = 4
arr[4] = 5
arr[5] = 0
arr[6] = 9
arr[7] = 8
arr[8] = 7
arr[9] = 6

常见的字符操作函数

c语言库中为我们准备了很多的字符串操作函数,需要头文件 #include <string.h>

strlen函数

函数原型:
    size_t strlen(const char *s);
函数功能:
    计算字符串的长度;
函数参数:
    需要测量长度的字符串;
返回值:
    size_t 类型就是 unsigned int 类型
    返回值就是字符串的长度。
#include <stdio.h>
#include <string.h>

//定义一个函数返回字符串的长度
int mystrlen(char *s)
{
	//定义一个计数器
	int count = 0;

	while(*s != '\0')
	{
		count++;
		s++;
	}
	return count;
}

int main(int argc, const char *argv[])
{
	//定义一个字符串
	char mystr[128] = "hello world";
	char *mystr1 = "hello";//也是一个字符串

	int len = strlen(mystr);
	int len1 = mystrlen(mystr1);

	printf("len = %d,len1 = %d\n",len,len1);

	return 0;
}

strcpy函数

函数原型:
     char *strcpy(char *dest, const char *src);
函数功能:
    将原字符串的内容拷贝到目标字符串;
函数参数:
    dest:目标字符串
    src:原字符串
返回值:
    目标字符串的首地址;
#include <stdio.h>
#include <string.h>

char *mystrcpy(char *dest,char *src)
{
	//将src里面的内容 赋值给dest
	
	char *p = dest;
	char *q = src;
/*
 //完成字符串的赋值
	while(*q != '\0')
	{
		*p = *q;
		p++;
		q++;
	}
	*p = '\0';
	*/
	while(*p++ = *q++);//依次取出指针p里面的数据
	//然后赋值给 指针p指向的空间,当*q为\0的时候,会将\0赋值给
	//*p的位置,因为赋值的是\0,所以这个表达式的结果为\0
	//0就是'\0',就是假,所以结束循环
}

int main(int argc, const char *argv[])
{
	char *src = "hello world";
	char dest[128];//空间必须给够

	char *ch = strcpy(dest,src);

	printf("ch = %s\n",ch);
	printf("dest = %s\n",dest);

	return 0;
}
结果:
ch = hello world
dest = hello world
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值