注:本文是对苏小红版c语言程序设计第11章的笔记
- 数组名代表数组元素的连续存储空间的首地址,即指向数组中的第一个元素的指针常量。e.g.: a <=>&a[0], *(a + i) <=>a[i]
不能对数组名执行增1或减1的操作(a是指针常量) - p + 1 和p++本质上是不同的操作:虽然二者都对指针变量p进行加1运算,但p+1不改变指针的指向,而p++相当于执行p = p + 1
- p++加上的是1*sizeof(基类型)
- 行指针:a[i][j] <–>* (a[i] + j) <–>* (* (a + i) + j) <–> *(a + i)[j]
二维数组中a[i]可以看成由a[i][1]…a[i][n]构成的一维数组的数组名,代表数组的首地址 - 列指针:a[i][j] <–>*(p+i * n+j) <–>p[i * n + j]
- 对比以下三种函数参数:
void input(int a[][N], int m, int n);//二位数组作函数参数
void input(int (*a)[N], int m, int n);//二位数组行指针作参数
void input(int *a, int m, int n);//二维数组列指针作参数
- 指针数组:元素是指向同一类型元素的指针,最主要用途之一就是对多个字符串进程处理操作
使用前必须进行初始化 - 物理排序:改变字符串在实际物理存储空间中的存放位置
索引排序:通过移动字符串索引地址实现,只改变指针数组中各元素指向。
9.* 命令行参数:
#include <stdio.h>
int main(int argc, char *argv[])//argc:命令行中参数个数 agrv:接收命令行参数
{
int i;
printf("The number of command line arguments is %d\n.", argc);
printf("The program name is :%s\n", argv[0]);
if(argc > 1)
{
printf("The other arguments are as following:\n");
for(i = 1; i < argc; i++)
{
printf("%s\n", argv[i]);
}
}
return 0;
}
-
c中变量的分配:
从静态存储区分配(编译时分配,终止前收回):
全局变量和静态变量
在栈上分配:
效率高,容量有限,可能出现栈溢出从而使程序运行失败
从堆上分配:
动态内存申请的内存
生存期由程序员决定,使用灵活,容易出现内存泄漏等问题
必须及时free()已不再适用的内存 -
动态内存分配函数
malloc():void *malloc (unsigned int size);
...
int *pi = NULL;
pi = (int *)malloc(sizeof(int));//用强转的方法将返回的指针值转为所需类型, 适用sizeof有利于提高可移植性
calloc():用于给若干同类型数据项分配两虚的存储空间并赋值为0
原型:void *calloc(unsigned int num, unsigned int size);
float *pf = NULL;
pf = (float*)calloc(10, sizeof(float));
free(): void free(void *p);
realloc():void realloc(void *p, unsigned int size);
用于改变原来分配的存储空间的大小, 返回值是新分配的存储空间的首地址,与原来分配的首地址不一定相同。
- 常见错误:
内存未分配成功就适用
内存分配成功了,但未初始化就适用
内存分配成功了, 也初始化了,但发生了越界使用
忘记了释放内存,造成内存泄漏
释放内存后仍然继续使用(使用野指针) - 野指针形成的主要原因:
指针操作超越了变量的作用范围
指针变量未被初始化
指针变量所指向的动态内存被free后未置为NULL
解决对策:
不把局部变量的地址(指向“栈内存”的指针)作为函数的返回值返回
在定义指针变量的同时对其初始化,要么设置为NULL,要么使其指向合法内存
尽量把malloc()集中在函数的入口处,free()集中在函数的出口处