龙空技术网

Linux C 编程 - 数组

大话幽默一刻 209

前言:

今天看官们对“c定义array”大约比较关切,同学们都需要知道一些“c定义array”的相关资讯。那么小编也在网上网罗了一些对于“c定义array””的相关知识,希望各位老铁们能喜欢,同学们快快来学习一下吧!

数组(Array)是一种复合数据类型,它由一系列相同类型的元素组成。例如定义一个由4个int型元素组成的数组count:

int count[4];

和结构体成员类似,数组count的4个元素的存储空间也是相邻的。结构体成员可以是基本数据类型,也可以是复合数据类型,数组中的元素也是如此。根据组合类型,我们可以定义一个由4个结构体元素组成的数组:

struct complex_struct{  double a;  double b;} a[4];

也可以定义一个包含数组成员的结构体:

struct complex_struct{ 	double a;  double b;  int count[4]} s;

数组类型的长度应该用一个整数常量表达式来指定,数组中的元素通过下标(index)来访问。

整个数组占了4个int型的存储单元,存储单元用小方框表示,里面的数字是存储在这个单元中的数据,而框外面的数字是下标,这四个单元分别用count[0], count[1], count[2], count[3]来访问。注意,在定义数组int count[4]; 方括号中的数字4表示数组的长度,而在访问数组时,方括号中的数字表示访问数组的第几个元素。数组元素是从"第0个"开始数的,这样规定使得访问数组元素非常方便,比如count数组中的每个元素占4个字节,则count[i]表示从数组开头跳过4*i个字节之后的那个存储单元。这种数组下标的表达式不仅可以表示存储单元中的值,也可以表示存储单元本身,也就是说可以做左值,因此以下语句都是正确的:

#include <stdio.h>int main(void){  int count[4] = {1, 2, 3, 4};  printf("==>UDEBUG count[%d] = %d\n", 0, count[0]);  count[0] = 11;  printf("==>UDEBUG count[%d] = %d\n", 0, count[0]);  count[0] = count[0]*2;  printf("==>UDEBUG count[%d] = %d\n", 0, count[0]);  ++count[0];  printf("==>UDEBUG count[%d] = %d\n", 0, count[0]);  return 0;}

使用数组下标不能超出数组的长度范围,这一点在使用变量做数组下标时尤其要注意。C 编译器并不检查count[-1]或是count[100]这样的访问越界错误,编译时能顺利通过,所以属于运行时错误。

数组也可以像结构体一样初始化,没有赋初值的元素也是用0来初始化,例如:

int count[4] = {3, 2, };

则count[0] 等于 3, count[1] 等于2, 后面两个元素等于0。如果定义数组的同时初始化它,也可以不指定数组的长度,例如:

int count[ ] = {3, 2, 1, };

编译器会根据初始化有三个元素确定数组的长度为3。

1.定义和访问数组

#include <stdio.h>int main(void){  unsigned int i = 0;  unsigned int arrayLen = 0;  int count[4] = {1, 2, 3, 4};  arrayLen = sizeof(count)/sizeof(int);  for (i = 0; i < arrayLen; i++)  {    printf("==>UDEBUG count[%d] = %d\n", i, count[i]);  }  return 0;}

数组和结构体虽然有很多相似之处,但也有一个显著的不同:数组不能相互赋值或初始化。例如这样是错的:

int a[5] = {4, 3, 2, 1};int b[5] = a;

2.数组应用实例:统计随机数

C 标准库中生成伪随机数的是rand函数,使用这个函数需要包含头文件stdlib.h, 它没有参数,返回值是一个介于0和RAND_MAX之间的接近均匀分布的整数。RAND_MAX是该头文件中定义的一个常量,在不同的平台上有不同的取值,但可以肯定它是一个非常大的整数。通常我们用到的随机数是限定在某个范围之中的,例如0~9,而不是0~RAND_MAX。

#include <stdio.h>#include <stdlib.h>#define N 20int a[N];void gen_random(int upper_bound){  int i = 0;  for (i = 0; i < N; i++)  {    a[i] = rand() % upper_bound;  }}void print_random(){  int i = 0;  for (i = 0; i < N; i++)  {    printf("%d ", a[i]);  }  printf("\n");}int main(void){  gen_random(10);  print_random();  return 0;}

用#define 定义一个常量,实际上编译的工作分为两个阶段,先是预处理阶段,然后才是编译阶段。预处理做了两件事,一是把头文件stdio.h和stdlib.h在代码中展开,二是把#define 定义的标识符N 替换成20。像#include 和 #define 这种以#号开头的被称为预处理指示。define 不仅用于定义常量,也可以定义更复杂的语法结构,称为宏定义。

#include <stdio.h>#include <stdlib.h>#define N 100000int a[N];void gen_random(int upper_bound){  int i;  for (i = 0; i < N; i++)  {    a[i] = rand() % upper_bound;  }}int howmany(int value){  int count = 0;  int i = 0;  for (i = 0; i < N; i++)  {    if (a[i] == value)    {      ++count;    }  }  return count;}int main(void){  int i = 0;  gen_random(10);  printf("value\thow many\n");  for (i = 0; i < 10; i++)  {    printf("%d\t%d\n", i, howmany(i));  }  return 0;}
value   how many0       101301       100722       99903       98424       101745       99306       100597       99548       98919       9958

从结果来看,0~9 各个数字出现的概率都在10000左右,分布比较均匀。

3.字符串

字符串可以看作一个数组,它的每个元素是字符型的,例如字符串“hello, world.\n”

注意每个字符末尾都有一个字符'\0' 做结束符,这里的\0 是ASCII码的八进制表示。数组元素可以通过数组名加下标的方式访问,而字符串字面值也可以像数组名一样使用,可以加下标访问其中的字符。

数组可以像结构体一样初始化,如果是字符数组,也可以用一个字符串字面值来初始化

char str[10] = "Hello";
char str[10] = { 'H', 'e', 'l', 'l', 'o', '\0'};

str的后四个元素没有指定,自动初始化为0,即NULL 字符。注意,虽然字符串字面值"Hello" 是只读的,但用它初始化的数组str确实可读可写的。数组str中保存了一串字符,以'\0'结尾,也可以叫字符串。

如果用于初始化的字符串字面值比数组还长,比如:

char str[10] = "Hello, world.\n";

则数组str只包含字符串的前10个字符,不包含NULL字符,这种情况编译器会给出警告,如果要用一个字符串字面值准确地初始化一个字符数组,最好的办法是不指定数组的长度,让编译器自己计算:

char str[] = "Hello, world.\n";

字符串字面值的长度包括NULL字符在内一共15个字符,编译器会确定数组str的长度为15。

使用printf加%s进行打印:

printf("string: %s\n", str);

printf 会从数组str 的开头一直打印到NULL字符为止。如果数组str 中没有NULL字符,那么printf 函数就会访问数组越界,后果可能会很出乎意料;有时候打印出乱码,有时候看起来没有错误,有时候引起程序崩溃。

标签: #c定义array