C语言中二维数组的基本使用 定义 赋值读写指定元素的值 作为函数参数传递的注意点

news2024/12/24 10:02:06

文章目录

    • 问题
    • 依次解决
      • C语言中二维数组如何定义、如何一次性赋值?
      • 如何使用 sizeof() 计算二维数组的行数、列数?【与定义数组的地方,在同一作用域内可用】
      • 如何读写指定位置的元素?【不同作用域,有两种方式】
      • 不同作用域内,如何遍历数组元素?
      • 二维数组作为函数参数时,函数如何声明(参数列表如何写)?
    • Code & Output
      • Screenshot
      • Code
      • Output

问题

  • C语言中二维数组如何定义、如何一次性赋值?
  • 如何使用 sizeof 计算二维数组的行数、列数?【与定义数组的地方,在同一作用域内可用】
  • 如何读写指定位置的元素?【不同作用域,有两种方式】
  • 不同作用域内,如何遍历数组元素?
  • 二维数组作为函数参数时,函数如何声明(参数列表如何写)?

依次解决

以下只给出最关键的几行代码。具体代码上下文可以在最后贴上的的代码全文中查看。

C语言中二维数组如何定义、如何一次性赋值?

int arr[3][4] = {
    [0] = {1,2,3,4},    // “[1] = ”部分可以省略,省略则按代码书写顺序排序。
    [1] = {5,6,7,8},
    [2] = {9,10,11,12}
};

还有其他好几种赋值方式,但等你完全需要的时候再花时间去查找how to……。

如何使用 sizeof() 计算二维数组的行数、列数?【与定义数组的地方,在同一作用域内可用】

int row = sizeof(arr) / sizeof(arr[0]);
printf("row count: %lu / %lu = %d\n", sizeof(arr), sizeof(arr[0]), row);
int column = sizeof(arr[0]) / sizeof(arr[0][0]);
printf("column count: %lu / %lu = %d\n", sizeof(arr[0]), sizeof(arr[0][0]), column);

// row count: 48 / 16 = 3
// column count: 16 / 4 = 4

如何读写指定位置的元素?【不同作用域,有两种方式】

比如说,我在 main 函数内定义了数组,然后在 main 函数内 有以下代码:

    // 同一作用域内,可以用 array[二维数组的行数][二维数组的列数] 读取/改写指定的元素值。
    arr[1][2] = 555;
    printf("%d\n", arr[1][2]);		// 555
    // 同一作用域内,不可以用 array[二维数组的第几行 * 每行数组的列数 + 当前列数] 方式读写指定元素
//    arr[6] = 666;   // Error:  Array type 'int[4]' is not assignable
//    printf("%d\n", arr[6]); // Warning: Array index 6 is past the end of the array (which contains 3 elements)

可如果我把二维数组作为函数参数传到另一个函数里,在该函数中该如何读区指定位置的元素呢?
反过来了:

在 main 函数/定义数组处,与数组定义在同一作用域内在被调用函数内(拿到的数组名其实是一个指针变量)
array[二维数组的行数][二维数组的列数]可用不可用
array[二维数组的第几行 * 每行数组的列数 + 当前列数]不可用可用

为什么二维数组中元素的定位除了 [行][列] 的定位方式,还可以用一个下标[index]就定位?
再回到二维数组的定义写法,以下三种方式等效:

int arr[3][4] = { [0]={1,2,3,4}, [1]={5,6,7,8}, [2]={9,10,11,12} };
int arr[3][4] = { {1,2,3,4}, {5,6,7,8}, {9,10,11,12} };
int arr[3][4] = { 1,2,3,4, 5,6,7,8, 9,10,11,12 }; 

前两行也就是省略了[行号]=
而第三行是直接把嵌套的大括号{}省略了,直接一层大括号按顺序赋值。
第三行的赋值方法可行,那我们拿array[通过行列号计算得出的下标]读写二维数组可行不可行? 部分场景是可行的

不同作用域内,如何遍历数组元素?

两种定位方式描述见上一条。

for (int i = 0; i < row; i++) {
    for (int j = 0; j < column; j++) {
        int value = arr[i][j];
        printf("array[%d][%d] = %d\t\t", i, j, value);
    }
    printf("\n");
}

for (int i = 0; i < row; i++) {
    for (int j = 0; j < column; j++) {
        // int value = arr[i][j];  // Error:  Subscripted value is not an array, pointer, or vector
        int index = i * column + j;
        int value = arr[index];
        printf("arr[%d][%d]不可用,对应的arr[%d]= %d\t\t", i, j, index, value);
    }
    printf("\n");
}

