1 关于很少使用的goto
goto语句不能跨越变量的定义语句向前跳转,但向后跳过已经执行的变量定义语句则是合法的。
向前跳过未执行的变量定义语句,意味着变量可能在没有定义的情况下使用。
向后跳回到一个变量定义之前,则会使系统撤销这个变量,然后再重新创建它。
goto 确实不是太好的idea,能少用还是少用吧。
2 关于空字符 '\0'
NUL解释说明ASII表中当前描述的字符是一个空字符,它不是一个真正的字符,只是一个human语言的空字符表达,所以我们代码中是不会出现NUL的使用,只会用0或'\0'。
转义字符'\0' 就是表示空字符,即符'\0' 是空字符NUL含义的对应字符;但是与指针空置NULL不是一个东西,后者只用于指针。
同时表示空字符含义的字符 在ASCII码表中对应的十进制的值为0,所以十进制0, 转义字符'\0'二者等价。
即0和'\0'都是表示空字符的意思,0是十进制表示的空字符, '\0'是字符表示的空字符。
所以初始化字符数组时可如下:
char str[20] = {0};
空字符和空格是两个不同的东西,空字符'\0'的ASII码十六进制为0x00,空格' '的ASII码十六进制为0x20
C语言转义字符表
转义字符 | 意义 | ASCII码值(十进制) |
\a | 响铃(BEL) | 007 |
\b | 退格(BS) | 008 |
\f | 换页(FF) | 012 |
\n | 换行(LF) | 010 |
\r | 回车(CR) | 013 |
\t | 水平制表(HT) | 009 |
\v | 垂直制表(VT) | 011 |
\\ | 反斜杠 | 092 |
\? | 问号字符 | 063 |
\' | 单引号字符 | 039 |
\" | 双引号字符 | 034 |
\0 | 空字符 | 000 |
\ddd | 任意字符 | 三位八进制 |
\xhh | 任意字符 | 二位十六进制 |
标准ASCII表
Bin | Dec | Hex | 缩写/字符 | 解释 |
00000000 | 0 | 00 | NUL | 空字符 |
00000001 | 1 | 01 | SOH(start of headling) | 标题开始 |
00000010 | 2 | 02 | STX (start of text) | 正文开始 |
00000011 | 3 | 03 | ETX (end of text) | 正文结束 |
00000100 | 4 | 04 | EOT (end of transmission) | 传输结束 |
00000101 | 5 | 05 | ENQ (enquiry) | 请求 |
0010 0000 32 20 (space) 空格
3 linux中错误码errno
错误码可以通过函数strerror转换为人可读的错误信息
#include <errno.h>
cout << strerror(errno) << endl;
4 用memset来赋值只包含基本数据类型的数据的strcut
struct A
{
char cName[6];
int i;
float scale;
}test;
memset(&test,0,sizeof(struct A));
由于char和int是相互可以转换的,所以十进制0对于char类型就是空字符NULL,
对于int类型就直接为0,对于folat类型就是0.0了。
Tips:
对于结构体中如果有类,并且类中含有虚函数或是深拷贝,或是结构体中有string等c++类型之类的就不能用memset来赋值struct。因为struct实例test在定义时,可能会生成了虚函数表的指针或是new出来了内存并赋值给成员指针。这时用memset赋值,就可能冲掉实例test中虚函数指针或是内存指针。
5 string的c_str()方法,一般如果最好是将c_str()和strcpy ()一起使用,即用后者将c_str()的c字符串拷贝到定长的char数组中,然后再对这个定长数组进行操作。
为什么要这么做呢?因为c_str()得到的c串的指针是只读的,是不能做写的操作(如果写的话,会得到不是你期待的结果,stl里面做了手脚吧),而且对str进行添加或是删除元素时都会改变string对象的内存结构,这样先前c_str()得到的临时指针也就无效了。
6 static member variable usage
class MyPlugin
{
public:
static MyPlugin& GetInstance()
{
static MyPlugin plugin; -----这是函数中的一个静态局部变量,局部静态变量只是在第一次执行时初始化,以后再次执行到此函数时,不再执行初始化。而且是存放在全局数据区,值一直保存着。
return plugin;
};
……
}
7 NULL 定义
/usr/include/linux下的stddef.h文件中的NULL定义:
#undef NULL
#if defined(__cplusplus)
#define NULL 0 ----c++中,为0
#else
#define NULL ((void *)0) ---c中,为void*类型指针
NULL不是被定义为0,就是被定义为(void *)0,这两种值几乎是相同的。当程序中需要一个指针时(尽管编译程序并不是总能指示什么时候需要一个指针),一个纯粹的零或者一个void指针都能自动被转换成所需的任何类型的指针。
8 c语言中变量的定义位置
在标准的c89中规定变量定义必须放在所有的执行语句之前,否则c编译器编译会报错。
不过在c99和c++中则没有这个问题,变量可以在程序任意位置定义。
gcc有很多扩展功能,可以完美支持c99标准。所以对于支持c99标准的c编译器就不会有此限制了。
9 bool和BOOL区别
typedef int BOOL;
#ifndef FALSE
#define FALSE 0
#endif
#ifndef TRUE
#define TRUE 1
#endif
1、类型不同
BOOL为int型
bool为布尔型
2、长度不同
bool只有一个字节
BOOL长度视实际环境来定,一般可认为是4个字节
3、取值不同
bool取值false和true,是0和1的区别
BOOL取值FALSE、TRUE或其他任意int类型值。
二:
bool是标准C++数据类型,可取值true和false。单独占一个字节,
如果数个bool对象列在一起,可能会各占一个bit,这取决于编译器。
BOOL是微软定义的typedef int BOOL。与bool不同,它是一个三值逻辑
BOOL a = 6;
if (TRUE == a) //此条件是不成立的,6!=1
{
//条件成立
int b = 0;
}
10 为什么一般二进制数据操作的时候都是用char数组呢?
个人觉得最主要的原因是因为解析一串二进制数据的时候,往往需要按字节或几个字节为单位来解析。这样如果是把二进制数据放在char数组中,可以根据char数组指针简单移位就可以解析以任意个字节为单元的数据了。方便!
另外一个原因,char数组的最小单元就是一个byte,按物理内存中的实际顺序存放,不存在字节序的问题。但是,假如用int来表示二进制,跨平台的时候那么会带来字节序的问题。
11. C++中有了malloc/free,为什么还需要new/delete?
C++中有了malloc/free,为什么还需要new/delete?
malloc与free是C++/C语言的标准库函数,new/delete是C++的运算符。它们都可用于申请动态内存和释放内存。
对于非内部数据类型的对象而言,光用malloc/free无法满足动态对象的要求。对象在创建的同时要自动执行构造函数,对象在消亡之前要自动执行析构函数。由于malloc/free是库函数而不是运算符,不在编译器控制权限之内,不能够构把造函数和析构函数的任务强加于malloc/free。
用malloc函数需要指定内存分配的字节数并且不能初始化对象,new 会自动调用对象的构造函数。delete 会调用对象的destructor,而free 不会调用对象的destructor.
因此c++语言需要一个能完成内存分配和初始化工作的运算符new,以及一个能完成清理与释放内存工作的运算符delete。new/delete不是库函数,而是运算符。
本文摘自《程序员面试宝典》
12 查看Make详细帮助文档
sudo apt-get install make-doc -----安装make文档
info make ---查看make的文档
info是一个文档格式,也是阅读此格式的一个阅读器,info命令的用法:
http://www.examw.com/linux/all/146595/
13 string转化大小写(C++)
如何将一个字符串转换成大写或者小写?这是字符串匹配中经常需要做的事情,然而C++的Standard Library并没有提供将std::string转成大写和小写的功能,只提供了将char转成大写(toupper)和小写(tolower)的功能而已。但我们可以利用STL的transform配合toupper/tolower,完成std::string转换大(小)写的功能。
transform(s.begin(),s.end(),s.begin(),::toupper);
::toupper为c库里的全局作用域的c函数