C语言数组使用、数组相关的宏定义剖析,及矩阵乘积、杨辉三角实例
数组一直是编程语言学习中需要重点掌握的部分,它是最基本的数据结构类型,是构成字符串及其他许多重要构造结构的基础。相对许多其他高级语言来说,C语言对数组本身提供的支持并不太多,尤其是不支持动态的数组定义。
本文总结了几种常见的数组使用中的错误用法,并通过分析原理解释错误原因,从而为掌握正确的数组用法提供帮助。同时提供了几个相对有代表性的数组的使用方式及源码,以方便学习。
指引
- 数组定义方法及使用示例
- 常见数组定义错误
- 数组原理及坑
- 矩阵乘积计算
- 杨辉三角
- 数组宏
数组定义方法
在C语言中,数组按如下的方法定义:
① 类型 数组名[数组大小];
int array[10];char str[15];
② 类型 数组名[]={元素1,元素2,元素3,...};1
int a={1,2,3,4,5};char ch[]={'a','b','c'};
③ 类型 数组名[数组大小]={元素1,元素2,元素3,...};2
float x[4]={1.5, 3.2, 6.0, 23};int y[5]={1,2,3,4};
数组使用方法示例
/*在下述代码代码片段中展示了几种常见的错误
*/#define N 5int main(){/*错误形式 01: 声明数组时没有确定长度 */int array1[];/*错误形式 02:数组长度必须在进行编译初期就能确定,而不能是在运算处理中才能计算出来的结果,如宏定义 */int m=5;int array[m];/*错误形式 03: 先声明了数组,再赋值*/int array2[N];array2={1,2,3,4,5};/*错误形式 04: 赋值范围超出了开辟的空间*/int array3[N]={1,2,3,4,5,6};/*错误形式 05: 试图进行对数组的整体赋值*/int a[N]={1,2,3,4,5},b[N];b=a;return 0;
}
数组原理及“坑”
1. 数组在定义的时候,在内存空间中为其开辟了一块连续的空间,其大小为单个数组元素类型所占大小 sizeof(type) 与元素个数N的积,即:
size = sizeof(type) * N
2. 同一数组内的数据元素必须一样,即即便如下述定义:
float x[]={1, 2, 3, 4.0, 3, 44, 27, 8};
其结果也是使得所有的元素都被强制转换为float类型!
3. 数组一旦定义之后,数组名就表示数组的第一个元素的地址,很大程度上等同于指向该数组的指针,即:
x==&(x[0]);//以下是关于该向量名称经常等同于指针来使用的情况的说明float *p;p = x; //或者 p = (float*)malloc(4)memset(x, 10, 4); //将 x[0]到 x[3] 共4个位置赋值为10memset(p, 10, 4); //将 float类型的地址从p开始到相邻的共4个位置全部赋值为10,和上一句效果相同memset(x+2, 10, 4); //将 x[2]到 x[5] 共4个位置赋值为10//数组名和指针,在以下表达式中不一样:sizeof(x) //等于数组元素的个数,即8 ,其中x的定义是 float x[]={1, 2, 3, 4.0, 3, 44, 27, 8};sizeof(p) //等于p的类型(float类型的指针)所占空间字节数,为4;//题外话:// 在32位系统中,所有类型的指针变量都存放的是该指针在内存中的地址,所以所占用的都是4个字节; 而64位系统中,则是8个字节!
如果试图按照这样的方式进行赋值:
int x[]={1,2,3,4,5,6},y[6];y=x;
就会报错,因为这一句话相当于:
&(y[0])=&(x[0]);
错误原因在于,左边的表达式 &(y[0]) 是一个内存中既定的地址而非一个变量符号,它不可被用于左值!3故是一种错误。
4.正是由于上述原因,因此如果按以下方式进行数组的声明4:
int x[5];//或者:#define N 5int x[N];
则必须对元素分别进行赋值,且只能通过下标的方式进行5,如:
int a[5];{a[i]=i;} //当所有元素赋值都相同时,也可以用 memset(a, 100, 5)的方式,比较简便
5.数组在进行函数调用时,传递给形参的值为该数组的名称 / 第一个元素的地址,因此不是值传递,在被调用函数中对数组的处理,都会导致原数组的值被改变,这一点尤其需要注意。如:
f(int x[]) // 定义函数f(){x[2] = -1;} int array[10] = {0};f(array); // 调用 f()处理该向量array[2] = ? // 结果是 -1, 这就是地址传递调用函数时产生的所谓的 “副作用”// 你肯定接触过的另一个例子是:// 排序函数,比如 sort(array),经过sort()排序函数处理后,array向量中的各个元素被改写了
6.数组在进行函数调用时,传递给形参的值为该数组的第一个元素的地址,在进行处理时计算机不知道该连续的数组地址到哪里结束,因此必须同时再传入一个指定的大小参数:length,见上例。
7.二维数组的使用同一维数组完全类似,只不过每一个一维数组的元素又是一个数组而已;多维数组完全类似,只要细心处理,就不会出现错误。
矩阵计算C语言源码:
#include<stdio.h>
#include<stdlib.h>
#include<time.h>void showYanghui(int );#ifndef MM
#define MM 5
#endif
#ifndef NN
#define NN 5
#endif
#ifndef KK
#define KK 7
#endifint main() {srand((unsigned)time(NULL));int a[MM][NN], b[NN][KK],C[MM][KK];for (int i = 0; i < MM; i++) {for (int j = 0; j < NN;j++) {a[i][j] = (int)((rand()-RAND_MAX/2)%9);}}for (int i = 0; i < NN; i++) {for (int j = 0; j < KK; j++) {b[i][j] = (int)((rand() - RAND_MAX / 2) % 9);}}/*显示a,b矩阵*/printf("matrix A=\n\n");for (int i = 0; i < MM; i++) {for (int j = 0; j < NN; j++) {printf("%3d\t",a[i][j]);}printf("\n");}printf("\n"); printf("\n");printf("matirx B=\n\n");for (int i = 0; i < NN; i++) {for (int j = 0; j < KK; j++) {printf("%3d\t", b[i][j]);}printf("\n");}/*矩阵求积*/for (int i = 0; i < MM; i++) {for (int j = 0; j < KK; j++) {int sum = 0;for (int k = 0; k < NN; k++) {sum += a[i][k] * b[k][j];}C[i][j] = sum;}}printf("\n"); printf("\n");printf("C=A*B=\n\n");for (int i = 0; i < MM; i++) {for (int j = 0; j < KK; j++) {printf("%3d\t",C[i][j]);}printf("\n");}getchar();
}
上述代码的运行结果为:
8.杨辉三角的完整实现:
#include<stdio.h>
#include<stdlib.h>#define N 20
void showYanghui(int );int main() {showYanghui(13);return 0;
}/*打印杨辉三角*/
void showYanghui(int n) {/*产生杨辉三角的存储矩阵*/int x[N][N];for (int i = 0; i < N; i++) {for (int j = 0; j < N; j++) {if (j == 0 || i == j) {x[i][j] = 1;}else {x[i][j] = x[i - 1][j - 1] + x[i - 1][j];}}}/*按照杨辉三角的显示形式显示*/for (int i = 0; i < n; i++) {for (int k = 0; k <( n-(i+1)); k++) {printf(" ");}for (int j = 0; j <= i; j++) {if (x[i][j] < 10) {printf("%4d", x[i][j]);}else if (x[i][j] < 100) {printf("%4d", x[i][j]);}else {printf("%4d", x[i][j]);}}printf("\n");}
}
上述代码的运行结果为:
在宏定义中使用数组
C语言中定义函数宏,实际上是在编译预处理时在被调用处将宏展开。通过宏定义的形式大大减少了工作量,而且有时候会使得程序运行时栈空间深度更浅,直接贴代码如下
#include<stdio.h>
#include<stdlib.h>#define SHOW_ARRAY(array){\int lengthOfArray=sizeof(array)/sizeof(array[0]);\for(int i=0;i<lengthOfArray;i++){\printf("%d\t",array[i]);\if((i+1)%5==0){\printf("\n");\}\}\printf("\n");\
}#define DISPLAY_ARRAY(str,array){\int lengthOfArray=sizeof(array)/sizeof(array[0]);\for(int i=0;i<lengthOfArray;i++){\printf("%s[%2d]=%d\t",str,i,array[i]);\if(i!=0&&(i+1)%4==0){\printf("\n");\}\}\printf("\n");\
}int main() {int vectory[] = { 53,78,35,89,23,62,22,12,62,95,27,28,8,86,32 };DISPLAY_ARRAY("vectory",vectory);printf("\n");SHOW_ARRAY(vectory);return 0;
}
上述代码的运行结果为:
其中,自定义字段“vectory”是可以随意替换的,例如换成“arr”:
注:
- 字符数组的定义 比较灵活且更加容易出错,后续专门整理. ↩
- 在赋值前指定大小: 这种情况也是合法的,但是绝不可以超过定义的大小,见:错误示例代码中的错误形式:04. ↩
- 左值/右值:在编程语言中处于赋值符号左右两边的变量值,要注意左值一般是要被赋值的。 ↩
- 这是C语言中唯一正确的不在定义时就赋值的数组定义方法! ↩
- 也叫直接寻址或直接访问方式,在访问 a[k] 时计算机内部存储器中对PC指针进行了如下运算: pc = sizeof(type)*k + &(a[0]) ↩
C语言数组使用、数组相关的宏定义剖析,及矩阵乘积、杨辉三角实例相关推荐
- 杨辉三角c语言用矩阵,C语言中杨氏矩阵与杨辉三角的实现方法
一.杨氏矩阵 1.杨氏矩阵的概念 在数学中,杨表(英语:young tableau),又称杨氏矩阵.是对组合表示理论和舒伯特演算很有用的工具.它提供了一种方便的方式来描述对称和一般线性群的群表示,并研 ...
- c语言编程规律数阵输出,趣味C程序100.9 绘制杨辉三角
说明:1.本问题来源于,所有程序为本人自己编写.与原程序不同之处作有标记. 2.本系列所有程序均使用codeblocks编译,操作系统为Windows XP. 问题:在屏幕上显示杨辉三角 1 1 1 ...
- C语言中的杨氏矩阵和杨辉三角
系列文章目录 文章目录 系列文章目录 前言 一.杨氏矩阵 1.杨氏矩阵的概念 2.杨氏矩阵的图解 3.杨氏矩阵的实现 二.杨辉三角 1.杨辉三角的概念 2.杨辉三角的图解 3.杨辉三角的实现 总结 前 ...
- 【C语言练习】杨氏矩阵、杨辉三角
目录 一:杨氏矩阵
- C语言每日一练——第72天:打印杨辉三角(使用两种方法)
C语言每日一练 2022年1月5日 文章目录 题目描述 问题分析 1. 使用数组法(打印直角三角) 2. 使用数组法(打印等腰三角) 3. 使用公式法(打印等腰三角) 网上参考 题目描述 打印杨辉三角 ...
- C语言实例第3期:在控制台打印出著名的杨辉三角
C语言文章更新目录 C语言学习资源汇总,史上最全面总结,没有之一 C/C++学习资源(百度云盘链接) 计算机二级资料(过级专用) C语言学习路线(从入门到实战) 编写C语言程序的7个步骤和编程机制 C ...
- 每日一题(42)—— 已知一个数组table,用一个宏定义,求出数据的元素个数
已知一个数组table,用一个宏定义,求出数据的元素个数. // 总大小除以第一个元素的大小 #define TNTBL (sizeof(table)/sizeof(table[0]))
- 杨辉三角 c语言 二维数组
杨辉三角的规律 c语言实现 思路:从第三行起,就要开始计算第n行的第二列到第n-1列的元素--其中每一个元素的值都是:前一行前一列元素+前一行该列元素 int main() {int arr[10][ ...
- 杨辉三角 C语言实现【一维数组】
杨辉三角 C语言[一维数组] 说明 写<C语言程序设计>作业的时候想到的一个算法,只用一维数组就可以实现杨辉三角的输出(不过肯定没用存储的功能了),自己感觉挺妙的,在答案和其他地方也没看到 ...
最新文章
- 区块链人才月均薪酬1.6万元?
- U-Mail邮件系统的管理权限分配
- c++ thread 内存泄漏_深入剖析ThreadLocal原理、内存泄漏及应用场景
- 白话Elasticsearch68-ES生产集群部署重要的操作系统设置
- linux系统下的mysqlgt;aborted_MySQL令人头疼的Aborted告警案例分析
- VTK:可视化之DistanceToCamera
- web前端面试问答_Web服务面试问答
- 【牛客 - 330I】Applese 的回文串(结论题,类似编辑距离,dp)
- ubuntu下安装mssql(sqlserver)客户端及使用
- 使用函数进行邮件发送的示例
- 网上的很多Android项目源码有用吗?Android开发注意的地方。
- 工作开不开心,都在钱上
- 本科三级专业目录计算机类,大学本科专业目录
- 全国计算机自动化办公专业人才证书,办公自动化证书有什么用
- Altium20版本快速批量修改Comment使之与Value相同
- 提升文学素养【文章解读】
- 【华为机试真题 Python实现】一个正整数到 Excel 编号之间的转换
- 二、Excel大纲—基础篇
- 滴滴云 远程访问jupyter
- 适合装u盘的linux系统下载软件,ghost xp系统镜像安装win7系统下载地址适合装u盘的linux...
热门文章
- PG数据库版本查看方法,sql语句查pg数据库版本方法
- java计算机毕业设计台球收费管理系统设计与实现(附源码、数据库)
- 如何区别python的主程序和子程序_主程序和子程序的区别
- vmware17虚拟机windows超详细安装教程(详细附图)
- Message的使用
- 品果php框架_【品果科技/Camera360php后端面试】我有很认真准备这次面试的,面试我的是技术牛人-看准网...
- isEmpty和isBlank的区别
- 软件构造—ADT的理解
- Android color大全
- 1053 习题4-9-1 判断正整数位数