你必须知道的495个c语言问题(笔记)
1.1我该如何决定使用哪种整数类型?
用到较大的数用long;空间很重要(例如有很大的数组或很多的结构)用short;此外用int。
win32:
int 32bit 4byte
char 8bit 1byte
short 16bit 2byte
long 32bit 4byte
float 32bit 4byte
double 64bit 8bit
注:wchar_t在Windows中是2byte,在Linux中是4byte
1.2为什么不精确定义标准类型的大小?
C语言认为对象的具体大小应该由具体的实现来决定
1.4新的64位机上的64位类型是什么样的?
long long
1.10同一个静态(static)函数或变量的所有声明都必须包含static储存类型吗?
语言标准没有严格规定这一点,最安全的做法是让static一致的出现在定义和声明中
1.11extern在函数声明中是什么意思?
比较正规的写法;
a.告诉编译器建立外部链接;
b.告诉读程序的人,去别的文件找
其实你不写extern,编译器也知道去外面找。
typedef:定义新的类型名称
1.13typedef和define有什么区别?
typedef能更好的处理指针
const:静态,常量(只读变量)
1.24我在一个文件中定义了一个extern的数组,然后在另一个文件中使用:
file1.c file2.c
int array[] = {1, 2, 3}; extern int array[];
为什么在file2中,sizeof娶不到array的大小?
未指定大小的extern数组是不完全类型,不能对它使用sizeof
1.31对于没有显示初始化的变量的初始值可以怎样的假定?如果一个全局变量初始值为“零”,它可否作为空指针或浮点零?
具有静态(static)生存周期的末初变化量(即函数声明外的变量和静态存储类型的变量)可以确保初始值为零。
具有动态生存周期的变量(即非静态存储类型的局部变量)如果没有显示的初始化,则包含的是垃圾内容。
1.33下面的初始化有什么问题?编译器提示“invalid initializers”或其他信息?
char *p = malloc(10);
初始中函数调用只能出现在自动变量(即局部非静态变量)。
1.34以下初始化有什么区别?
char a[] = "string literal";
char *p = "string literal";
a.a[]分配了15个字节内存,去存储string literal;而p分配的是string literal的地址。
b.前者内容可变,而后者不可变(因为后者被定义为了const char *)。
2.9为什么不用内建的==和!=操作符来比较结构?
a.==和!=是简单的按字节比较,因为内存的值合理对齐时,机器的访问效率非常高效。因此结构体中会按字符类型对齐,因此会留下没有使用的空洞。使简单的按字节
比较不能实现。
b.就算能够实现,也会产生大量难以接受的代码。
2.23枚举和一组预处理的#define有什么不同?
c标准规定枚举为整型,枚举常量为int型。
表达式取值顺序:编译器有相对自由的选择权,编译器选择的顺序通常并无实质影响。
3.4设计一个巧妙的表达式:
a ^= b ^= a ^= b;
它不需要临时变量就可以交换a和b的值。
3.8为什么表达式
printf(“%d %d”,f1(), f2());
先调用f2?我觉得逗号表达式应该确保从左到右的求值顺序。
printf函数对参数的计算是从右到左,输出是从左到右。
3.9
a.在一个表示式中对同一个对象进行2次或2次以上的修改(未定义)
eg:printf(“%d\n”, i++ * i++);
在一个表达式中对i进行了两次修改
b.右边一个对象对自身进行修改时,不能同时出现在左边。
eg: i = i++;
3.16
对类型的转换应该是作用于一个数上的
eg: long int c = (long int)a * b;
void **:二级指针指向另一个指针的地址
void *:一级指针指向一个变量的地址
(void **)&a:讲变量a的地址强制 为void **型指针,即认为a是指针变量并取这个指针变量的地址。将这个地址强制为忽略原有类型只有地址的指针
4.13通用指针是什么?当我把函数指针赋向void *类型的时候编译通不过。
没有通用指针,void *指针只能保存对象(也就是数据)指针(普通指针),将函数指针转换为void *指针是不可移植的。
5.1空指针到底是什么?
空指针不指向任何对象或函数;
未初始化的指针则可能指向任何地方。
5.4 NULL是什么,它怎么定义的?
#define NULL ((void *) 0)
空指针不是指向0地址的指针,而是什么都不指向(或者说它指向一个为空的虚无空间)。但是访问0地址的指针却要考虑空指针的影响。
6.4既然他们不同,那么为什么作为函数形参的数组和指针声明可以互换呢?
由于数组会马上退化为指针,数组事实上从来没有传入到函数。允许指针参数声明为数组只不过是为让它看起来好像传入了数组。形参的数组,在编译器中都被当做
指针来处理,因此在传入数组的时候,函数接收到的正是指针。
char *型指针可以直接赋值其他不行
eg:char *p = "abc"; (正确)
int *i = 123; (错误)
7.19为什么malloc返回了离谱的指针值?我的确读过7.9,而且在调用之前包含了extern void *malloc();声明。
malloc分配的空间不能超过前面字符类型所能容纳的范围大小
7.24动态分配的内存一旦释放之后就不能再使用?
是的,因为它被保留给后续程序使用,没有返还给系统。见7.29。
7.25为什么在调用free()之后指针没有变空?使用(赋值,比较)释放之后的指针有多么不安全?
当你调用free()的时候,传入的指针指向的内存被释放,但调用函数的指针值可能保持不变,因为c的按值传参的语义意味着被调函数永远不会永久改变参数的值。
通常最好在释放之后立即把它们置为NULL。
7.29我有个程序分配了大量的内存,然后又释放了。但从操作系统看,内存的占用率却没有变回去。
多数malloc/free的实现并不把释放的内存返回给操作系统。而是留着供同一程序的后续malloc使用
8.9我注意到sizeof(‘a’)是4而不是1(既不是sizeof(char)),是不是我的编译器有问题?
c语言中的字符常量是int型(c语言中将char按int型来存储:ASCII值),因此sizeof('a')是sizeof(int)。sizeof(char)是1
10.3怎么写一个交换两个值的通用宏?
#define swap(a, b) (a ^= b ^= a ^= b)
10.13 sizeof(sizeof是关键字)操作符可以用在#if预处理指令中吗?
不行。预处理编译过程之前,此时尚未对类型名称进行分析。
11.9为什么不能再初始化维度中使用const值?例如:
const int n = 5;
int a[n];
const限定词的真正的含义是“只读”,用它限定的对象是运行时不能被赋值的对象。因此用const限定的对象的值并不完全是一个真正的常量。不能用作数组维度,case行表或类
似的环境。
11.10 "const char *p", "char const *p", "char * const p"有何区别?
前两者可以互换。
const char *p:内容不能被改变。(内容不变)
char * const p:p指针不能修改(地址不变)
11.13能否通过将main声明为void来关掉“main没有返回值”的警告?
不能。main函数只有两种和法的声明:
int main(void);
int main(int argc, char **argv);
12.7如何在printf的格式串中输出一个'%'字符?
只需要重复百分号:%%。
12.8为什么这么写不对?
long int n = 123456;
printf("%d\n", n);
因为printf不知道传入的数据类型所以这样要使用%ld
结合12.9理解
12.9有人告诉我不能再printf中使用%lf,为很么printf()用%f输出double型,而scanf却用%lf呢?
printf的%f说明符的确既可以输出float也可以输出double。根据“默认参数提升”规则。float型会被提升为double型。因此在printf中只能看到双精度数。
scanf它接受指针,这里没有参数提升。所以还是%f和%lf。
12.11如何用printf实现可变的域宽度?就是说,我在想运行时确定宽度而不是使用%08d?
使用printf(%*d, width, x)。
这本书太老了
你必须知道的495个c语言问题(笔记)的更多相关文章
- 你必须知道的495个C语言问题,学习体会一
C语言作为一门古老的语言,其灵活性和容易出错都让人 又爱又恨,书籍<你必须知道的495个C语言问题>,使用问答的形式,告诉读者 C语言使用的各个方面的知识,包括一些冷知识等.以下,我要摘录 ...
- C语言学习书籍推荐《你必须知道的495个C语言问题》
萨米特 (Steve summit) (作者), 孙云 (译者), 朱群英 (译者) 下载地址:点我 <你必须知道的495个C语言问题>以问答的形式组织内容,讨论了学习或使用C语言的过程中 ...
- 《你必须知道的495个C语言问题》知识笔记及补充
1. extern在函数声明中是什么意思? 它能够用作一种格式上的提示表明函数的定义可能在还有一个源文件里.但在 extern int f(); 和 int f(); 之间并没有实质的差别. 补充:e ...
- 你必须知道的495个C语言问题,学习体会四
本文,我们来学习下指针,这是个梦魇啊.无数次折磨着C语言学习者,无数次的内存泄露,无数次的访问失败,无数次的越界溢出, 这些错误造就的仅仅是一个 跟随者,真正的优秀者必须要正视语言的局限,同时在最大限 ...
- 你必须知道的495个C语言问题,学习体会三
本文是 本系列的第三篇,本文主要对C语言的表达式做个小结 先从两个坑爹的表达式说起:i++ 与++i 上大学的时候,学长告诉我,这两个表达式,意义是一样的,后来老师纠正说,还是有区别的,于是让我们记住 ...
- 你必须知道的495个C语言问题,学习体会二
这是本主题的第二篇文章,主要就结构体,枚举.联合体做一些解释 1.结构体 现代C语言编程 结构化的基石,diy时代的最好代言人,是面向对象编程中类的老祖宗. 我们很容易定义一个结构体,比如学生: st ...
- 《你必须知道的495个C语言问题》读书笔记之第11-14章:ANSI C标准、库函数、浮点数
一.ANSI C标准 1. ANSI向C语言预处理器引入了几项新的功能,包括“字符串化”操作符(#).“符号粘贴”操作符(##).#pragma指令. 2. Q:char a[3] = "a ...
- 《你必须知道的495个C语言问题》读书笔记之第8-10章:字符串、布尔类型和预处理器
一.字符和字符串 1. Q:为什么strcat(string, '!')不行? A:strcat()用于拼接字符串,所以应该写成strcat(string, "!")." ...
- 《你必须知道的495个C语言问题》读书笔记之第4-7章:指针
1. Q:为什么我不能对void *指针进行算术运算? A:因为编译器不知道所值对象的大小,而指针的算法运算总是基于所指对象的大小的. 2. Q:C语言可以“按引用传参”吗? A:不可以.严格来说,C ...
随机推荐
- 13、Spring Boot 2.x 多数据源配置
1.13 Spring Boot 2.x 多数据源配置 完整源码: Spring-Boot-Demos
- 爬取前尘无忧python职位信息并保存到mongo数据库
1.re实现 import re,os import requests from requests.exceptions import RequestException MAX_PAGE = 10 # ...
- [Luogu] LCA
https://www.luogu.org/problemnew/show/P4211 baoli #include <iostream> #include <cstdio> ...
- 1625: 【例 1】反素数 Antiprime
1625: [例 1]反素数 Antiprime [题目描述] 原题来自:POI 2001 如果一个大于等于 1 的正整数 n,满足所有小于 n 且大于等于 1 的所有正整数的约数个数都小于 n 的约 ...
- Python流程控制和缩进
我们语文学写作文,有如果- -,那么- -的句式,同样Python也有这样的句式: #如何这个条件成立了,那就执行下面这个语句 if 条件: 内容1 内容2 else: 内容3 几点说明:
- AGC009C Division into Two
题意 有\(n\)个严格升序的数,请你分成两个集合\(A\)和\(B\),其中一个集合任意两数之差不小于\(x\),另一集合任意两数之差不小于\(y\). 问方案数,集合可以为空. $n \le 10 ...
- Leetcode题目283.移动零(简单)
题目描述: 给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序. 示例: 输入: [0,1,0,3,12] 输出: [1,3,12,0,0] 说明: 必须在原 ...
- tp5 回滚事务记录,其中一条语句报错,全部回滚
#################################### 测试事务 // 启动事务 Db::startTrans(); try { //插入行为表 $data = [ 'userId' ...
- win10系统搭建vagrant时开启bios,虚拟化问题
VT-x is disabled in the BIOS的意思是VT-X虚拟化技术处于禁止关闭状态,需要在电脑主板BIOS中开启CPU虚拟化技术thinkpad重启F1进入BIOS,选择: Sercu ...
- MISS YOU
文章来源:刘俊涛的博客 欢迎关注,有问题一起学习欢迎留言.评论