C语言中容易被忽略的细节(第四篇)

前言:本文的目的是记录C语言中那些容易被忽略的细节。我打算每天抽出一点时间看书整理,坚持下去,今天是第一篇,也许下个月的今天是第二篇,明年的今天又是第几篇呢?……我坚信,好记性不如烂笔头。第四篇了,fight~...

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

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

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

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。

时间: 2024-10-16 17:50:46

C语言中容易被忽略的细节(第四篇)的相关文章

C语言中容易被忽略的细节(第二篇)

前言:本文的目的是记录C语言中那些容易被忽略的细节.我打算每天抽出一点时间看书整理,坚持下去,今天是第一篇,也许下个月的今天是第二篇,明年的今天又是第几篇呢?--我坚信,好记性不如烂笔头. 第一篇链接:C语言中容易被忽略的细节(第一篇) 1.C语言中只有一维数组,而且数组的大小必须在编译期就作为一个常数确定下来.C语言中数组元素可以是任何对象,也可以是另外一个数组,即数组的数组. 2.C语言允许初始化列表出现多余的逗号.例如:int days[] = {1,2,3,};作用:方便自动化生成代码.

C语言中容易被忽略的细节(第一篇)

前言:本文的目的是记录C语言中那些容易被忽略的细节.我打算每天抽出一点时间看书整理,坚持下去,今天是第一篇,也许下个月的今天是第二篇,明年的今天又是第几篇呢?--我坚信,好记性不如烂笔头. 1. 在C语言中,符号之间的空白(包括空格符.制表符或换行符)将被忽略.但一个符号的中间不能有空白,否则可能被解释为另一个或几个符号.以下两种写法是等价的: //写法1 if (x > big) big = x; //写法2 if ( x > big ) big = x ; 2.编译器将程序分解为符号的&q

C语言中容易被忽略的细节(第三篇)

前言:本文的目的是记录C语言中那些容易被忽略的细节.我打算每天抽出一点时间看书整理,坚持下去,今天是第一篇,也许下个月的今天是第二篇,明年的今天又是第几篇呢?--我坚信,好记性不如烂笔头.第三篇了,fight~... 第一篇链接:C语言中容易被忽略的细节(第一篇) 第二篇链接:C语言中容易被忽略的细节(第二篇) 1.__attribute__((noreturn)) __attribute__可设置函数属性.变量属性和类型属性.__attribute__((noreturn))设置了函数属性,n

程序猿之---C语言细节26(C语言中布尔类型、continue细节、sizeof举例、strlen举例)

主要内容:C语言中布尔类型.continue细节.sizeof举例.strlen举例 一.布尔类型 可能很多人不知道现在C语言已经有了布尔类型:从C99标准开始,类型名字为"_Bool" 在C99标准之前我们常常自己模仿定义布尔类型,常见有以下几种方式: 1.方式一 #define TURE 1 #define FALSE 0 2.方式二 typedef enum {false, true} bool; 3.方式三 typedef int bool 闲int浪费内存,对内存敏感的程序使

C语言中变量存储类型有哪些?

变量的存储类型是C语言的重要组成部分,也是C语言学习的基础.那C语言中变量的存储类型有哪几种呢?在编程过程中又该怎样运用呢?就这一问题,我今天给大家介绍一下!总的来说,C语言中变量的存储类型可以分为四种,他们分别是自动变量.静态变量.外部变量和寄存器变量这四种,他们的说明符依次是:auto.static.extern和register. 一.auto auto称为自动变量. 局部变量是指在函数内部说明的变量(有时也称为自动变量).用关键字auto进行说明,当auto省略时,所有的非全程变量都被认

C语言中一些乱七八糟的用法与细节(不断更新)

用C语言比较多,这篇是平时攒下的.有些内容在工作后可能会很常见,但是不用容易忘,所以就写篇博客吧. 一.printf的用法 %*可以用来跳过字符,可以用于未知缩进.像下面一样. for(i = 1; i < 10; i++) { printf("%*c\r%*c\n",  9 - abs(i - 5), '*', abs(i - 5) + 1, '*'); } %[]可以用来读取指定的内容,%[^]可以用来忽略指定内容(正则表达式?) %m可以不带参数,输出产生的错误信息 二.关

Java中容易被你忽略的细节(一)

1.在一个程序当中代码段访问了同一个对象从单独的并发的线程当中,那么这个代码段叫"临界区" 怎么解决呢:使用同步的机制对临界区进行保护 同步的两种方式:同步块和同步方法 对于同步来说都是使用synchronized方法 每一个对象都有一个监视器,或者叫做锁. java用监视器机制实现了进程之间的异步执行 2.Struts框架基于MVC模式 Struts的工作流程: 在web应用启动时就会加载初始化ActionServlet,ActionServlet从 struts-config.xm

职场中你忽略的细节,都是别人晋升的秘密

作为职场新人,在职场这门学问中,我们都还没有入门,这是我听完曹政老师的知识星球年终福利课<职场的真相>之后的感悟,曹政老师这门课针对的就是我们这样的职场新人,在课中曹政老师讲述了他自己当年在职场中所犯的错误并且指导年轻人该如何在职场中前行,虽然里面的不少观点在曹政老师的很多公众号文章中有提到过,但是经过曹政老师整理和解读之后,收获很多,这两天我也是反复的听,希望自己可以多吸收一点,在职场中走的顺利一些. 职场中不知道你是否跟我一样,有不少费解的地方,比如为什么我的技术明明比他强,但是他晋升的比

c语言中会遇到的面试题

预处理器(Preprocessor) 1 . 用预处理指令#define 声明一个常数,用以表明1年中有多少秒(忽略闰年问题)         #define SECONDS_PER_YEAR (60 * 60 * 24 * 365)UL我在这想看到几件事情:1) #define 语法的基本知识(例如:不能以分号结束,括号的使用,等等)2)懂得预处理器将为你计算常数表达式的值,因此,直接写出你是如何计算一年中有多少秒而不是计算出实际的值,是更清晰而没有代价的.3) 意识到这个表达式将使一个16位