嵌入式linux学习笔记:04_C语言_数组及指针

这篇博客详细介绍了C语言中的数组和指针。数组部分讲解了数组的概念、初始化、下标以及数组名字的含义。在指针方面,讨论了指针的概念、野指针与空指针的区别、指针的运算以及数组与指针的关系。文章深入浅出地阐述了数组和指针在内存中的表现和操作,适合嵌入式Linux初学者学习。
摘要由CSDN通过智能技术生成

一、数组

1、数组的概念?

1、 什么是数组?数组与普通变量有什么关系?
数组其实是集合来的,它是由多个相同类型的普通变量组合而成。当用户需要同时定义多个相同变量时,就可以使用数组。

2、 定义数组时,需要交代什么东西?
1)数组元素的个数?
2)数组中每一个元素的数据类型? ->char short int long float double

定义公式:
数据类型 数组名字[元素的个数]

例子:定义一个具有100个int类型变量的数组
int A[100];

3、从内存空间分析数组特点:

int main()
{
   
       int a; //在内存空间中连续申请4个字节,使用变量a间接访问这片空间。

       int A[100];  //在内存空间中连续申请400个字节,使用变量A间接访问这片空间。

       printf("sizeof(a) = %d\n",sizeof(a));//4

       printf("sizeof(a) = %d\n",sizeof(A));//400

       return 0;
}

4、定义了数组,编译器如何处理数组?
例如: int A[100]
其实分开两个部分进行处理, “int”为第二部分, "A[100]"作为第一部分。

第一部分 -> 决定内存空间中元素的个数。

第二部分 -> 决定每一个元素的数据类型

2、数组初始化

1)定义同时初始化
-> 元素数据类型 数组名字[元素个数] = {初始化列表,每一个成员之间使用","分开}

int A[3] = {100,200,300}; //编译通过

int A[3] = {100,200}; //编译通过

第三个没有赋值的成员等于0

int A[3] = {100,200,300,400}; //编译警告

警告: warning: excess elements in array initializer

int A[] = {100,200}; //编译通过 决定了下标等于2

int A[] = {100,200,300}; //编译通过 决定了下标等于3

int A[] = {100,200,300,400}; //编译通过 决定了下标等于4

2)先定义,没有初始化
int a; -> 局部变量 -> 随机值

int a; -> 全局变量 -> 0

int A[3]; -> 局部变量 -> 全部元素都是随机值

int A[3]; -> 全局变量 -> 全部元素都是0

int A[3] = {100,200}; -> 局部变量 -> 最后一个元素是0

int A[3] = {100,200}; -> 全局变量 -> 最后一个元素是0

3)先定义,后初始化 -> 一般结合循环来完成!
int A[3];

A = {100,200,300}; //编译出错

int A[3];

A[3] = {100,200,300}; //编译出错

小结论:定义数组时没有整体初始化,则之后都不能整体初始化,只能单个初始化。

int A[3];

A[0] = 100;

A[1] = 200;

A[2] = 300;

3、数组的下标

int A[3]; -> 在内存空间中连续申请12个字节,使用变量A间接访问这片内存空间,在访问数组中,使用下标来对成员进行访问。
例如:
int A[N] -> 下标范围: 0~N-1
记住: 最后一个元素是A[N-1],而不是A[N]

4、研究数组的名字含义

1)当数组名作用于sizeof()时,数组名代表这个数组的内存空间。
sizeof() -> 计算内存空间的大小

例子:

int main()

{

int A[3];

printf("%d\n",sizeof(A)); //12

}

2)当数组名不作用于sizeof()时,数组名代表数组首元素的地址。
int A[3];

数组名: A

首元素: A[0]

首元素的地址: &A[0]

结论: A = &A[0]

例子:

int main()

{

int A[3] = {100,200,300};

printf("A[0] = %d\n",A[0]);

printf("&A[0] = %p\n",&A[0]); //0xbfec8cb4

printf("A = %p\n",A);  //0xbfec8cb4

return 0;

}

sizeof(粤嵌) -> 计算整个粤嵌的大小

粤嵌 -> 仅仅代表整个粤嵌第一层楼的地址

二、指针

1、指针的概念

1、什么是指针?什么是指针变量?指针干什么用?
指针 指向是内存上地址,例如: 0xbfec8cb4

指针变量指向是专门用于存放地址的变量 p

指针是唯一的地址,所以确定申请的内存空间在哪里。

例子:

int a; -> 在内存申请一片内存空间,使用变量a间接访问这片内存

&a; -> 获取a变量的地址 &-> 取址符

2、究竟&a获取到地址,存放在哪里?
指针是一个地址,地址就应该存在指针变量中。

3、指针变量如何定义?
指针变量怎样定义取决于指向的内容的数据类型。

例如: int -> int *p

  char   ->    char *p

  double ->    double *p

定义步骤:
1)先写一个 *

