C语言easy忽视的细节(第四部分)

前言:本文的目的是记录C这些语言easy忽视的细节。我会每天花一点时间来阅读整理,坚持下去,今天是第一章。也许今天是下个月的第二,明年,今天是第几?……我坚信,,记性不如烂笔头。第四篇了。fight~...


第一篇链接:C语言中easy被忽略的细节(第一篇)

第二篇链接:C语言中easy被忽略的细节(第二篇)

第三篇链接:C语言中easy被忽略的细节(第三篇)


1、void*类型的指针不能參与算术运算。仅仅能进行赋值、比較和sizeof操作的原因?

指针的算术运算还要包括指针所指对象的字节数信息。



2、不能把“&”单独用于一个非变量的东西。不能对字面常量使用“&”来取其地址,由于字面常量保存在符号表中。没有地址概念。数组名是一个指针常量。不能改动数组名的值。比例如以下面语句1与语句2是等价的:

int a[10];                  //语句1
int *const a;               //语句2

int b[3][4];                //语句1
int (*const b)[4];          //语句2

int c[3][4][5];             //语句1
int (*const c)[4][5];       //语句2


3、return 0与exit(0)的几点差别

(1)exit结束正在执行的整个程序,仅仅要调用exit就结束,它将參数返回给OS。把控制权交给操作系统;return退出当前函数,返回函数值,把控制权交给调用函数;

(2)exit是系统调用级别。它表示一个进程的结束。return是语言级别的。它表示调用堆栈的返回。

(3)main函数结束时也会隐式地调用exit函数,它将删除进程使用的内存空间,同一时候把错误信息返回给父进程。

(4)main函数返回一个整型值与该值调用exit是等价的。


4、static修饰符是一个可以降低命名冲突的实用工具。比如:static int a;将a的作用域限制在一个源文件内。对于其它源文件,a是不可见的。

可以在多个源文件里定义同名的变量a,仅仅要全部的变量a都被定义为static,或者仅仅仅仅有当中一个变量不是static。

static修饰符也适用于函数。


5、C语言同意程序猿写操作前控制产生的输出数据量,这样的控制能力是通过库函数setbuf实现的。比如:setbuf(stdout, buf);语句将通知输入/输出库,全部写入到stdout的输出都使用buf作为输出缓冲区。直到buf缓冲区被填满或程序猿直接调用fflush,buf缓冲区的内容才实际写入到stdout中。

缓冲区的大小由系统头文件<stdio.h>中的BUFSIZ定义。《C陷阱与缺陷》中有一个样例:

#include <stdio.h>

int main(void)
{
	char c;
	char buf[BUFSIZ];
	setbuf(stdout, buf);
	while ((c = getchar()) != EOF)
		putchar(c);

	return 0;
}

以上程序是错误的。

buf缓冲区最后一次被清空是在main函数结束之后,作为程序交回控制给操作系统之前C执行时库所必须进行清理工作的一部分。在此之前buf字符数组已经被释放了。改动的方法有3种:

(1)定义缓冲数组为静态数组static char buf[BUFSIZ];

(2)将缓冲数组拿到main函数外;

(3)动态分配缓冲区。程序中并不主动释放分配的缓冲区。setbuf(stdout, malloc(BUFSIZ));

备注:

(1)因为缓冲区是动态分配的,所以main函数结束时并不会释放该缓冲区。这样C执行时库进行清理工作时就不会发生缓冲区已释放的情况。

(2)假设malloc调用失败,返回NULL指针,此时标准输出不须要进行缓冲。

(3)对于由写操作打开的文件,调用fflush将导致输出缓冲区的内容被实际地写入该文件。


6、为什么向函数传递多维数组时候不须要说明第一维长度而必须说明其它维长度?

(1)数组元素在内存中依照“行优先”规则存储。须要列数确定一行有多少元素;

(2)编译器在计算元素地址时不须要数组第一维的长度,但须要全部其它维的长度信息;

(3)C/C++不正确数组进行越界訪问检查。对编译器来说不须要知道第一维的长度。


7、C语言将多维数组转换为数组指针。

下面4种表达方式是等价的:

a[i][j];
*(a[i] + j);
(*(a + i))[j];
*(*(a + i) + j);

8、在语义上。下标操作符返回的是一个元素的引用。

比如语句1和语句2是等价的:

//语句1
a[3] = 100;		

//语句2
int &ri = a[3];
ri = 100;

9、不能使用一个元素类型的指针来接收动态创建的多维数组的返回地址。由于一个多维数组在语义上并不等价于一个指向其元素类型的指针。它等价于一个“指向数组的指针”。比例如以下面使用方法是正确的:

char *q = new char[5];
delete []q; 

char (*p)[4] = new char[5][4];
delete []p;

10、(1)标号(lable)是具有函数作用域的唯一一种标识符。

不管标号定义在函数哪行,函数内嵌套多深,它都能在函数体内不论什么一个地方訪问到。标号一般用在goto语句中,假设goto语句没有使用到该标号,那么该标号将被忽略。(2)当局部变量与某一个全局变量同名时,在函数内部将遮蔽该全局变量。在这一点上是美元范围解析运算符来引用全局变量的一个函数里,例如::a。

版权声明:本文博主原创文章,博客,未经同意不得转载。

posted @ 2015-09-14 16:57  lcchuguo  阅读(343)  评论(0编辑  收藏  举报