嵌入式开发学习———Linux环境下C语言学习(八)
指针与数组的关系中,数组名是首元素地址常量,可通过指针遍历数组;数组指针指向整个数组,常用于多维操作,而指针数组存储指针,适合管理字符串。区别在于数组名为常量指针,指针为变量,数组指针以数组为单位移动,指针数组元素需单独管理。内存管理分为静态内存、栈内存(自动管理但容量有限)和堆内存(需手动分配释放,如malloc/calloc与free配对)。常见问题包括内存泄漏、野指针和越界访问,建议释放后置
指针与数组的关系
在C语言中,指针与数组紧密相关。数组名本质上是数组首元素的地址常量,而指针是存储地址的变量。通过指针可以遍历或操作数组元素,例如:
int arr[3] = {1, 2, 3};
int *p = arr; // p指向arr首元素
printf("%d", *(p + 1)); // 输出arr[1]的值2
指针算术允许通过增减指针值访问数组后续或前置元素。
数组指针(指向数组的指针)
数组指针指向整个数组而非单个元素,其声明需指定数组大小。常用于多维数组操作:
int arr[2][3] = {{1, 2, 3}, {4, 5, 6}};
int (*p)[3] = arr; // p指向包含3个元素的数组
printf("%d", p[1][2]); // 输出6(访问第二行第三列)
p的类型是“指向含有3个整数的数组的指针”,步长以整个一维数组为单位。
指针数组(存储指针的数组)
指针数组是元素为指针的数组,常用于管理多个字符串或动态内存:
char *names[3] = {"Alice", "Bob", "Charlie"}; // 每个元素是char*指针
for (int i = 0; i < 3; i++) {
printf("%s\n", names[i]); // 输出字符串
}
每个元素names[i]指向独立的字符串常量,内存布局分散。
关键区别总结
-
指针与数组:数组名是常量指针,指针是变量,可重新赋值。
-
数组指针:指向整个数组,步长由数组大小决定。
-
指针数组:数组元素是指针,需单独分配或指向数据。
通过理解这三者的内存模型和操作方式,可以灵活应用于动态内存、函数参数传递等场景。
指针与数组的关系
在C语言中,指针与数组紧密相关。数组名本质上是数组首元素的地址常量,而指针是存储地址的变量。通过指针可以遍历或操作数组元素,例如:
int arr[3] = {1, 2, 3};
int *p = arr; // p指向arr首元素
printf("%d", *(p + 1)); // 输出arr[1]的值2
指针算术允许通过增减指针值访问数组后续或前置元素。
数组指针(指向数组的指针)
数组指针指向整个数组而非单个元素,其声明需指定数组大小。常用于多维数组操作:
int arr[2][3] = {{1, 2, 3}, {4, 5, 6}};
int (*p)[3] = arr; // p指向包含3个元素的数组
printf("%d", p[1][2]); // 输出6(访问第二行第三列)
p的类型是“指向含有3个整数的数组的指针”,步长以整个一维数组为单位。
指针数组(存储指针的数组)
指针数组是元素为指针的数组,常用于管理多个字符串或动态内存:
char *names[3] = {"Alice", "Bob", "Charlie"}; // 每个元素是char*指针
for (int i = 0; i < 3; i++) {
printf("%s\n", names[i]); // 输出字符串
}
每个元素names[i]指向独立的字符串常量,内存布局分散。
关键区别总结
-
指针与数组:数组名是常量指针,指针是变量,可重新赋值。
-
数组指针:指向整个数组,步长由数组大小决定。
-
指针数组:数组元素是指针,需单独分配或指向数据。
通过理解这三者的内存模型和操作方式,可以灵活应用于动态内存、函数参数传递等场景。
C语言内存管理概述
C语言的内存管理主要涉及程序运行时内存的分配、使用和释放,分为静态内存、栈内存和堆内存三种方式。程序需手动管理堆内存,避免内存泄漏或非法访问。
静态内存分配
在编译时确定内存大小,生命周期贯穿整个程序运行期。
- 全局变量:存储在静态区,程序启动时分配,结束时释放。
int global_var; // 全局变量 - 静态局部变量:使用
static关键字,作用域限于函数内,但生命周期与全局变量相同。void func() { static int count = 0; // 静态局部变量 }
栈内存分配
由编译器自动管理,用于局部变量和函数调用。
-
特点:内存分配/释放速度快,但容量有限(通常几MB)。
- 示例:
void foo() { int stack_var; // 栈内存分配 } -
注意:栈内存随函数结束自动释放,不可返回指向栈内存的指针。
堆内存分配
需手动管理,通过malloc、calloc、realloc和free操作。
malloc:分配指定字节的未初始化内存。int *arr = (int*)malloc(10 * sizeof(int)); // 分配10个int的空间free:释放内存,避免泄漏。free(arr); // 释放内存 arr = NULL; // 避免野指针
常见问题与建议
-
内存泄漏:未释放堆内存导致资源浪费。需配对使用
malloc/calloc和free。 -
野指针:释放后未置空指针,可能引发非法访问。释放后立即赋
NULL。 -
越界访问:操作超出分配的内存范围。确保索引在合法区间内。
-
碎片化:频繁分配/释放小块内存可能导致碎片。合理规划内存使用。
C语言内存管理概述
C语言的内存管理主要涉及程序运行时内存的分配、使用和释放,分为静态内存、栈内存和堆内存三种方式。程序需手动管理堆内存,避免内存泄漏或非法访问。
静态内存分配
在编译时确定内存大小,生命周期贯穿整个程序运行期。
- 全局变量:存储在静态区,程序启动时分配,结束时释放。
int global_var; // 全局变量 - 静态局部变量:使用
static关键字,作用域限于函数内,但生命周期与全局变量相同。void func() { static int count = 0; // 静态局部变量 }
栈内存分配
由编译器自动管理,用于局部变量和函数调用。
-
特点:内存分配/释放速度快,但容量有限(通常几MB)。
- 示例:
void foo() { int stack_var; // 栈内存分配 } -
注意:栈内存随函数结束自动释放,不可返回指向栈内存的指针。
堆内存分配
需手动管理,通过malloc、calloc、realloc和free操作。
malloc:分配指定字节的未初始化内存。int *arr = (int*)malloc(10 * sizeof(int)); // 分配10个int的空间calloc:分配并初始化内存为零。int *arr = (int*)calloc(10, sizeof(int)); // 分配且初始化为0realloc:调整已分配内存的大小。arr = (int*)realloc(arr, 20 * sizeof(int)); // 扩展至20个intfree:释放内存,避免泄漏。free(arr); // 释放内存 arr = NULL; // 避免野指针
常见问题与建议
-
内存泄漏:未释放堆内存导致资源浪费。需配对使用
malloc/calloc和free。 -
野指针:释放后未置空指针,可能引发非法访问。释放后立即赋
NULL。 -
越界访问:操作超出分配的内存范围。确保索引在合法区间内。
-
碎片化:频繁分配/释放小块内存可能导致碎片。合理规划内存使用。

作业 :
1.用指针实现二维数组的冒泡排序
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
int main(int argc, const char *argv[])
{
int arr[3][4]={1,0,2,5,11,7,4,6,9,8,3,12};
int (*ptr)[4]=NULL;
int i,j,temp;
ptr=arr;
for(i=0;i<12-1;i++)
for(j=0;j<12-i-1;j++)
if(*(ptr[0]+j)>*(ptr[0]+j+1))
{
temp=*(ptr[0]+j);
*(ptr[0]+j)=*(ptr[0]+j+1);
*(ptr[0]+j+1)=temp;
}
for(i=0;i<12;i++)
printf("%-2d ",*(ptr[0]+i));
putchar(10);
return 0;
}
运行结果:
openvela 操作系统专为 AIoT 领域量身定制,以轻量化、标准兼容、安全性和高度可扩展性为核心特点。openvela 以其卓越的技术优势,已成为众多物联网设备和 AI 硬件的技术首选,涵盖了智能手表、运动手环、智能音箱、耳机、智能家居设备以及机器人等多个领域。
更多推荐



所有评论(0)