C 小问题集锦

摘要:在学习 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 取得数组大小,但这样又涉及数组的初始化等问题,很是麻烦。

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

时间: 2024-10-18 06:38:19

C 小问题集锦的相关文章

博主喜欢的、常用的和垃圾的小工具集锦

博主喜欢的.常用的和垃圾的小工具集锦 目录 XMind 1.XMind:http://www.xmindchina.net/ 总是有很多人喜欢问:你的图画的好漂亮啊,这是什么来的呢?思维导图,用什么画的呢?XMind,一个开源的东东哦.

C#小常识集锦(一)--《更锋利的CSharp代码》读书笔记

?.采用类似匈牙利命名法为控件命令,对于其他变量申明则不需要了 e.g. Button btnAdd; e.g. TextBox txtUsername; e.g. ListBox lstFileNames; e.g. Panel panelInfo; ?.对于函数参数.局部变量.私有及受保护字段的命名采用Camel规则(首字母小写),其他的情况如命名空间.结构.类.接口.枚举.枚举项.属性.方法.事件.委托及公开的字段等都采用Pascal规则(首字母大写) ?.多使用XML文档注释,它与VS开

优秀小工具集锦

这里我对小工具的定义安装包<10M 1.GifCam(1.56M,无需安装) 官网,小巧而功能强大的录屏软件. 2.window-on-top(665KB) 官网,Windows On Top 是一个可以让任意 Windows 窗口置于顶层的小软件. 附注:发现自及说的软件这个网站[小众软件]都有啊,但是我的这些都是根据自己日常需要整理的,比较有针对性.

iOS面试小题集锦

1.Object-C有多继承吗?没有的话用什么代替? cocoa 中所有的类都是NSObject 的子类 多继承在这里是用protocol 委托代理 来实现的你不用去考虑繁琐的多继承 ,虚基类的概念.ood的多态特性 在 obj-c 中通过委托来实现. 2.Object-C有私有方法吗?私有变量呢? objective-c – 类里面的方法只有两种, 静态方法和实例方法. 这似乎就不是完整的面向对象了,按照OO的原则就是一个对象只暴露有用的东西. 如果没有了私有方法的话, 对于一些小范围的代码重

QT5学习过程的小问题集锦(平台:LinuxMint18 / Ubuntu16.04)

*** only available with -std=c++11 or -std=gnu++11 添加以下代码到*.pro文件. CONFIG += c++11 在 Qt creator 中设置 Build & Run 中的 Qt Versions 时,下方 qmake location 的下一行提示:No qmlscene installed.(图未显示该错误提示) 安装 qtdeclarative5-dev 包即可解决. 编译错误提示:connot find QAppocation (之

java review几处小问题集锦

1 线程池使用不当 我们的调度系统需要将一堆会员分配给相应的人员来处理,流程如以下伪代码所示: public void dispatch() { while (true) { List<Member> memberList = getUnassignedMemberList(); //获取所有未分配的会员 for(Member each : memberList) { singleDispatch(each); //为每一个会员分配相应的人员处理 } try { Thread.sleep(10

Xcode开发小问题集锦

Q:用Xcode 6 创建的工程在iOS 7的设备上运行时上下部均会出现黑色的区域且应用不能全屏运行. A:Targets -> General -> App Icons and Launch Images -> Launch Images Source -> 点击Use Asset Catalog -> 选择Images -> Migrate R:应该是 Xcode 6 上默认使用的 LaunchScreen.xib 并未能够很好地在 iOS 7 的系统上适应屏幕尺寸

小知识点集锦

cmd进入文件夹命令: 返回上级目录cd..就可以了 也可以直接cd 文件夹名字进入文件夹. 加上双引号可以直接进入想要的进入的文件夹 mysql 免安装配置教程 http://blog.csdn.net/wolfofsiberian/article/details/39753561 2.解压文件到D盘 当然你可以解压到其他盘符下面,但是注意最好放置在根目录下,这样可以避免一些异常的问题. 3.将mysql的bin目录路径添加到系统的path中 这台电脑---右键选择属性---高级系统设置---

[Qt小知识集锦]QT的5个基础知识,你知道几个

1 你不能调用QObject的拷贝构造函数和赋值运算符 QObject A: QObject B(A); 错误. QObject A: QObject B: B = A: 也是错误. 2 QPointer能够帮你自动管理指针 QPointer引用了QObject对象,删除被引用对象后,不管是否显示设置其为0,都能够自动归零: QLabel *pLabel = new QLabel(); QPointer<QLabel> label = pLabel; deletepLabel; qDebug(