目录
一维数组
二维数组
传递数组给函数
方式 1
方式 2
方式 3
实例
二维数组传递给函数
方法1: 第一维的长度可以不指定,但必须指定第二维的长度:
方法2: 指向一个有5个元素一维数组的指针:
方法3: 利用数组是顺序存储的特性,通过降维来访问原数组!
实例
从函数返回数组
概述: 数组是一种数据结构,用于存储相同类型的元素。数组名实际上是一个指向其第一个元素的指针。
声明数组:
要声明一个数组,你需要指定数组的类型、数组的名称以及数组的大小。例如:
int arr[5]; // 声明一个名为arr的整型数组,大小为5
初始化数组:
1. 在声明数组的同时初始化它:
int arr[5] = {1, 2, 3, 4, 5}; // 初始化一个整型数组
2. 只给部分元素赋值,只给前面部分元素赋值,其余未赋值的默认赋0。
int a[10]={12, 19, 22 , 993, 344};
int b[10] = {0}; // 所有元素都为0
组名本身是一个常量指针,意味着它的值是不能被改变的,一旦确定,就不能再指向其他地方。 使用数组名作为常量指针是合法的,反之亦然。因此,*(balance + 4) 是一种访问 balance[4] 数据的合法方式。
double balance[10];
// balance 是一个指向 &balance[0] 的指针,即数组 balance 的第一个元素的地址。
// 因此,下面的程序片段把 p 赋值为 balance 的第一个元素的地址:
double *p;
double balance[10];
p = balance;
一旦把第一个元素的地址存储在 p 中,就可以使用 p、(p+1)、*(p+2) 等来访问数组元素。
int array = [1,2,3]; // 定义数组
array[0] == *array == 1; // 数组名表示数组第一个元素地址
array[1] == *(array + 1) == 2; // 加一表示第二个元素地址
array[2] == *(array + 2) == 3; // 加二表示第三个元素地址
获取数组长度
数组长度可以使用 sizeof 运算符来获取数组的长度,例如:
int numbers[] = {1, 2, 3, 4, 5};
int length = sizeof(numbers) / sizeof(numbers[0]);
// 数组的总字节数 / 数组第一个元素的字节 = 数组的长度
在 C 语言中,数组名表示数组首元素的地址。当我们在声明和定义一个数组时,该数组名就代表着该数组的地址。
int myArray[5] = {10, 20, 30, 40, 50};
int *ptr = &myArray[0]; // 或者直接写作 int *ptr = myArray;
在上面的例子中,ptr 指针变量被初始化为 myArray 的地址,即数组的第一个元素的地址。
需要注意的是,虽然数组名表示数组的地址,但在大多数情况下,数组名会自动转换为指向数组首元素的指针。这意味着我们可以直接将数组名用于指针运算,例如在函数传递参数或遍历数组时:
void printArray(int arr[], int size) // 等价于 int *arr
{
for (int i = 0; i < size; i++)
{
printf("%d ", arr[i]); // 数组名arr被当作指针使用
}
}
int main()
{
int myArray[5] = {10, 20, 30, 40, 50};
printArray(myArray, 5); // 将数组名传递给函数 地址传递
return 0;
}
在上述代码中,printArray 函数接受一个整数数组和数组大小作为参数,我们将 myArray 数组名传递给函数,函数内部可以像使用指针一样使用 arr 数组名。
字符数组
字符数组通常用于存储字符串。字符串在C语言中通常以空字符'\0'结尾。例如:
char str[] = "Hello"; // 声明并初始化一个字符数组(字符串)
// 会在后面自动补上 /0
使用
sizeof
来计算str
数组的大小(以字节为单位)会返回6,因为整个数组包括一个额外的字符'\0'来表示字符串的结束。如果你要计算字符数组(字符串)中的元素个数,可以使用
sizeof(str) /sizeof(str[0])
,也会返回6,因为每个字符占用一个字节,而整个数组有6个字符(包括结束符'\0')。
多维数组最简单的形式是二维数组。一个二维数组,在本质上,是一个一维数组的列表。
声明一个 x 行 y 列的二维整型数组,形式如下:
type arrayName [ x ][ y ];
其中,type 可以是任意有效的 C 数据类型,arrayName 是一个有效的 C 标识符。一个二维数组可以被认为是一个带有 x 行和 y 列的表格。下面是一个二维数组,包含 3 行和 4 列:
int x[3][4];
int a[3][4] = {
{0, 1, 2, 3} , /* 初始化索引号为 0 的行 */
{4, 5, 6, 7} , /* 初始化索引号为 1 的行 */
{8, 9, 10, 11} /* 初始化索引号为 2 的行 */
};
因此,数组中的每个元素是使用形式为 a[ i , j ] 的元素名称来标识的,其中 a 是数组名称,i 和 j 是唯一标识 a 中每个元素的下标。
int a[3][4] = {{0}};
二维数组存放字符串,读取时当一维数组使用。比如:
#include
int main()
{
char names[3][10] = {"John", "Mark", "Sarah"};
for (int i = 0; i < 3; i++)
{
printf("Name: %s\n", names[i]);
}
return 0;
}
结果
Name: John
Name: Mark
Name: Sarah
形式参数是一个指针:优先使用此方法
void myFunction(int *param)
{
. . .
}
形式参数是一个已定义大小的数组: 若传递的数组大于形参定义的大小时,编译器不会报警。但是在函数内部,我们应该小心使用 param
,以确保我们不会超出定义的大小访问数组元素。如果 myFunction
尝试访问超出定义大小的元素,那将导致未定义行为。
void myFunction(int param[10])
{
. . .
}
形式参数是一个未定义大小的数组:
void myFunction(int param[])
{
. . .
}
#include
/* 函数声明 */
double getAverage(int arr[], int size);
int main ()
{
/* 带有 5 个元素的整型数组 */
int balance[5] = {1000, 2, 3, 17, 50};
double avg;
/* 传递一个指向数组的指针作为参数 */
avg = getAverage( balance, 5 ) ;
/* 输出返回值 */
printf( "平均值是: %f ", avg );
return 0;
}
double getAverage(int arr[], int size)
{
int i;
double avg;
double sum=0;
for (i = 0; i < size; ++i)
{
sum += arr[i];
}
avg = sum / size;
return avg;
}
结果
平均值是: 214.400000
void print_a(int a[][5], int n, int m) //n,m 为数组的行与列
void print_b(int (*a)[5], int n, int m) //n,m 为数组的行与列
void print_c(int *a, int n, int m) //n,m 为数组的行与列
#include
/*********************************
* 方法1: 第一维的长度可以不指定
* 但必须指定第二维的长度
*********************************/
void print_a(int a[][5], int n, int m){
int i, j;
for(i = 0; i < n; i++) {
for(j = 0; j < m; j++)
printf("%d ", a[i][j]);
printf("\n");
}
}
/*****************************************
* 方法2: 指向一个有5个元素一维数组的指针
*****************************************/
void print_b(int (*a)[5], int n, int m) {
int i, j;
for(i = 0; i < n; i++) {
for(j = 0; j < m; j++)
printf("%d ", a[i][j]);
printf("\n");
}
}
/***********************************
* 方法3: 利用数组是顺序存储的特性,
* 通过降维来访问原数组!
***********************************/
void print_c(int *a, int n, int m) {
int i, j;
for(i = 0; i < n; i++) {
for(j = 0; j < m; j++)
printf("%d ", *(a + i*m + j));
printf("\n");
}
}
int main(void)
{
int a[5][5] = {{1, 2}, {3, 4, 5}, {6}, {7}, {0, 8}};
// 注意数组并未全部赋初值 为赋初值的元素默认为0
// 1 2 0 0 0
// 3 4 5 0 0
// 6 0 0 0 0
// 7 0 0 0 0
// 0 8 0 0 0
printf("\n方法1:\n");
print_a(a, 5, 5);
printf("\n方法2:\n");
print_b(a, 5, 5);
printf("\n方法3:\n");
print_c(&a[0][0], 5, 5); //传递第一个元素的地址
return 0;
}
数组用作函数入参时,最好带上其长度。
sizeof求数组的长度结果时 ,不能在入参后求,也不能在入参时求。因为数组形参此时被默认转换为指针类型,此时求得的结果为指针类型的空间大小。
// 在函数参数声明中,使用了数组形式的参数 int a[],但实际上在函数内部,参数 a 被默认转换为指针类型 int*。
// 因此,对于 sizeof(a) 的求值,实际上是对指针类型的大小求值,而不是数组的大小。
// 下面代码编译器报错但可分析 //
void getSize(int a[]) //这里int a[] 可替换为int *a效果一样
{
int i;
i=sizeof(a);// 这里的i是4,是int *的大小,不管你传入的a有几个元素
int b;
b=sizeof(a)/sizeof(a[0]);// 逻辑没错,a的大小除以元素的大小得到长度,可是sizeof(a)并不是数组占的空间,而是指针,也就是i
}
int main()
{
int a[]={1,2,3,4,5};
getSize(a); // 传递数组名 即数组地址
}
//
// 正确做法应在传递前 把数组长度计算出来 //
/
void getSize(int a[],int size)
{
int k = size;// 已经保存入参大小
// 遍历或者其他操作
}
int main()
{
int a[]={1,2,3,4,5};
// 此时a并不是入参,sizeof可以得到开发人员想要的结果
int size = sizeof(a)/sizeof(a[0]);
getSize(a,size);
}
使用约定一个结束标记的方法来确定数组的元素个数如下
// 在定义数组时,在数组的最后一个元素后面添加一个特殊的结束标记,例如 -1 或 0。
// 假设有一个整型数组 arr,可以定义为 int arr[] = {1, 2, 3, 4, 5, -1};。
// 在函数内部,使用循环来遍历数组。当遇到结束标记时,停止循环。
void getSize(int a[])
{
int i = 0;
while (a[i] != -1) // 当遇到 -1时循环条件不满足 跳出循环
{
i++;
}
// 现在,变量 i 的值就是数组的元素个数
printf("数组的元素个数:%d\n", i);
}
C 不支持在函数外返回局部变量的地址,除非定义局部变量为 static 变量。
因为当函数执行完毕后,局部变量被销毁并释放其内存空间,因此不能保证在函数返回后局部变量的地址仍然有效。具体来说,当你在一个 C 函数内部声明一个局部变量时,该变量只在函数执行期间存在,并在函数结束时被销毁。这意味着你不能在函数外部使用该变量的地址或引用。
若要在外部引用则要定义为static变量。
int* getLocalVariableAddress()
{
int x = 10; // 在函数内部声明的局部变量
return &x; // 错误:尝试返回局部变量的地址
}
int main()
{
int* ptr = getLocalVariableAddress(); // 错误:尝试使用函数内部局部变量的地址
// ...
return 0;
}
C 语言不允许返回一个完整的数组作为函数的参数。但是,可以通过指定不带索引的数组名来返回一个指向数组的指针。
如果想要从函数返回一个一维数组,必须声明一个返回指针的函数,如下:
int * myFunction() // 此函数可返回指针
{
....
}
#include
#include
#include
/* 要生成和返回随机数的函数 */
int * getRandom( )
{
static int r[10];// 定义静态数组 若不定义为静态则在执行完函数销毁 因此不能返回地址
int i; // 定义循环变量i
/* 设置种子 */
srand( (unsigned)time( NULL ) );
for ( i = 0; i < 10; ++i)
{
r[i] = rand(); // 把生成的随机数存放到数组中
printf( "r[%d] = %d\n", i, r[i]); // 打印每个生成的随机数
}
return r; // 把数组名作为返回值 返回其数组地址
}
/* 要调用上面定义函数的主函数 */
int main ()
{
/* 一个指向整数的指针 */
int *p;
int i;
p = getRandom(); // 接收返回的地址
for ( i = 0; i < 10; i++ )
{
printf( "*(p + %d) : %d\n", i, *(p + i));
}
return 0;
}
结果
r[0] = 313959809
r[1] = 1759055877
r[2] = 1113101911
r[3] = 2133832223
r[4] = 2073354073
r[5] = 167288147
r[6] = 1827471542
r[7] = 834791014
r[8] = 1901409888
r[9] = 1990469526
*(p + 0) : 313959809
*(p + 1) : 1759055877
*(p + 2) : 1113101911
*(p + 3) : 2133832223
*(p + 4) : 2073354073
*(p + 5) : 167288147
*(p + 6) : 1827471542
*(p + 7) : 834791014
*(p + 8) : 1901409888
*(p + 9) : 1990469526
上一篇:C语言运算符
下一篇: