S4——数组

news/2024/11/8 17:06:07/

目录

1.  一维数组的创建和初始化

        1.2  一维数组的使用

        1.3  一维数组在内存中的存储

2.  二维数组的创建和初始化

        2.2  二维数组的使用

        2.3  二维数组在内存中的存储

3.  数组越界

4.  数组作为函数参数

        4.1  冒泡排序

        4.2  数组名是什么?


1.  一维数组的创建

1.1  数组的创建

数组是一组相同数据类型元素的集合。

数组的创建方式

type_t    arr_name[const_n];

//type_t:是指数组的元素类型(可以是基本数据类型的任意一种)

//arr_name:数组名(与变量相同,遵循标识符的命名规则)

//const_n:常量表达式(用来表示数组中元素个数,即数组的大小(长度))

注:常量表达式是用[]方括号括起来的,不是()圆括号。

数组创建的实例

代码1:

int  arr1[10];//定义一个有10个整形的一维数组

char  arr2[5];

float  arr3[6];

...

代码2:

int  n=10;

int  arr[n];//这样可以吗?

注:变长数组(不定长的数组)

数组创建,在C99标准之前,[]中要给一个常量才可以,不能使用变量。在C99标准支持了变长数组的概念,数组的大小可以使用变量指定,但是数组不能初始化

理解:

①能否用变长数组:先看环境支不支持C99的新特性

    如:VS   IDE   不支持C99中的变长数组

           Linux  gcc   支持C99中的变长数组

②注意:变长数组不能初始化

1.2  数组的初始化

数组的初始化是指,在创建数组的同时给数组的内容一些(合理)初始值。

即:创建的同时给数组一些值,这就叫初始化(类似变量)

一维数组初始化的一般形式如下

1、完全初始化:(元素个数=数组长度)

①指定数组长度:

int   arr1[6]={0,1,2,3,4,5};//元素个数=数组长度

②不指定数组长度:(没有指定数组长度,编译会根据初始化的内容来确定数组长度)

int   arr2[]={0,1,2,3,4};//数组长度=5

2、不完全初始化:(数组长度!=元素个数)

如:

    ①int型:剩余没赋初值的元素默认初始化为0

    ②char型:剩余的元素默认初始化为‘\0’

注:数组元素之间用,逗号隔开。

注意区分以下代码:

代码1:

#include<stdio.h>
int main()
{char arr1[] = { 'a','b','c'};char arr2[] = "abc";printf("%s\n", arr1);printf("%s\n", arr2);return 0;
}

运行结果:

%s——打印字符串,直到遇到‘\0’才停止。 

每一个字符串末尾隐藏放了个'\0'。

 代码2:

#include<stdio.h>int main()
{char arr1[4] = { 'a','b','c' };char arr2[] = { 'a','b','c' };printf("%s\n", arr1);printf("%s\n", arr1);return 0;
}

运行结果:

注:char未初始化的元素默认'\0' 

1.3  一维数组的使用

知识点:

1、数组是使用下标来访问的,下标是从0开始的(下标标明了元素在数组中的位置)

2、[]在这是下标访问操作符(所以里面可以是变量)

3、数组的大小可以通过计算得到

如:

        int arr[10];

        sz=sizeof(arr)/sizeof(arr[0]);

代码实例如下:

#include<stdio.h>int main()
{int arr[] = { 0,1,2,3,4,5 };int sz = sizeof(arr) / sizeof(arr[0]);//计算元素个数//1、顺序打印int i = 0;//下标for (i = 0; i < sz; i++){printf("%d ", arr[i]);}printf("\n");//逆序打印for (i = sz - 1; i >= 0; i--){printf("%d ", arr[i]);}printf("\n");return 0;
}

运行结果:

说明:

数组的使用与变量相似,但也有区别!

1、数组必须先定义,后使用。

2、数组元素只能逐个引用,而不能一次引用整个数组(字符串除外)。

3、 当逐个使用数组中的每一个元素时,通常借助for循环语句。

1.4  一维数组在内存中的存储

探讨数组在内存中的存储:我们打印每个元素的地址看看

#include<stdio.h>
int main()
{int arr[6] = { 0,1,2,3,4,5 };//打印每一个元素的地址int i = 0;for (i = 0; i < 6; i++){printf("%p\n", &arr[i]);//%p-专门用来打印地址的}return 0;
}

运行结果:

由于数组在内存连续存放,所以我们知道数组的一个地址就可以顺藤摸瓜找到其他元素。

代码如下:

#include<stdio.h>
int main()
{int arr[6] = { 0,1,2,3,4,5 };int * p = &arr[0];int i = 0;for(i=0;i<6;i++){printf("%d ", *(p+i));}return 0;
}

 运行结果:

 2.  二维数组的创建和初始化

2.1  二维数组的创建

//二维数组创建

int  arr[3][4];//定义一个3行4列的整形数组

char  arr1[2][3];

说明:

①二维数组可以看成一个矩阵(先行后列)

②元素个数=行数*列数

③存储一个二维数组所需的内存字节数:

                                 总字节数=sizeof(类型)*行数*列数

2.2  二维数组的初始化

1、按数组的排列顺序对各数组元素赋初值:

    int  arr1[2][3]={1,2,3,4,5,6};

2、分行给二维数组赋初值(一个花括号{}表示一行)

      int  arr2[2][3]={{1,2},{4}};

3、注意:二维数组如果初始化,行是可以省略的,但列不能省略!

       int  arr3[][2]={1,2,3,4,5,6};//元素个数=行数*列数—》行数=3

2.3  二维数组的使用

二维数组的使用也是通过下标的方式(访问)。

说明:

1、行和列的下标也是从0开始的。

2、确定行和列的下标就能找到元素了。

3、注:数组元素只能逐个引用,而不能一次引用整个数组。(for嵌套)

代码实例:

#include<stdio.h>int main()
{int arr[3][4] = { 0,1,2,3,4,5,6,7,8,9,10,11 };//打印3行4列的数组int i = 0;for (i = 0; i < 3; i++){int j = 0;for (j = 0; j < 4; j++){printf("%d ", arr[i][j]);}printf("\n");}return 0;
}

2.4  二维数组在内存中的存储

像一维数组一样,这里我们打印二维数组的每一个元素的地址看看:

#include<stdio.h>int main()
{int arr[3][4] = { 1,2,3,4,5,6,7,8,9,10,11,12 };//打印二维数组每一个元素的地址int i = 0;for (i = 0; i < 3; i++){int j = 0;for (j = 0; j < 4; j++){printf("&arr[%d][%d]=%p\n", i, j, &arr[i][j]);}}return 0;
}

 结论:二维数组在内存也是连续存储的。

理解:二维数组是连续的。

1、看成连续的一维数组。

#include<stdio.h>int main()
{int arr[3][4] = { 1,2,3,4,5,6,7,8,9,10,11,12 };//1、下标法打印int i = 0;for (i = 0; i < 3; i++){int j = 0;for (j = 0; j < 4; j++){printf("%d ", arr[i][j]);}}printf("\n");//2、指针法int* p = &arr[0][0];int k = 0;for (k = 0; k < 12; k++){printf("%d ", *(p + k));}printf("\n");return 0;
}

运行结果:

2、 把每一行看成一维数组(即:二维数组也是一维数组的数组(集合))

应用:

计算行数:sizeof(arr)/sizeof(arr[0])

计算列数:sizeof(arr[0])/sizeof(arr[0][0]) 

总结:知道数组在内存中是连续存放的,我们就可以用指针访问数组元素。

3.  数组的越界

        数组的下标是有范围限制的。

        数组的下标规定是从0开始的,如果数组有n个元素,最后一个元素的下标就是n-1.

        所以数组的下标小于0,或者大于n-1,就是数组越界访问了,超出了数组合法空间的访问

        C语言本身是不做数组下标的越界检查,编译器也不一定报错,但是编译器不报错,并不意味程序就是正确的。

        所以程序员写代码时,最好自己做越界的检查。

代码实例:

#include<stdio.h>
int main()
{int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };//下标的范围0-9int i = 0;for (i = 0; i <= 10; i++)//下标大于9了{printf("%d ", arr[i]);}printf("\n");return 0;
}

这个时候我们发现当i=10时,数组越界了,但是编译器不报错!

运行结果:

 当我们打印数组元素,发现有不是数组范围的值,经验告诉我们很可能数组越界了。

当出现以下错误,一定是数组越界了。

 注:二维数组的行和列也可能存在越界。(越界就如:生活中没抓到的小偷,就不是罪犯吗?)

4.  数组作为函数参数

我们在写代码的时候,会将数组作为参数传给函数。

将一个整形数组排序。

排序:冒泡、选择、插入、快速...

在这我先讲个简单的冒泡排序

冒泡排序:

4.1  冒泡排序函数的错误设计

#include<stdio.h>void Sort(int arr[])
{int sz = sizeof(arr) / sizeof(arr[0]);//能计算出数组的个数吗?int i = 0;for (i = 0; i < sz - 1; i++){int j = 0;for (j = 0; j < sz - 1 - i; j++){if (arr[j] > arr[j + 1])//是否升序{int temp = arr[j];arr[j] = arr[j + 1];arr[j + 1] = temp;}}}}int main()
{int arr[10] = { 3,6,9,0,8,5,2,1,4,7 };//写一个函数对数组进行排序Sort(arr);//能否正确排序?int i = 0;for (i = 0; i < 10; i++){printf("%d ", arr[i]);}printf("\n");return 0;
}

 运行结果:

我们发现数组并未排序成功,这是为什么呢?

        通过调试,我们发现在函数内部sz=1。为什么呢——难道数组作为函数参数的时候,不是把整个数组传递过去?

接下来理解数组名。

4.2  数组名是什么?

#include<stdio.h>
int main()
{int arr[10] = { 0 };printf("%p\n", arr);printf("%p\n", &arr[0]);return 0;
}

运行结果:

 结论:数组名是数组首元素的地址。

但是有两个例外

1、sizeof(数组名),这里的数组名是表示整个数组,计算的是整个数组的大小,单位是字节。

2、&数组名,这里的数组名是表示整个数组,&数组名取出的是数组的地址。

#include<stdio.h>
int main()
{int arr[10] = { 0 };printf("%p\n", arr);printf("%p\n", arr+1);printf("%p\n", &arr);printf("%p\n", &arr + 1);return 0;
}

运行结果:

 

虽然arr和&arr值一样,但是含义是不同的! 

4.3  冒泡排序函数的正确设计

当数组传参的时候,实际上只是把数组的首元素的地址传递过去了。所以即使在函数参数部分写成数组的形式:int arr[]的本质是一个指针:int * arr。(所以在sort函数内部sz=1,因为在函数内部的sizeof(arr)的结果是4)

改正:

#include<stdio.h>void Sort(int arr[], int sz)
{int i = 0;for (i = 0; i < sz - 1; i++){int j = 0;for (j = 0; j < sz - 1 - i; j++){if (arr[j] > arr[j + 1]){int t = arr[j];arr[j] = arr[j + 1];arr[j + 1] = t;}}}
}int main()
{int arr[] = { 3,6,9,0,7,2,1,5,8,4 };int sz = sizeof(arr) / sizeof(arr[0]);Sort(arr, sz);int i = 0;for (i = 0; i < sz; i++){printf("%d ", arr[i]);}printf("\n");return 0;
}

运行结果:

 补充:

arr[i] <---->*(arr+i)

&arr[i] <----->arr+i


http://www.ppmy.cn/news/477316.html

相关文章

Atcoder Beginner Contest 269(A-G)

Atcoder Beginner Contest 269 A - Anyway Takahashi 题目太水了&#xff0c;一年级小朋友都可以做 #include<bits/stdc.h> using namespace std; int main(){int a,b,c,d;cin>>a>>b>>c>>d;cout<<(ab)*(c-d)<<endl;cout<<&…

S4语法整理

1. VALUE type( ... )&#xff0c;DATA(WA) 临时定义类型并且赋值给构造 TYPES:BEGIN OF TY_TAB,ZCHAR1 TYPE C LENGTH 10,ZCHAR2 TYPE C LENGTH 10,ZCHAR3 TYPE C LENGTH 10,ZCHAR4 TYPE C LENGTH 10,END OF TY_TAB.DATA(WA) VALUE TY_TAB( ZCHAR1 1 ZCHAR2 2 ZCHAR3 3 Z…

S4 MIGO屏幕增强

1.创建结构和表 结构&#xff1a;ZSMIGO_ITEM 表类型&#xff1a; 表 &#xff1a;ZTMIGO_ITEM&#xff08;用来保存增强字段的值&#xff09; 2.创建函数组 TOP里的代码&#xff1a; FUNCTION-POOL zfg_migo. "MESSAGE-ID ..* INCLUDE LZFG_MIGOD..…

三星性能测试软件,13款软件压力测试 Galaxy S4性能体验

第1页:前言 第2页:第一轮测试&#xff1a;检阅综合性能 第3页:第二轮测试&#xff1a;考验CPU单元 第4页:第三轮测试&#xff1a;考验GPU单元(一) 第5页:第四轮测试&#xff1a;考验GPU单元(二) 第四轮测试&#xff1a;考验GPU单元(二) 除了这些国内用户耳熟能详的工具外&#…

S4 BP详解

ECC中客户和供应商是分开管理的&#xff0c;这种模式具有部分局限性&#xff1a; 客户和供应商不能是同一实体关系&#xff0c;建两个主数据会造成数据的冗余 客户/供应商只能有一个地址 属性无时间相关性 S4中使用BP业务伙伴模型解决这个问题(代替了传统的FD01/VD01/FK01/…

AntV G6 的坑之——从卡掉渣到满帧需要几步

AntV G6 是一款图可视化与分析开源引擎。《AntV G6 的坑之——XXX》系列文章持续更新中&#xff0c;总结常见问题及神坑解决方案。任何问题可在 GitHub Issue 中提问&#xff0c;求 GitHub Star ⭐️https://github.com/antvis/g6 原文链接&#xff1a;https://g6.antv.antgrou…

Android studio虚拟机联网

Android studio虚拟机联网 背景 最近由于需要调试老是使用真机每次都要链接太麻烦,我的大致思路是功能慢慢完善使用虚拟机调试,一个功能开发的差不多了再到真机上试一下,但是虚拟网络不同很是不爽,网上搜了一大堆要么不详细,要么不兼容,所以观者需要先看一下开发环境的版本和s…

AndroidStudio中虚拟机的联网问题

最近使用云数据库进行移动开发遇到了一些网络问题 报错1&#xff1a;在虚拟机页面的报错 尚未失败: Unable to resolve host “open.cctvcloud.cn” No address associated with hostname 解决&#xff1a;把校园网换成流量就好了…无语 关于虚拟机版本选择的联网 在遇到虚…