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。没舍得入鱼水,入了百利金。
最近校招。不想多说什么,招人不容易,求职也不容易。
这篇博客未完,先放在这里,以后有时间再说吧。睡觉了。。。。早睡早起。身体最重要。