摘要:在学习 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. MacOSX中使用NSWindow创建背景透明的窗体

    1.Windows 在window上创建异形窗体必须要使用WS_EX_LAYERED样式,再调用SetLayeredWindowAttributes设置透明度或者透明颜色属性.用updatelayer ...

  2. hdu1205(类似 分布垃圾数列)

    Problem Description A Fibonacci sequence is calculated by adding the previous two members the sequen ...

  3. 熬之滴水成石:Spring--精简的J2EE(7)

                                              49--持久性 关于持久性在最早的Delphi单元中,就曾介绍过.持久性是数据库中读取,保存,或删除数据的过程.毫无 ...

  4. 总结 React 组件的三种写法 及最佳实践 [涨经验]

    React 专注于 view 层,组件化则是 React 的基础,也是其核心理念之一,一个完整的应用将由一个个独立的组件拼装而成. 截至目前 React 已经更新到 v15.4.2,由于 ES6 的普 ...

  5. JS —— 数组与字符串方法

    数组 1. 基本方法  1)Array.prototype.unshift(item1,item2,item3...) 描述: 在数组的前面添加元素,一次可以传入多个参数. 注意:元素会根据当前传入的 ...

  6. javascript实现 京东淘宝等商城的商品图片大图预览功能

    在京东和淘宝等购买东西的时候,我们会经常预览左侧商品展示图片,把鼠标放到原图,右侧就会有个大图显示出细节.本文将带领大家写一个这样简单的功能! 一.实现原理 当鼠标移入某一图片内部时,图片上部会出现一 ...

  7. c#-委托,匿名方法,lambda表达的关系

    什么是委托: 包含单个方法的委托和函数指针是相似的,不同的是,委托是面向帝乡的并且是类型安全的 声明委托类型: delegate void mydel(int x); 声明委托和声明方法差不多,两个不 ...

  8. iOS之崩溃处理:This application is modifying the autolayout engine from a background thread

    一.错误提示 今天在开发的时候遇到一个崩溃问题,"This application is modifying the autolayout engine from a background ...

  9. 三、spark入门:文本中发现5个最常用的word,排除常用停用词

    package com.yl.wordcount import java.io.File import org.apache.spark.{SparkConf, SparkContext} impor ...

  10. Head First设计模式——策略设计模式

    策略设计模式 说在前面的话 入软件一年啦,平心而论,总算不限于只会钻研些基础的语言语法了,数据结构和算法也恶补的差不多了.所以~趁着现在一边实习一边啃<Head First设计模式>的功夫 ...