摘要:在学习 C 语言编程中遇到的一些容易混淆出错的问题,记录下来备忘。

C语言学习 小问题集锦

作者:乌龙哈里
时间:2015-11-24
平台:Window7 64bit,C# :Visual Studio Community 2015, C:TCC 0.9.26(x86-64 Win64)

参考:

章节:

  • 数组元素 a[n++] 是 a[n] 还是 a[n+1]?
  • 2个递归到底如何运行?
  • 传递数组的元素个数?

正文:

一、数组元素 a[n++] 是 a[n] 还是 a[n+1]?

在学习排序中,看到了一种写法,a[n++],这个a[n++]到底是 a[n]还是 a[n+1]?不用多说,上测试代码:

#include <stdio.h>
int main(void){
    int a[4]={1,2,3,4};

printf("Array: ");
    for(int i=0;i<4;i++){printf("%d ",a[i]);}
    printf(" n=%d \n",n);

int n=0;
    a[n++]=8;

printf("Array: ");
    for(int i=0;i<4;i++){printf("%d ",a[i]);}
    printf(" n=%d \n",n);
    return 0;
}
/*结果:
Array: 1 2 3 4 n=0
Array: 8 2 3 4 n=1
*/

结果表明:a[n++] 还是指 a[n],然后n=n+1了。

二、2个递归如何运行?

在学习快速排序的时候,遇到了同时有2个递归的情况,如:

QuickSort(a,left,i-1);
QuickSort(a,i+1,right);

他们到底是怎么运行的呢?上测试代码:

#include <stdio.h>
int n=0;
void Recursion(int a,int b){
    if (b>3 ) return;
    if(a!=3) printf("%2d : R: %d %d \n",n,a,b);
    n++;
    b++;
    Recursion(0,b);
    Recursion(1,b);
}
int main(void){
    Recursion(3,0);
    return 0;
}
/*结果:
 1 : R: 0 1
 2 : R: 0 2
 3 : R: 0 3
 4 : R: 1 3
 5 : R: 1 2
 6 : R: 0 3
 7 : R: 1 3
 8 : R: 1 1
 9 : R: 0 2
10 : R: 0 3
11 : R: 1 3
12 : R: 1 2
13 : R: 0 3
14 : R: 1 3
*/

根据递归的原理,用栈记录函数的出入口,我简单地认为把函数压入栈,根据栈后进先出的特性,我把上面的用符号记录过程,把两个函数分别标记为R0,R1。R0-1--代表第1个递归函数,b值为1;R1-2,代表第2个递归函数,b值为2,下来分解:

步    执行及b值     栈内及b值                描述
  1    R0-1            R1-1                        b=1,执行R0-1,把R1-1压入栈
  2    R0-2            R1-1, R1-2             进入R0,b++为2,执行R0-2,把R1-2压入栈
  3    R0-3            R1-1, R1-2, R1-3    进入R0,b++为3,执行R0-3,把R1-3压入栈
  4    R1-3            R1-1, R1-2             进入R0,b++为4,触发退出,回到栈内取最后一个R1-3执行
  5    R1-2            R1-1                        R1-3执行,触发退出,执行R1-2
  6    R0-3            R1-1, R1-3              进入R1-2,b++为3,执行 R0-3,把R1-3压入栈
  7    R1-3            R1-1                        R0-3触发退出,从栈内取出 R1-3运行
  8    R1-1            R1-2                        运行R1-1,进入R0-2,把R1-2压入栈
  9    R0-2            R1-2, R1-3              运行R0-2,进入R0-3,把R1-3压入栈
10    R0-3            R1-2, R1-3              运行R0-3,触发退出
11    R1-3            R1-2                        运行R1-3,触发退出
12    R1-2            R1-3                        运行R1-2,b++为3,准备进入R0-3,把R1-3压入栈
13    R0-3            R1-3                        运行R0-3,触发退出
14    R1-3                                            运行R1-3,触发退出,栈内为空,全部结束。

脑袋都疼了,那么复杂,这些人到底怎么想出来的,难道他只用知道退出机制及计算过程,根本不关注执行顺序。

三、传递数组的元素个数?

在学习排序中,经常要循环,需要知道数组的长度(元素个数),在同个函数内,用
int len=sizeof(a)/sizeof(a[0]);
就能知道,把数组传递进函数后,难道也能这样?上测试代码:

#include <stdio.h>
void Test(int a[]){
    printf("byref: a %2d, a[0] %d,num %d\n",sizeof(a),sizeof(a[0]),sizeof(a)/sizeof(a[0]));
}
int main(void){
    int a[]={1,2,3,4};
    printf("none : a %2d, a[0] %d,num %d\n",sizeof(a),sizeof(a[0]),sizeof(a)/sizeof(a[0]));
    Test(a);
    return 0;
}
/*输出:
none : a 16, a[0] 4,num 4
byref: a 8, a[0] 4,num 2
*/

明显在传递数组的函数内再用这种方式是错误,原因在于数组作为形式参数是指针化了,显示的是指针的大小,64位平台指针是8 byte的。查了一堆资料,除了用结构 struct 把数组包装一下,如下:

