C
语言常见问题集
原著:Steve
Summit
翻译:朱群英, 孙 云
修订版
0.9.4, 2005
年
6
月
23
日
版权所有
c 2005
目½
目½
前言
1
声明和初始化
1.1
1.2
1.3
1.4
1.5
1.6
我如½决定½用那种整数类型?
. . . . . . . . . . . . . . . . . . .
64
½机上的
64
½类型是什么样的?
. . . . . . . . . . . . . . . .
怎样定义和声明全局变量和½数最½?
. . . . . . . . . . . . . . .
extern
在½数声明中是什么意思?
. . . . . . . . . . . . . . . . .
关键字
auto
到底有什么用途?
. . . . . . . . . . . . . . . . . . .
我似乎不½成功定义一个链表。我试过
typedef struct
{
char
*item; NODEPTR next;
}
*NODEPTR;
½是编译器报了错误信
息。难道在C语言中一个结构不½包含指向自己的指针吗?
. . . .
怎样建立和理解非常复杂的声明?例如定义一个包含
N
个指向返
回指向字符的指针的½数的指针的数组?
. . . . . . . . . . . . . .
½数只定义了一次, 调用了一次, ½编译器提示非法重定义了。
. .
main()
的正确定义是什么?
void main()
正确吗?
. . . . . . . . .
对于没有初始化的变量的初始值可以½怎样的假定?如果一个全
局变量初始值为
“零”,
它可否½为空指针或浮点零?
. . . . . . .
代码
int f()
{
char a[] =
"Hello,
world!";}
不½编译。
. . . . . . .
这样的初始化有什么问题?char
*p = malloc(10);
编译器提示
“非
法初始式” 云云。
. . . . . . . . . . . . . . . . . . . . . . . . . . .
以下的初始化有什么区别?char
a[] =
"string
literal"; char *p =
"string
literal";
½我向
p[i]
赋值的时候, 我的程序崩溃了。
. . . .
我总算弄清除½数指针的声明方法了, ½怎样才½初始化呢?
. .
i
xvii
1
1
1
2
2
2
3
3
4
4
4
5
5
5
5
7
7
7
7
7
7
1.7
1.8
1.9
1.10
1.11
1.12
1.13
1.14
2
结构、联合和枚举
2.1
2.2
2.3
2.4
2.5
声明
struct x1
{
. . .
};
和
typedef struct
{
. . .
}
x2;
有什么不同?
.
为什么
struct x
{
. . .
};
x thestruct;
不对?
. . . . . . . . . . . . .
一个结构可以包含指向自己的指针吗?
. . . . . . . . . . . . . . .
在
C
语言中实现½象数据类型什么方法最½?
. . . . . . . . . . .
在
C
中是否有模拟继承等面向对象程序设计特性的½方法?
. . .
i
目½
2.6
我遇到这样声明结构的代码:
struct name
{
int namelen; char
namestr[1];};
然后又½用一些内存分配技巧½
namestr
数组用起
来½像有多个元素。这样合法和可移植吗?
. . . . . . . . . . . .
是否有自动比较结构的方法?
. . . . . . . . . . . . . . . . . . . .
如½向接受结构参数的½数传入常数值?
. . . . . . . . . . . . . .
怎样从/向数据文件读/写结构?
. . . . . . . . . . . . . . . . . . .
我的编译器在结构中留下了空洞, 这导致空间浪费而且无法与外
部数据文件进行
”二进制”
读写。½否关掉填充, 或者控制结构域
的对½方式?
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
为什么
sizeof
返回的值大于结构的期望值, 是不是尾部有填充?
. .
如½确定域在结构中的字节偏移?
. . . . . . . . . . . . . . . . .
怎样在运行时用名字访问结构中的域?
. . . . . . . . . . . . . . .
程序运行正确, ½退出时却
“core dump”了,怎么回事?
. . . . .
可以初始化一个联合吗?
. . . . . . . . . . . . . . . . . . . . . . .
枚举和一组预处理的
#define
有什么不同?
. . . . . . . . . . . .
有什么容易的显示枚举值符号的方法?
. . . . . . . . . . . . . . .
ii
8
8
8
9
2.7
2.8
2.9
2.10
9
9
9
10
10
10
10
11
13
2.11
2.12
2.13
2.14
2.15
2.16
2.17
3
表达式
3.1
3.2
3.3
3.4
3.5
3.6
3.7
3.8
3.9
3.10
3.11
3.12
为什么这样的代码:
a[i] = i++;
不½工½?
. . . . . . . . . . . .
½用我的编译器,下面的代码
int i=7; printf("%d\n", i++ * i++);
返回
49?不管按什么顺序计算,
难道不该打印出56吗?
. . . . . .
对于代码
int i = 3; i = i++;
不同编译器给出不同的结果, 有的为
3,
有的为
4,
哪个是正确的?
. . . . . . . . . . . . . . . . . . . . .
这是个巧妙的表达式:
a ˆ= b ˆ= a ˆ= b
它不需要临时变量就可
以交换
a
和
b
的值。
. . . . . . . . . . . . . . . . . . . . . . . . .
我可否用括号来强制执行我所需要的计算顺序?
. . . . . . . . . .
可是
&&
和
||
运算符呢?我看到过类似
while((c = getchar()) !=
EOF && c !=
’\n’)
的代码 ……
. . . . . . . . . . . . . . . . . .
我怎样才½理解复杂表达式?“序列点” 是什么?
. . . . . . . . .
那么, 对于
a[i] = i++;
我们不知道
a[]
的哪一个分量会被改写,½
i
的确会增加
1,
对吗?
. . . . . . . . . . . . . . . . . . . . . . . . .
++i
和
i++
有什么区别?
. . . . . . . . . . . . . . . . . . . . . .
如果我不½用表达式的值, 我应该用
++i
或
i++
来自增一个变量
吗?
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
为什么如下的代码
int a = 100, b = 100; long int c = a * b;
不½
工½?
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
我需要根据条件把一个复杂的表达式赋值给两个变量中的一
个。可以用下边这样的代码吗?
((condition) ? a : b) = compli-
cated expression;
. . . . . . . . . . . . . . . . . . . . . . . . . . .
13
13
14
14
14
14
15
15
15
15
15
16
目½
4
指针
4.1
4.2
4.3
4.4
我想声明一个指针并为它分配一些空间, ½却不行。这些代码有
什么问题?char
*p; *p = malloc(10);
. . . . . . . . . . . . . . . .
*p++
自增
p
还是
p
所指向的变量?
. . . . . . . . . . . . . . . .
我有一个
char *
型指针正巧指向一些
int
型变量, 我想跳过它们。
为什么如下的代码((int
*)p)++;
不行?
. . . . . . . . . . . . . .
我有个½数,它应该接受并初始化一个指针
void f(int *ip)
{
static
int dummy = 5; ip = &dummy;}
½是½我如下调用时:
int *ip;
f(ip);
调用者的指针却没有任½变化。
. . . . . . . . . . . . . . .
我½否用
void**
指针½为参数, ½½数按引用接受一般指针?
. .
我有一个½数
extern int f(int *);
它接受指向
int
型的指针。我怎
样用引用方式传入一个常数?下面这样的调用
f(&5);
似乎不行。
.
C
有
“按引用传递”
吗?
. . . . . . . . . . . . . . . . . . . . . . .
我看到了用指针调用½数的不同语法½式。到底怎么回事?
. . .
我怎样把一个
int
变量½换为
char *
型?我试了类型½换, ½是不
行。
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
iii
17
17
17
17
18
18
18
18
19
19
21
21
21
22
23
23
23
24
24
24
24
25
25
26
26
4.5
4.6
4.7
4.8
4.9
5
空
(null)
指针
5.1
5.2
5.3
5.4
5.5
5.6
5.7
5.8
5.9
5.10
5.11
5.12
5.13
5.14
臭名昭著的空指针到底是什么?
. . . . . . . . . . . . . . . . . . .
怎样在程序里获得一个空指针?
. . . . . . . . . . . . . . . . . . .
用缩写的指针比较
“if(p)”
检查空指针是否可靠?如果空指针的内
部表达不是
0
会怎么样?
. . . . . . . . . . . . . . . . . . . . . . .
NULL
是什么, 它是怎么定义的?
. . . . . . . . . . . . . . . . . .
在½用非全零½为空指针内部表达的机器上,
NULL
是如½定义
的?
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
如果
NULL
定义成
#define NULL ((char *)0)
难道不就可以向½
数传入不加½换的
NULL
了吗?
. . . . . . . . . . . . . . . . . .
如果
NULL
和
0
½为空指针常数是等价的, 那我到底该用哪一个
呢?
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
½是如果
NULL
的值改变了, 比如在½用非零内部空指针的机器
上, 难道用
NULL (而不是 0)
不是更½吗?
. . . . . . . . . . . . .
用预定义宏
#define Nullptr(type) (type *)0
帮助创建正确类型的
空指针。
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
这有点奇怪。NULL 可以确保是
0,
½空
(null)
指针却不一定?
. .
为什么有那么多关于空指针的疑惑?为什么这些问题如此经常地
出现?
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
我很困惑。我就是不½理解这些空指针一类的东西。
. . . . . . .
考虑到有关空指针的所有这些困惑, 难道把要求它们内部表达½
必须为
0
不是更简单吗?
. . . . . . . . . . . . . . . . . . . . . . .
说真的, 真有机器用非零空指针吗, 或者不同类型用不同的表达?
评论