二维数组作为函数参数时,函数如何声明(参数列表如何写)?

首先排除第一种int arr[][]
传递数组可以用int* arrint arr[]两种方式。
因为是传递数组作为参数到另一个函数,在这个新函数内无法用 sizeof() 求出数组size及元素个数,所以函数参数列表中还需要调用方计算出行数、列数并传递

// void traversePrint(int arr[][]);   // 方法声明直接报错: Array has incomplete element type 'int[]'
// void traversePrint(int* arr[]);	   // 方法声明倒是不直接报错,但是在方法内部没有办法读写指定元素。  arr[i][j] 报错: Thread 1: EXC_BAD_ACCESS (code=1, address=0x400000003)
void traversePrint(int* arr, int row, int column);
void traversePrint(int arr[], int row, int column);

Code & Output

Screenshot

在这里插入图片描述

Code

//
//  main.c
//  012911am-二维数组
//
//  Created by wuyujin1997 on 2023/1/29.
//

#include <stdio.h>

/// 接收二维数组变量,遍历该数组并依次打印各个元素
/// - Parameters:
///   - arr: 数组变量(本质上也是一个指向了自己的指针变量)
///   - row: 二维数组的行数(需要调用者传至本函数)
///   - column: 二维数组的列数
//void traversePrint(int arr[][]) {   // Error:  Array has incomplete element type 'int[]'
//void traversePrint(int* arr, int row, int column) {
void traversePrint(int arr[], int row, int column) {
    // 在本函数作用域内,无法通过 arr 求出其 size 和长度。
    for (int i = 0; i < row; i++) {
        for (int j = 0; j < column; j++) {
            // int value = arr[i][j];  // Error:  Subscripted value is not an array, pointer, or vector
            int index = i * column + j;
            int value = arr[index];
            printf("arr[%d][%d]不可用,对应的arr[%d]= %d\t\t", i, j, index, value);
        }
        printf("\n");
    }
    
    // 试一下能否用 array[二维数组的第几行 * 每行数组的列数 + 当前列数] 直接读写指定的元素
    arr[6] = 123456;
    printf("%d\n", arr[6]);
    
}

int main(int argc, const char * argv[]) {
    
    // 定义二维数组
    int arr[3][4] = {
        [0] = {1,2,3,4},    // “[1] = ”部分可以省略,省略则按代码书写顺序排序。
        [1] = {5,6,7,8},
        [2] = {9,10,11,12}
    };
    
    // 同一作用域内,可以用 array[二维数组的行数][二维数组的列数] 读取/改写指定的元素值。
    arr[1][2] = 555;
    printf("通过 array[行号][列号]直接读写某个元素的值: %d\n", arr[1][2]);
    // 同一作用域内,不可以用 array[二维数组的第几行 * 每行数组的列数 + 当前列数] 方式读写指定元素
//    arr[6] = 666;   // Error:  Array type 'int[4]' is not assignable
//    printf("%d\n", arr[6]); // Warning: Array index 6 is past the end of the array (which contains 3 elements)
    
    // 计算二维数组的行数、列数
    int row = sizeof(arr) / sizeof(arr[0]);
    printf("row count: %lu / %lu = %d\n", sizeof(arr), sizeof(arr[0]), row);
    int column = sizeof(arr[0]) / sizeof(arr[0][0]);
    printf("column count: %lu / %lu = %d\n", sizeof(arr[0]), sizeof(arr[0][0]), column);
    
    // 遍历二维数组
    for (int i = 0; i < row; i++) {
        for (int j = 0; j < column; j++) {
            int value = arr[i][j];
            printf("array[%d][%d] = %d\t\t", i, j, value);
        }
        printf("\n");
    }

    traversePrint(arr, row, column);
    
    return 0;
}

Output

