数组作为函数参数为什么要多传一个长度_Day10 数组作为函数参数为什么要多传一个长度——Day10 学习记录从数组传参到日历打印学完函数之后我开始用函数封装各种功能。但很快就遇到了问题——把数组传给函数后用sizeof计算长度结果根本不是数组的大小。后来才知道这是 C 语言最经典的数组退化为指针规则。今天就把数组传参、字符串操作函数、作用域和存储类别串起来讲一遍最后用一个打印日历的例子收尾。① 数组传参的本质为什么不是传整个数组很多新手包括我第一次写数组传参时都会这么想“把整个数组传进去不就行了”但 C 语言偏不。它不传整个数组只传首元素的地址。原因数组可能很大。如果每次传参都复制整个数组性能开销太大了。C 语言的设计哲学是相信程序员不做多余的事。所以数组名做参数时编译器把它解释为指针——准确地说是退化为首元素地址。既然函数拿到的只是一个地址它当然不知道数组有多长。这就是为什么必须额外传一个长度参数。与之对比字符数组字符串不需要传长度因为字符串自带\0结束标志。函数只需一直读到\0就知道到哪结束了。一句总结数组传参退化为指针函数拿不到数组大小所以要么额外传长度要么靠 ‘\0’ 结尾。② 一维数组传参怎么写错误示例voidprintArray(inta[]){intlensizeof(a)/sizeof(a[0]);// 错sizeof(a) 是指针大小}这个坑我踩过不止一次。sizeof(a)在函数里返回的是指针的字节数8 或 4不是数组的大小。正确写法voidprintArray(inta[],intlen){for(inti0;ilen;i)printf(%d ,a[i]);}printArray(a,10);// 调用时传入长度字符数组就不一样了voidprintStr(chars[]){for(inti0;s[i]!\0;i)printf(%c,s[i]);}printStr(hello);// 不需要传长度一句总结整型数组传参要加长度参数字符数组靠 ‘\0’ 结尾。③ 二维数组传参为什么列数不能省略错误示例voidoutputArray(inta[][],introw);// 编译错误为什么错二维数组本质上是数组的数组。访问a[i][j]时编译器需要计算偏移量地址 首地址 (i * 列数 j) * 元素大小列数不指定这个公式就没法算。行数可以省略因为编译器不需要行数就能算出地址。正确写法voidoutputArray(inta[][4],introw){for(inti0;irow;i){for(intj0;j4;j)printf(%d ,a[i][j]);printf(\n);}}二维字符数组同理char str[][10]列数必须写行数可以省略。一句总结二维数组传参必须指定列数因为编译器需要列数来定位元素。④ 字符串操作函数自己动手实现标准库提供了string.h但自己实现一遍能更深刻理解原理。Strlen计算字符串长度遇到\0就停统计\0之前的字符数。intmyStrlen(constchars[]){inti0;while(s[i]!\0)i;returni;}Strcpy复制字符串注意要把\0也复制过去。voidmyStrcpy(chardest[],constcharsrc[]){inti0;while(src[i]!\0){dest[i]src[i];i;}dest[i]\0;// 别忘了复制结束符}Strcat拼接字符串先找到 dest 的末尾\0的位置再从那里开始复制 src。voidmyStrcat(chardest[],constcharsrc[]){inti0,j0;while(dest[i]!\0)i;// 找到 dest 末尾while(src[j]!\0){dest[i]src[j];i;j;}dest[i]\0;}Strcmp比较字符串逐个字符比较 ASCII 码找到第一个不同的字符就返回差值。intmyStrcmp(constchars1[],constchars2[]){inti0;while(s1[i]!\0s2[i]!\0){if(s1[i]!s2[i])returns1[i]-s2[i];i;}returns1[i]-s2[i];}一句总结四个操作函数的本质都是遍历 ‘\0’ 结尾的字符数组。⑤ 作用域与存储类别作用域讲的是在哪能用生命周期讲的是啥时候销毁。局部变量 vs 全局变量intg10;// 全局变量所有函数都能用voidfunc(){inta5;// 局部变量只能在 func 里用}就近原则如果局部和全局同名局部优先。存储类别关键字关键字存储位置生命周期作用域说明auto栈块内块内默认局部变量static全局区程序始终块内只初始化一次register寄存器建议块内块内编译器可忽略extern外部存储程序始终全局声明外部变量static最常用——它让局部变量在函数多次调用之间保持值不变但其他函数又访问不到。一句总结作用域决定可见性static 让局部变量拥有全局生命周期但保持局部访问限制。⑥ 综合实战打印日历今天最后一个实战打印 2026 年 7 月的日历。拆成四个函数每个只做一件事#includestdio.hintisLeapYear(intyear){return(year%40year%100!0)||(year%4000);}intgetMonthDays(intyear,intmonth){intdays[]{31,28,31,30,31,30,31,31,30,31,30,31};if(month2isLeapYear(year))return29;returndays[month-1];}intgetAllDays(intyear,intmonth){inttotal0;for(inty1;yyear;y)totalisLeapYear(y)?366:365;for(intm1;mmonth;m)totalgetMonthDays(year,m);returntotal;}voidprintCal(intyear,intmonth){intdaysgetMonthDays(year,month);intweekday(getAllDays(year,month)1)%7;// 2026.1.1 是周四printf( %d 年 %d 月\n,year,month);printf(日 一 二 三 四 五 六\n);for(inti0;iweekday;i)printf( );for(intd1;ddays;d){printf(%2d ,d);if((weekdayd)%70)printf(\n);}printf(\n);}intmain(){printCal(2026,7);return0;}核心思路从公元 1 年 1 月 1 日到目标年月的 1 日算出总天数总天数 % 7 得到星期几再按格式输出。每日一练运行上面的代码验证 2026 年 7 月的日历是否正确。你可以把年份和月份改成其他值测试。今日避坑指南坑原因怎么避函数内 sizeof(a) 不是数组大小数组名退化为指针额外传 len二维数组列数省略导致编译错误编译器无法计算偏移形参写int a[][N]Strcpy 忘记复制 \0目标数组不是合法字符串循环结束后加dest[i]\0Strcat 目标空间不够拼接后越界确保 dest 容量足够全局变量滥用函数间耦合高、难调试能用传参就别用全局忘记闰年判断2 月天数算错isLeapYear 单独封装今日学习感悟今天最有价值的收获是理解了 C 语言数组传参退化为指针这条规则。以前写sizeof(a)在函数里算出指针大小时我只觉得莫名其妙。今天搞明白了背后的原因——性能优先的设计哲学一切都有道理。另一个收获是日历打印这个实战。把一个看起来复杂的问题拆成四个小函数每个函数独立测试最后组合起来。这个拆分思路在嵌入式开发中特别重要一个函数只做一件事做好一件事。Day10 学习记录明天继续。

相关新闻

最新新闻

SerenityOS 命令行选项解析指南:getopt 与 getopt_long 用法、返回值与底层实现

SerenityOS 命令行选项解析指南:getopt 与 getopt_long 用法、返回值与底层实现

SerenityOS 命令行选项解析指南:getopt 与 getopt_long 用法、返回值与底层实现 【免费下载链接】serenity The Serenity Operating System 🐞 项目地址: https://gitcode.com/GitHub_Trending/se/serenity 导读 本文以 getopt(3) 手册 为核心&a…

2026/9/25 12:45:43
轻量服务器还是ECS?大促云服务器选购与避坑实战指南

轻量服务器还是ECS?大促云服务器选购与避坑实战指南

每年大促节点,群里永远有人在问同一个问题:“38元的轻量服务器到底怎么抢?为什么我每次点进去都是已售罄?68元直购和99元的ECS我到底选哪个?”作为一个常年帮团队和自己采购云服务器的老用户,我太清楚这种纠…

2026/9/24 14:25:52
为 AI 代理的 Review 动作编写 Cedar 审批门控策略:review-agent-governance 策略编写实战指南

为 AI 代理的 Review 动作编写 Cedar 审批门控策略:review-agent-governance 策略编写实战指南

为 AI 代理的 Review 动作编写 Cedar 审批门控策略:review-agent-governance 策略编写实战指南 【免费下载链接】agents Multi-harness agentic plugin marketplace for Claude Code, Codex, Cursor, OpenCode, GitHub Copilot, and Google Antigravity 项目地址:…

2026/9/24 14:49:33
PaddleOCR 手写数学公式识别算法 CAN 实战指南:Counting-Aware Network 训练、评估与推理部署

PaddleOCR 手写数学公式识别算法 CAN 实战指南:Counting-Aware Network 训练、评估与推理部署

PaddleOCR 手写数学公式识别算法 CAN 实战指南:Counting-Aware Network 训练、评估与推理部署 【免费下载链接】PaddleOCR Turn any PDF or image document into structured data for your AI. A powerful, lightweight OCR toolkit that bridges the gap between i…

2026/9/23 8:01:38
Spring源码解析:构造器注入的类型转换与候选匹配机制

Spring源码解析:构造器注入的类型转换与候选匹配机制

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/24 14:28:18
openai-agents-python 多模型接入指南:深入解析 AnyLLMModel 适配层与 any-llm 路由

openai-agents-python 多模型接入指南:深入解析 AnyLLMModel 适配层与 any-llm 路由

openai-agents-python 多模型接入指南:深入解析 AnyLLMModel 适配层与 any-llm 路由 【免费下载链接】openai-agents-python A lightweight, powerful framework for multi-agent workflows 项目地址: https://gitcode.com/GitHub_Trending/op/openai-agents-pyth…

2026/9/24 11:09:24

日新闻

周新闻