摘要:在学习 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. linux netstat 命令详解

    linux netstat 命令详解 1.功能与说明 netstat 用于显示linux中各种网络相关信息.如网络链接 路由表  接口状态链接 多播成员等等. 2.参数含义介绍 -a (all)显示所 ...

  2. 黑马程序员:Java基础总结----正则表达式

    黑马程序员:Java基础总结 正则表达式   ASP.Net+Android+IO开发 . .Net培训 .期待与您交流! 正则表达式 import  java.util.regex.*; 符合一定规 ...

  3. github + SourceTree管理自己的库并上传到cocoapods及各种坑的解决办法

    一.上传写好的库到github(我这里使用SourceTree客户端) 1.在github上创建一个仓库 2.将仓库拉倒本地 复制仓库地址 将刚才复制的地址粘贴到这里 3.上传项目到github 将写 ...

  4. Epicor系统二次开发

    Epicor系统二次开发 一.获取或修改界面EpiDataView的字段数据(Get EpiDataView data) C# EpiDataView edv = (EpiDataView)oTran ...

  5. 类xml数据格式解析

    需要解析一种类xml的数据文件,数据格式1如下: <head> //文件头 <type>xtype</type> <condition> key1=va ...

  6. 消息推送之androidpn部署

    androidpn客户端的部署在eclipse上,要记住两点: 1.直接导入的项目是上个世纪的lib这个文件夹,要改为libs.否则会报错找不到云云类. 2.如果在虚拟器上测试,要将res/raw/a ...

  7. 替换ubuntu 14.04的源

    1. 背景(为什么要替换)安装ubuntu,默认源是(http://extras.ubuntu.com/ubuntu),国内访问很慢...当我们用apt-get安装软件包或者更新时有时很慢,所以才想到 ...

  8. HDU 1269 迷宫城堡(DFS)

    迷宫城堡 Problem Description 为了训练小希的方向感,Gardon建立了一座大城堡,里面有N个房间(N<=10000)和M条通道(M<=100000),每个通道都是单向的 ...

  9. eclipse 一些快捷键

    快捷键 alt + 上下方向键 向后缩进 shift + tab 整体向左移动 tab 就是向右移动 ctrl + Q 就是构建有参的构造方法 ctrl + E 是get set 方法,要把quick ...

  10. Webservice WCF WebApi

    注明:改编加组合 在.net平台下,有大量的技术让你创建一个HTTP服务,像Web Service,WCF,现在又出了Web API.在.net平台下,你有很多的选择来构建一个HTTP Service ...