通过 array[行号][列号]直接读写某个元素的值: 555
row count: 48 / 16 = 3
column count: 16 / 4 = 4
array[0][0] = 1		array[0][1] = 2		array[0][2] = 3		array[0][3] = 4		
array[1][0] = 5		array[1][1] = 6		array[1][2] = 555		array[1][3] = 8		
array[2][0] = 9		array[2][1] = 10		array[2][2] = 11		array[2][3] = 12		
arr[0][0]不可用,对应的arr[0]= 1		arr[0][1]不可用,对应的arr[1]= 2		arr[0][2]不可用,对应的arr[2]= 3		arr[0][3]不可用,对应的arr[3]= 4		
arr[1][0]不可用,对应的arr[4]= 5		arr[1][1]不可用,对应的arr[5]= 6		arr[1][2]不可用,对应的arr[6]= 555		arr[1][3]不可用,对应的arr[7]= 8		
arr[2][0]不可用,对应的arr[8]= 9		arr[2][1]不可用,对应的arr[9]= 10		arr[2][2]不可用,对应的arr[10]= 11		arr[2][3]不可用,对应的arr[11]= 12		
123456
Program ended with exit code: 0

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/183582.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Git(见资源)

Git的概念【1】Git技术&#xff1a;公司必备&#xff0c;一定要会 【2】Git概念&#xff1a; Git是一个免费的、开源的分布式版本控制系统&#xff0c;可以快速高效地处理从小型到大型的项目。【3】什么是版本控制&#xff1f; 版本控制是一种记录一个或若干文件内容变化&#…

BGP基础实验(华为)

题目&#xff1a; 思路&#xff1a; 该题分为三个AS区域&#xff0c;并且三个区别间分别使用不同的路由&#xff0c;EBGP,IBGP,OSFP连接等&#xff0c;其中AS1与AS2之间使用的是EBGP连接&#xff0c;这点需要EBGP的命令来进行实现&#xff0c;AS2中使用的OSPF&#xff0c;AS2&a…

不规范使用ThreadLocal导致的bug,说多了都是泪

ThreadLocal一般用于线程间的数据隔离&#xff0c;通过将数据缓存在ThreadLocal中&#xff0c;可以极大的提升性能。但是&#xff0c;如果错误的使用Threadlocal&#xff0c;可能会引起不可预期的bug&#xff0c;以及造成内存泄露。 因为线程重用导致的信息错乱的bug 有时我们…

一起自学SLAM算法:11.2 环境感知

连载文章&#xff0c;长期更新&#xff0c;欢迎关注&#xff1a; 环境感知就是机器人利用传感器获取自身及环境状态信息的过程&#xff0c;自主导航机器人的环境感知主要包括实时定位、环境建模、语义理解等&#xff0c;下面具体讨论。 11.2.1 实时定位 定位其实就是在回答图…

BI技巧丨近两年及当年月份数据汇总

BOSS&#xff1a;白茶&#xff0c;有个需求&#xff0c;不知道你能不能做&#xff1f; 白茶&#xff1a;不能&#xff01; BOSS&#xff1a;我还没说呢&#xff0c;小伙砸&#xff01;做了加钱&#xff01; 白茶&#xff1a;BOSS您吩咐&#xff01; BOSS&#xff1a;是这样的&a…

C语言开发基于RT-Thread家庭安全环境检测系统源码,RTT设计大赛

基于RT-Thread家庭安全环境检测 简介 基于RT-Thread和中蓝讯科的AB32VG1开发板实现的家庭安全检测功能&#xff0c;主要包含如下功能&#xff1a; 1、基于RT-Thread操作系统的按键组件&#xff0c;音频播放组件等&#xff1b; 2、基于AB32VG1开发板的语音播放功能&#xff1b…

BlackByte勒索软件开始使用新的数据泄露工具ExByte

BlackByte 勒索软件在 2021 年被首次发现&#xff0c;随后不断发现其变种。BlackByte 勒索软件不仅使用双重勒索&#xff0c;还运营着勒索软件即服务&#xff08;RaaS&#xff09;。最近&#xff0c;研究人员发现 BlackByte 开始使用名为 ExByte 的数据泄露工具来窃取受害者的数…

什么品牌的蓝牙耳机音质好?四款高音质蓝牙耳机推荐

随着时代的发展&#xff0c;蓝牙耳机的使用频率越来越高&#xff0c;在日常生活中随处可见的戴蓝牙耳机的人。或是听音乐&#xff0c;或是追剧&#xff0c;或是玩游戏等等。在现如今众多的蓝牙耳机品牌当中&#xff0c;什么品牌的蓝牙耳机音质好&#xff1f;下面&#xff0c;我…

基于Yolo实现的交通路况汽车识别 附完整代码(使用Keras框架)

一、问题描述 假设你现在在做自动驾驶的汽车,你想着首先应该做一个汽车检测系统,为了搜集数据,你已经在你的汽车前引擎盖上安装了一个照相机,在你开车的时候它会每隔几秒拍摄一次前方的道路。 您已经将所有这些图像收集到一个文件夹中,并通过在您找到的每辆车周围画边界框…