2)在*后面写一个指针变量名 *p

3)确定指向的内容 int a;

4)把第3步的内容的变量名去掉 int

5)把第4步的结果写在第2步结果前面 int *p

结果:int *p -> 指针变量,该变量指向一个整型数据!

变量定义公式: 数据类型 + 变量名

变量名:p

数据类型: int*

例子:

int a=100; -> 在内存申请一片内存空间,使用变量a间接访问这片内存

&a; -> 获取a变量的地址 &-> 取址符

int *p = &a; -> 将a变量的地址赋值给指针变量p

4、已知指针变量的值,如何求出该地址指向的内容是什么?
取地址: 已知变量值a,求地址值。 &a

解引用: 已知地址值p,求变量值。 *p

例子:

int a = 100; -> 在内存申请一片内存空间,使用变量a间接访问这片内存

&a; -> 获取a变量的地址 &-> 取址符

int *p = &a; -> 将a变量的地址赋值给指针变量p

int b = *p; -> 解引用出p地址指向的值,再赋值给变量b

例子====

#include <stdio.h>

int main()

{

int a = 100;

int *p = &a;

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

printf("&a = %p\n",&a); // 0xbfde90c8

printf("p = %p\n",p);  // 0xbfde90c8

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

return 0;

}

=======================================================

练习1: char b=‘A’ 能不能赋值给int *p ? -> 不可以,指针类型不对,只能是char *

char b = ‘A’;

char *p = &b;

printf("*p = %c\n",*p); // ‘A’

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

5、指针的内存空间多大?
指针是一个地址,在linux系统32位中,地址长度都是4字节,所有指针变量都是4字节。

sizeof(指针变量名) = 4

#include <stdio.h>

int main()

{

int a = 100;

char b = 'A';

int *pa = &a;

char *pb = &b;

printf("%d\n",sizeof(a));//4

printf("%d\n",sizeof(b));//1

printf("%d\n",sizeof(pa));//4

printf("%d\n",sizeof(pb));//4

return 0;

}

2、野指针与空指针

1、什么是野指针?
定义了一个指针变量之后,但是没有进行初始化,指针变量就会赋值一个随机值,指向一个未知区域。

int a; -> 随机值

a = 5;

int *p; -> 随机值 -> 这时候p就称之为野指针。

p = &a;

2、如何解决野指针?
1)在定义指针初始化指针指向的区域。
例子:

int a;

int *p = &a;

2)使用空指针 -> NULL
NULL其实是一个宏定义,真正NULL是等于0,被定义在一个头文件:

#if defined(__cplusplus)

#define NULL 0

#else

#define NULL ((void *)0)

#endif

例子:

int *p = NULL;

3)其实空指针只是安全区域中其中一个地址,安全区域地址范围: 0x00000000~0x08048000,只要指针指向该范围,那么指针就不会指向别的区域了。
int a;

int *p = (0x00000000~0x08048000);

p = &a;

3、如果访问了安全区域的数据,会出现什么情况?

例子:

#include <stdio.h>

int main(int argc,char *argv[])

{

int *p = (int *)0x08047000;

int a = *p;

printf("p = %p\n",p);

return 0;

}

编译: 通过

执行: 出现段错误 Segmentation fault (core dumped) -> 非法内存访问。

1、如何在程序中寻找段错误?
段错误不是语法错误,所以在编译时不会提示出错,只有等到运行时才会提示出现段错误,但是段错误不会提示在哪一行,可以通过printf()函数来寻找段错误位置,只要发生段错误,那么程序就会马上结束。

例子:

printf(“11111!\n”);

xxxx;

printf(“22222!\n”);

yyyy;

printf(“33333!\n”);

zzzz;

执行:

11111!

22222!

Segmentation fault (core dumped) -> 说明段错误是出现"yyyy;"

2、找到段错误之后,怎么处理?
一般段错误都是与指针指向有关,找到段错误准确那一行就打印对应指针的值。

4、void* 通用类型的指针?

1)void *指向一个什么类型的数据?是指向一个void型变量吗?
例子:

void a; -> 没有void型变量

void *p = &a;

void b = *p;

void *类型指针代表该指针指向任何类型,而且C语言没有void型变量。

2)把特定类型赋值给void *代表含义?
int a; --> 买了一个商场(int)

int p = &a; --> p装者商场的地址 p的数据类型是 商场(int*)

void *pa = p; --> p的地址赋值给pa,pa是void *类型,pa可以指向任何类型的数据

含义:本身p已知指向int类型,赋值给pa,pa还是指向那片区域,但是那片区域是什么类型的数据,就不知道了!
3)把void *赋值给特定类型含义?
int a; --> 买了一个商场(int)

int p = &a; --> p装者商场的地址 p的数据类型是 商场(int*)

void *pa = p; --> p的地址赋值给pa,pa是void *类型&

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值