程序设计基础
Posted 海林的菜园子
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了程序设计基础相关的知识,希望对你有一定的参考价值。
变量与指针
变量
数的表示形式
数据的输入与输出
指针变量与指针的指针
简化表达式
共性与可变性的分析
数组与指针
数组的数组与指针
数组的数组--二维数组
二维数组int data[2][3] = {{1,2,3},{4,5,6}};
,可以用下面的表格来描述
data
是由data[0]
,data[1]
这两个元素构成的一维数组。
data[0]
是由data[0][0],data[0][1],data[0][2]
三个元素构成的一维数组。
data[1]
是由data[1][0],data[1][1],data[1][2]
三个元素构成的一维数组。
请注意,以下是精彩段落
由于表达式中的数组名可以被解释为指针.
data
是指向data[0]
的指针
data == &data[0]
*data == data[0]
data[0]
是指向data[0][0]
的指针
data[0] == &data[0][0]
*data[0] == data[0][0]
故有
data == &data[0] == &(&data[0][0])
*data == data[0] == &data[0][0]
**data == data[0][0]
练习
若有定义int a[2][3] = {{1},{2,3}}
,则 a[1][0]
的值是多少
分析:
二维数组是基于一维数组变化而来了,我们可以将题目中的数据拆成一维数组来分析
int a0[3] = {1};
int a1[3] = {2,3};
故由此可知,题目答案为 2
数组的指针
按照变量的声明规则,将data取出后,余下的就是data数据类型。这是开发编译器时约定的。
对一维数组int test[2]
,int [2]
就是test
的数据类型,test
是指向int
的指针,即int *
对于二维数组int a[2][3]
,int [2][3]
就是a
的数据类型。
a[0] a[1]
的数据类型是int [3]
a
是指向a[0]
的指针,而a[0]
的数据类型是int [3]
,即a
是指向int [3]
的指针,即 int (*)[3]
将二维数组作为函数参数
方法一
int sum (int data[][2], int size);
方法二
int sum(int (*pdata)[2], int size);
用法
int data[3][2] = {{1,2},{3,4},{5,6}};
int total = sum(data, 3);
对二维数组的常用操作
获取二维数组的相关数据
sizeof(data)
整个二维数组的空间大小
sizeof(data[0])
一行元素的空间大小
sizeof(data[0][0])
单个元素的空间大小
sizeof(data)/sizeof(data[0])
行数
sizeof(data[0])/sizeof(data[0][0])
列数
sizeof(data)/sizeof(data[0][0])
元素个数
找到二维数组中的最大元素
可以将二维数组转为一维数组来进行搜索
int max(int *pdata, int size);
用法
int data[3][2] = {{1,2},{3,4},{5,6}};
int n = sizeof(data)/sizeof(data[0][0]);
int max = max((int *)data, n);
清空二维数组
memset(data, 0, sizeof(data));
对二维数组的某一行进行清0
memset(data[row], 0, sizeof(data[0]));
对二维数组的某一列进行清0
由于数组是按行而不按列存储,因此操作二维数组中的列元素就相对复杂一些。
下面是对数组data的第i列清0
int data[row][col],(*pData)[col],i;
for(pData = &data[0];pData < &data[row];pData++)
(*pData)[i] = 0; //对某行的i列的元素清零
or
int data[row][col],i
for(int r = 0; r < row; r ++)
data[r][i] = 0; //对r行i列的元素清零
字符串与指针
动态分配内存
程序在运行时请求内存,被分配的空间称之为HEAP,虽然计算机在硬件上不直接支持HEAP,但是C函数库(stdlib.h)提供了申请与释放的函数,在运行时根据需要申请内存空间,在不需要时释放。
malloc()
void *malloc(unsigned int size);
void *表示函数返回值是一个指针,从C99开始,void *类型指针可以赋值给摺有类型的指针变量
size 为所需内存的字节数
eg.
int *pi = malloc(sizeof(int));
if (NULL != pi)
{
//成功申请到内存
}
else
{
//没有申请到内存
}
calloc()
比malloc()函数更好用函数
void *calloc (size_t nmeb, size_t size);
为nmeb个元素的数组分配内存,每个元素的大小为size 字节。在内存分配成功后,会将这片内存全部清0。
如,申请n个整数的数组,并初始化为0
pi = calloc(n,sizeof(int));
技巧:将calloc函数的第一个参数输入“1”,就可以为任何类型的数据项分配空间。
申请一块类型空间,同时清为0
struct point {int x,y;} *pi;
pi = calloc(1, sizeof(struct point));
realloc()
在原有分配的内存基础上,扩充内存。
void *realloc(void *pointer, unsigned int size);
alloc是allocate分配的缩写,前缀re是重新分配的意思。
如果原内存后面还有足够空闲内存的话,realloc()只是修改分配表,还是返回原内存地址;
如果没有足够空闲内存,realloc()会申请新的内存,然后将原内存的数据复制到新内存中,原内存将被free()掉,realloc()返回新的内存地址。
比如,有5个int型元素的数组变量需要分配内存
int *pi = malloc(5*sizeof(int));
但是在使用时发现,申请的空间不够了,需要10个才够用,那么需要先释放内存,然后再申请新的内存。
free(pi);
pi = malloc(10*sizeof(int));
为了保留原来的数据,需要再做一些工作
int *temp = pi; //让temp 指向原内存
pi = malloc(10*sizeof(int)); 让pi指向新内存
memcpy(pi,temp,5*sizeof(int)); 将原内存的数据复制到新内存
free(temp); //释放原内存
但上面的工作也可以由下面的一句话来完成
pi = realloc(pi,10*sizeof(int))
free()
通常内存申请与释放配对使用,当申请的内存使用完毕后,如果不及时释放掉,就会导致可用内存空间减少,也就是内存泄露,进而影响程序的正常运行。
void free(void *pointer);
悬空指针的出现
char *pi = malloc(5);
free(pi); //释放掉pi所指向的内存块,但是pi依旧指向这块空间,此时的pi被称为悬空指针
strcpy(pi,"abc"); //错误
更好的方法
由于free()函数不会检查传入的参数是否为NULL,也不会返回前将指针设置为NULL,因此为了安全起见,要创建自己的free函数。
如
void safer_free(void **pp)
{
if (pp != NULL && *pp != NULL)
{
free(*pp);
*pp = NULL;
}
}
为了简化使用,可以将其定义成宏,可以省略类型转换和传递指针的地址
#define SAFER_FREE(p) safer_free((void **)&p)
其调用形式如下:
int pi = malloc(sizeof(int));
SAFER_FREE(pi);
以上是关于程序设计基础的主要内容,如果未能解决你的问题,请参考以下文章
20155201 李卓雯 《网络对抗技术》实验一 逆向及Bof基础