struct A{
    int count;
    int a[];
};

这样能通过 count 取得数组大小,但这样又涉及数组的初始化等问题,很是麻烦。

若还在学习的过程中碰到这些小问题,继续补充。
未完待续...

C 小问题集锦的更多相关文章

  1. LoadRunner小技巧集锦

    preftest 性能测试工作室,专注于性能测试技术研究(www.AutomationQA.com) LoadRunner小技巧集锦 1.录制脚本中包含中文,出现乱码怎么办? 把录制选项中的Suppo ...

  2. flex开发小技巧集锦

    关于flex开发网上有非常多的相关信息介绍,因此我们要想学习关于flex开发的知识信息技能是一件非常简单和方便的事情.而针对于flex开发小编要告诉大家的是一些flex开发小技巧.利用这些小技巧能够有 ...

  3. iOS面试小题集锦

      1.Object-C有多继承吗?没有的话用什么代替? cocoa 中所有的类都是NSObject 的子类 多继承在这里是用protocol 委托代理 来实现的你不用去考虑繁琐的多继承 ,虚基类的概 ...

  4. android浏览器开发小技巧集锦(转)

    本人和朋友们做了一段时间浏览器,将一些小技巧分享出来,先写一部分,慢慢写,同时也为我们的浏览器打打广告 我们的浏览器将要上线,名叫沙发浏览 1.网页内的右键菜单 public boolean onLo ...

  5. sql server 小技巧 集锦

    sql server 小技巧(1) 导入csv数据到sql server sql server 小技巧(2) 删除sql server中重复的数据 sql server 小技巧(3) SQL Serv ...

  6. python经典小程序集锦(一) 实现九九乘法表

    本篇文章主要是收集整理一些小程序以供大家娱乐,或者是在面试的时候使用到.文章会持续更新,希望大家收藏关注哦. 1.代码实现过程 for i in range(1, 10): for j in rang ...

  7. Xcode开发小问题集锦

    Q:用Xcode 6 创建的工程在iOS 7的设备上运行时上下部均会出现黑色的区域且应用不能全屏运行. A:Targets -> General -> App Icons and Laun ...

  8. QT5学习过程的小问题集锦

    *** only available with -std=c++11 or -std=gnu++11 添加以下代码到*.pro文件. CONFIG += c++11 在 Qt creator 中设置 ...

  9. 近期code review几处小问题集锦

    1 线程池使用不当 我们的调度系统需要将一堆会员分配给相应的人员来处理,流程如以下伪代码所示: public void dispatch() { while (true) { List<Memb ...

随机推荐

  1. PHP 数组拼接成字符串

    PHP[知识分享] 数组拼接成字符串 <?php // 格式: [二维数组] Array ( [0] => Array ( [topicid] => 1 ) [1] => Ar ...

  2. 调试设置移动端Web开发环境搭建实践

    新手发帖,很多方面都是刚入门,有错误的地方请大家见谅,欢迎批评指正 本文重要总结一下挪动端进行前端开发时需要用到的一些工具,以及他们之间互相的组合,同时也包含本人应用的组合. 1. Chrome To ...

  3. 关于js关闭浏览器技术细谈

    前言:前端时间做项目遇到一个js的问题,需要使用js关闭浏览器,在原有js代码是有这样功能的, 代码如下 window.close(); 但是呢,chrome,firefox等中有时候会不起作用. 后 ...

  4. C语言之循环结构 for(二)

    一 for循环的嵌套使用 for循环的嵌套语法: for(int i =0;i<10;i++){ for(int j=0;j<5;j++){ } } 一般用来打印平面,或者控制平面,或者说 ...

  5. orchard相关网址

    1.官网文档  http://docs.orchardproject.net/ 2.github  https://github.com/OrchardCMS/Orchard 3.stackoverf ...

  6. windows全系列激活脚本-改良版.cmd

    @ECHO OFFTITLE Windows 全版本系统激活cscript //nologo %Systemroot%\system32\slmgr.vbs -skms 10.1.1.12ECHO 检 ...

  7. php目录函数

    1.创建 mkdir()mkdir(目录地址,权限模式,是否递归创建)默认不支持递归创建,用第三个参数true表示递归创建 <?php header("content-type:tex ...

  8. Windows server 2008 r2上安装MySQL

    用MSI安装包安装 根据自己的操作系统下载对应的32位或64位安装包.按如下步骤操作: MySQL数据库官网的下载地址http://dev.mysql.com/downloads/mysql,第一步: ...

  9. hdu1046

    #include<iostream> #include<cmath> using namespace std; int main() { int T,t=0,m,n; cin& ...

  10. 教你成为全栈工程师(Full Stack Developer) 一-各显神通总结八大类编程语言的区别

    为了能在最快的时间里理解更多语言的相同点和不同点,我用大家最熟悉的Hello World来展示一下各个语言的奥妙   请尊重原创,转载请注明来源网站www.shareditor.com以及原始链接地址 ...