人生中第一篇博客,写这篇博客的目的主要是为了把编程中自己的所思所想所感记下来,毕竟好记性不如烂笔头,就算写到注释里,过后半年,也不一定能再找到那段代码去看。
数组作为C语言里非常常用的数据结构,有很多需要注意的地方:
数组特点
个人理解,数组说白了就是指向该数组第一个元素的指针,数组定义就是开辟一片一定大小(由程序员决定)的内存空间,数组名就是那片空间的起始地址,所以数组能通过指针来访问便没有疑问了。num[i]与*(num+i)其实是一个意思。二维以及多维数组一样适用,只不过需要对数组理解有一定深度之后才能手到擒来。数组定义
数组定义时只需注意一件事就行了,不能用变量
const int n = 5;
int a[N];//合法,此处N是通过#define定义的常量,值为5
int a[n];//不合法,因为const定义的变量放在静态存储区,理论上也是可变的
int num[5] = { 1, 2, 3 };//给出的元素数量不足,后面补0
double num[5] = { 1, 2, 3 };//会自动进行类型转换,若输出,结果为1.0000之类的,忘了几个0了
int num[] = { 1, 2, 3 };//此处给三个元素,数组占12个字节
- 字符数组与字符串
由于C语言里并没定义C++里有的String类,所以字符串一般通过定义字符数组形式来实现,但是初学者刚开始一般都会犯这样一个错误:
char str[5] = { 'h', 'e', 'l', 'l', 'o' };
char str[7] = "notepad";
这样子拿去输出的话,就会有好玩的事情发生了,烫烫烫烫烫……就出来了,为什么呢,因为认定字符串的结束是以'\0'为标志,上面的字符串结尾并没有这个标志,所以就会一直输出一直向后找,直到找到'\0'为止,其实你如果像这样定义,编译器会自动帮你加结束标志的
char str[6] = { 'h', 'e', 'l', 'l', 'o' };
char str[8] = "notepad";
有什么变化呢,多分配了一个字节的内存空间,这样编译器就会自动帮你加上结束标志'\0'。
还有一点,scanf为字符串数组赋值时会自动在字符串结尾加'\0',而且可以突破数组定义时的长度,但可能会发生异常,所以不建议。
- 数组传递
数组作为参数在函数间传递是很常见的,但是需要注意一点,数组名是作为一个地址传给函数的,所以如果用sizeof判断传入的数组大小时,得到的只是一个地址所占的内存空间,一般是4个字节(32位)。 - 二维及多维数组
如果用指针访问二维或多维数组的话,就需要了解多维数组的含义。如果定义一个二维数组
int a[5][10];
那么这个二维数组就是5个一维数组的集合,每个元素都是a[10]。如果把这个二维数组看做矩阵的话,就是一个5行10列的矩阵。前面说*(a+i)
即表示a[i],所以对于上面的二维数组而言,*(a+2)
即表示整个第三行,第三行有10个元素,若要再访问其中第5个元素其中之一便可以这么写*(*(a+2)+4)
**总结下,想访问第i行第j列数据,就这么写 ***(*(a+i-1)+j-1)
下面是一个示例程序
#include<stdio.h>
#include<stdlib.h>
#define N 10
void main()
{
int num[N][N];
for (int i = 0; i < N; i++)
{
for (int j = 0; j < N; j++)
{
num[i][j] = N*i + j + 1;
printf("%-5d", *(*(num + i) + j));
}
printf("\n");
}
system("pause");
}