C is Interesting

November 14, 2014
C

最近偶尔看C语言,看了一点有意思的东西。

  • C语言里函数声明有一个很有意思的现象:

如果一个函数没有float, short, 或者char类型的参数,在函数生命中完全可以省略 参数类型的说明(但是函数定义中不可以省略)。

也就是说有一个函数定义:

double double(double a)
{
	return a * a;
}

那么这个函数可以声明为:

double square();

这个规则好像是为了兼容旧版本的C吧。

  • 一个例子:
/*
 * =====================================================================================
 *       Filename : type_scanf.c
 *    Description : This program outputs differently on different systems.
 *    Version     : 
 *        Created : 11/12/14 22:45
 *         Author : Liu Xue Yang (LXY), liuxueyang457@163.com
 *         Motto  : Suicide is Painless
 * =====================================================================================
 */
#include <stdio.h>
main()
{
	int i;
	char c;

	for ( i = 0; i < 5; ++i ) {
		scanf ( "%d", &c );
		printf ( "%d\n", i );
	}
	printf ( "\n" );
}

这个函数的输出是什么呢? 仔细想一想,其实一种情况的输入和输出如下:

c~>./type_scanf 
1
0
2
0
128
0
256
1
512
2
3
4

从这个输出可以看出,编译器把整型i放到了char型c的后面,这个系统是小端存储。说起这个小 端和大端,那天看到一本书这么解释,我感觉比较好:

小端存储就是小端优先,先存数值的低位,也就是小的一端;
大端存储就是大端优先,先存数值的高位,也就是大的一段;

以前总是搞不清或者搞反了,这次记住了。。。另外就是,写个程序判断当前系统是小端还是大端 其实也是很简单的。思想就是利用指针的强制类型转换。这里不写了,以后也许补上,我还要早睡。

我自己想到一个问题:

举出几个例子,使得体现“本来错误的程序因为某种巧合却能够工作”这一点。

其实有很多吧,先放到这里,以后再加上。

在某些系统中,下面的程序打印出%g,这是为什么呢?

#include <stdio.h>
main()
{
	printf("%g\n", sqrt(2));
}

这个问题在C陷阱里面解释的很好,恍然大悟。

  • 宏定义

我觉得最容易出错的一点就是,在一个宏里面,一个变量被求值超过一次,这是很危险的。举 个简单的例子,经常看到有人这么写:

#define max(a,b) ((a) >(b) ? (a) : (b))

万一有个倒霉蛋类似于下面这么用,那结果就不对了咯。

int a[10];
int *p = a;
int n;
int tmp = max(*p++, n);

还有很多种情况,因为多次求值而出现问题的,比如,早期的库函数toupper有一种宏实现:

#define toupper(c) \
	((c) >= 'a' && (c) <= 'z' ? (c) - 'a' + 'A' : (c))

这个也同样存在问题。

宏另外还有一个要注意的问题是,宏定义时候的空格!比如:

#define f (x) ((x) - 1)
#define g(x) ((x) - 1)

这两个完全不一样哦!但是,调用的时候却没有这个规则,也就是说我们可以:

int a = 1;
g(a) == g (a)
  • typedef

一个很早之前就知道的一件事儿是:

#define FOO struct foo *
typedef struct foo * PFOO;

FOO a, b;
PFOO c, d;

a是指针,b是结构。c,d都是指针。道理很简单。

  • 有符号整数的向右移位运算并不等同于除以2的某次幂。(-1)>>1一般不可能是0(gcc上结果是-1),但是(-1)/2却一般都是0.

  • 关于取余。

q = a / b; r = a % b; 不妨假设b > 0;

我们一般希望满足三点:

1. q * b + r == a
2. 若改变a的正负号,那么这会改变q的符号,但是q的绝对值不变
3. 当b > 0 时,r >= 0 && r < b

有趣的是,这三个性质不可能同时成立。这货明天再写,今天晚了,我要早睡!23:26了。。。。

最后两句:

以前看书都不怎么做笔记的,偶尔拿起钢笔写字才想起来自己很久不好好写字了,干脆读书的时候写写笔记什么的吧。然后就入了两个英雄616做读书笔记,这笔确实品控差,所以入了pilot 78G和lamy Safari。没舍得入鱼水,入了百利金。

最近校招。不想多说什么,招人不容易,求职也不容易。

这篇博客未完,先放在这里,以后有时间再说吧。睡觉了。。。。早睡早起。身体最重要。

comments powered by Disqus