BlackStone:一款功能强大的渗透测试报告工具

关于BlackStone BlackStone是一款功能强大的渗透测试报告工具&#xff0c;该项目可以帮助广大研究人员自动起草和提交渗透测试或安全研究审计报告。该工具允许我们在数据库中提交和存储渗透测试过程中发现的漏洞&#xff0c;并通过内部和外部审计来对漏洞进行分类。除此之外&a…

界面控件DevExpress WinForm的先进技术——服务器和即时反馈模式

DevExpress WinForm拥有180组件和UI库&#xff0c;能为Windows Forms平台创建具有影响力的业务解决方案。DevExpress WinForm能完美构建流畅、美观且易于使用的应用程序&#xff0c;无论是Office风格的界面&#xff0c;还是分析处理大批量的业务数据&#xff0c;它都能轻松胜任…

vue中如何优雅的实现数字递增特效

需求 前几天项目开发中遇到一个需求&#xff0c;需要在数字更新时&#xff0c;实现其动态递增的效果 并且&#xff0c;在数字大于10000时&#xff0c;将单位进行转换&#xff0c;如数字大于10000时&#xff0c;单位从m变为万m 我们以vue中开发为例&#xff0c;一一实现下这两个…

多目标跟踪(MOT)入门介绍

1. 相关方向 这些是我所了解的多目标跟踪&#xff08;MOT&#xff09;的一些相关方向。其中单目标跟踪&#xff08;VOT/SOT&#xff09;、目标检测&#xff08;detection&#xff09;、行人重识别&#xff08;Re-ID&#xff09;都是非常热门的方向。而偏视频的相关方向就比较冷…

java 随机数种子 java设置随机数种子教程 java随机数种子怎么设置

我们常用的随机数生成就是Math.random()&#xff1b;java.util.Random类有两种方式构建方式&#xff1a;带种子和不带种子import java.util.Random;不带种子&#xff1a;不带种子将会返回随机的数字&#xff0c;每次运行结果不一样public class RandomTest {public static void…

分享149个ASP源码,总有一款适合您

ASP源码 分享149个ASP源码&#xff0c;总有一款适合您 下面是文件的名字&#xff0c;我放了一些图片&#xff0c;文章里不是所有的图主要是放不下...&#xff0c; 149个ASP源码下载链接&#xff1a;https://pan.baidu.com/s/173AhCXJgM5AvPqBw-la60w?pwdqk9j 提取码&#x…

如何在UI自动化测试中加入REST API的操作

1、问题 当我们描述一个“好的自动化测试用例”时&#xff0c;经常出现标准是&#xff1a; 精确 自动化测试用例应该测试一件事&#xff0c;只有一件事。与测试用例无关的应用程序的某个部分中的错误不应导致测试用例失败。 独立 自动化测试用例不应该受测试套件中任何其他测…

SVN服务端使用教程

前言 正式进入公司项目后&#xff0c;我们需要和同事进行协同开发&#xff0c;此时代码管理工具是必不可少的&#xff0c;目前常用的两款工具是&#xff1a;SVN 和 Git。本人因为要搭建一个自动化测试的框架&#xff0c;对SVN和Git都不熟悉&#xff0c;在调研后选择了操作更为…

组合选择器

<!DOCTYPE html> <html> <head> <meta charset"UTF-8"> <title>组合选择器</title> <style type"text/css"> /* 多个选择器组合在一起中间用逗号","隔开就形成了组合选择器&…

销售过程管理系统对企业的好处是什么

当线索转化成销售机会后&#xff0c;要不断地跟进才有可能成交。但是这个过程时间跨度长&#xff0c;涉及人员、要素过多&#xff0c;销售过程中经常会遇到很多的问题。不少企业使用CRM销售管理系统把控销售过程。下面来说说&#xff0c;为什么企业需要销售过程管理系统? 销售…

【Mysql】X档案:Mysql 服务和Navicat客户端的安装与使用(超详细步骤)

Mysql 服务和Navicat客户端的安装与使用&#xff08;超详细步骤&#xff09;一、Mysql 安装配置1、下载安装2、配置环境变量3、设置服务自动启动二、Mysql Cli 使用1、连接 Mysql2、创建数据库3、创建数据表4、数据表操作5、删除数据库对象三、Navicat 安装1、下载2、安装3、FR…