注释


编译器会用空格代替代码中原来的注释,并先于预处理指令执行
/*…*/ 这种形式的注释不能嵌套
只要斜杠(/)和星号(*)之间没有空格,都会被当作注释的开始。例如这样:
y = x/*p;

\ 是一个接续符,表示断行。编译器会将反斜杠剔除掉,跟在反斜杠后面的字符自动接续到前一行。但是注意:反斜杠之后不能有空格,反斜杠的下一行之前也不能有空格。(有的编译器有空格可以通过)。\ 还能被用作转义字符的开始标识。

位运算符


交换两个变量的值:a ^= b; b ^= a; a ^= b;

0x01<<+;
// ==32
// "+"号的优先级比移位运算符的优先级高

在 32 位系统下:

0x01<<+;
0x01<<-;

左移和右移的位数不能大于数据的长度,不能小于0。(有的编译器还是可以通过的)

对于有符号数,在>>右移时,符号位将随同移动。当为正数时,最高位补0;

而为负数时,符号位为 1,最高位是补 0 或是补 1 取决于编译系统的规定。Turbo C 和很多系统规定为补 1。

常用的位操作宏:

#define  SETBIT(x, y)  ((x) |=  (y))
#define CLRBIT(x, y) ((x) &= ~(y))
#define TOGLBIT(x, y) ((x) ^= (y))
#define TESTBIT(x, y) ((x) & (y))
#define SETBIT(x, y)  ((x) |= 1<<(y))
#define CLRBIT(x, y) ((x) &= ~(1<<(y)))

花括号


char a[]{ = “abcde”};

花括号的作用就是打包。

自加减++、--


i=;
(++i)+(++i)+(++i); //未定义行为,取决于编译器
// TCC:15, VC6:16, GCC:18
i=3;
(i++)+(i++)+(i++);

自加或自减运算是在本计算单位计算结束( 遇到 , 或 ; )之后再自加或自减。

int i,j;
i=;
j=(i++,i++,i++); //j=2,i=3 i=;
j=(++i,++i,++i); //j=3

/ 和 %


有2组计算

/; (-)/; /(-); (-)/(-);
%; (-)%; %(-); (-)%(-);

优先级


. []和() 的优先级比 * 高
== 和 != 优先级高于位操作
== 和 != 优先级高于赋值符
算术运算符高于位移运算符

*p++

* 和 ++ 是同优先级,其结合方向为自右向左,因此 *p++ 等价于

*(p++)

预处理


预处理指令是编译器的功能,不是C语言的一部分。

宏定义

ANSI 标准 C 还定义了如下几个宏:
_LINE_ 表示正在编译的文件的行号
_FILE_ 表示正在编译的文件的名字
_DATE_ 表示编译时刻的日期字符串,例如: "25 Dec 2007"
_TIME_ 表示编译时刻的时间字符串,例如: "12:30:55"
_STDC_ 判断该文件是不是定义成标准 C 程序

下面的写法都是对的:

#define EMPTY
# define EMPTY

在使用宏函数的时候,宏名和参数之间的空格会被编译器忽略掉。定义宏的时候空格是有效的。

#error 预处理指令的作用是,编译程序时,只要遇到 #error 就会生成一个编译错误提示消息,并停止编译。其语法格式为:
#error error-message

#line 的作用是改变当前行数和文件名称,它们是在编译程序中预先定义的标识符。命令的基本形式如下:
#line number["filename"]

#pragma 指令的作用是设定编译器的状态或者是指示编译器完成一些特定的动作。

#和##都是预处理命令。

断言assert

#if !defined(NDBUG)
#define assert(p) if(!(p)){fprintf(stderr,\
"Assertion failed: %s, file %s, line %d\n",\
#p, __FILE__, __LINE__);abort();}
#else
#define assert(p)
#endif

main函数


无参的写法

int main(void)

有参的写法

int main(int argc, char *argv[])
int main(int argc, char **argv)

argc -- 命令行参数总个数,包括 可执行程序名

argv[0] -- 可执行程序名

argv[i] -- 第 i 个参数

例子

# ./a.out Love Live !

该例子中 argc 为4,argv[0]=a.out, argv[1]=Love, argv[2]=Live, argv[3]=!

main函数的位置

C语言规定,main函数是程序的入口。所以不管把main函数放在源程序的任意地方,都是没有错的。

数组 int a[5];


定义一个数组 a 时,编译器根据指定的元素个数和元素的类型分配确定大小的一块内存,并把这块内存的名字命名为 a
名字 a 一旦与这块内存匹配就不能被改变。a[0],a[1]等为 a 的元素,但并非元素的名字。数组的每一个元素都是没有名字的。

&a[0]和&a 的区别(I)

a[0]是一个元素,a 是整个数组,虽然 &a[0] 和 &a 的值一样,但其意义不一样。

前者是数组首元素的首地址,而后者是数组的首地址

数组名 a 作为左值和右值的区别

(1) a 作为右值时其意义与 &a[0] 是一样,代表的是 数组首元素的首地址,而不是数组的首地址。

int *p; p = &a[0]; 或者 int *p; p = a; 两者同意。

(2) a 不能作为左值!只能访问数组的某个元素而无法把数组当一个总体进行访问。

&a[0] 和 &a 的区别(II)

int main()
{
char a[] = {'A','B','C','D'};
char (*p3)[] = &a;
char (*p4)[] = a;
return ;
}

p3 和 p4 都是数组指针,指向的是整个数组。p3 这个定义的“=”号两边的数据类型完全一致,而 p4 这个定义的“=”号两边的数据类型就不一致了。左边的类型是指向整个数组的指针,右边的数据类型是指向单个字符的指针。但由于 &a 和 a 的值一样,而变量作为右值时编译器只是取变量的值,所以运行并没有什么问题。

p3+1 和 p4+1 的值又是多少呢?

C 语言中,当一维数组作为函数参数的时候,编译器总是把它解析成一个指向其首元素首地址的指针。

指针


两个指针指向同一个变量

int *p1,*p2;
int x = ;
p1 = &x;
p2 = p1;

野指针产生的原因

定义指针变量时未初始化;指针释放后之后未置空。free和delete只是把指针所指的内存给释放掉,但并没有把指针本身干掉。此时指针指向的就是“垃圾”内存。释放后的指针应立即将指针置为NULL,防止产生“野指针”。

动态内存的使用

1.使用malloc函数申请内存空间后,要检查指针p是否为NULL

char *p = (char *)malloc(sizeof(char)*LENGTH+1);

if(NULL == p){ }

2.及时为指针p赋初值,防止未初始化内存就去使用

char *p = NULL;

3.申请与释放内存必须配对(malloc-free)

2. 用完指针之后也将指针变量的值设置为 NULL,防止产生“野指针”
free(p);
p = NULL;

C语言笔记(二)的更多相关文章

  1. 嗨翻C语言笔记(二)

    ~a a中所有位都取反 a & b a中的位 与 b中的位 (都为1则1,否则为0) a | b a中的位 或 b中的位 (只要对应位一个位1则为1) a ^ b a中的位 亦或 b中的位 & ...

  2. Go语言学习笔记二: 变量

    Go语言学习笔记二: 变量 今天又学了一招如何查看go的版本的命令:go version.另外上一个笔记中的代码还可以使用go run hello.go来运行,只是这种方式不会生成exe文件. 定义变 ...

  3. #r语言(二)笔记

    #r语言(二)笔记 #早复习 #概述:R是用于统计分析.绘图的语言和操作环境 #对象: #数据类型--统称为对象 #向量(vector):用于存储数值型.字符型或逻辑型数据的一维数组. #定义向量: ...

  4. 手把手和你一起实现一个Web框架实战——EzWeb框架(二)[Go语言笔记]Go项目实战

    手把手和你一起实现一个Web框架实战--EzWeb框架(二)[Go语言笔记]Go项目实战 代码仓库: github gitee 中文注释,非常详尽,可以配合食用 上一篇文章我们实现了框架的雏形,基本地 ...

  5. AJax 学习笔记二(onreadystatechange的作用)

    AJax 学习笔记二(onreadystatechange的作用) 当发送一个请求后,客户端无法确定什么时候会完成这个请求,所以需要用事件机制来捕获请求的状态XMLHttpRequest对象提供了on ...

  6. Swift语言指南(二)--语言基础之注释和分号

    原文:Swift语言指南(二)--语言基础之注释和分号 注释 通过注释向自己的代码中注入不可执行的文本,作为你自己的笔记或提示.Swift编译器运行时会忽略注释. Swift的注释与C语言极其相似,单 ...

  7. NumPy学习笔记 二

    NumPy学习笔记 二 <NumPy学习笔记>系列将记录学习NumPy过程中的动手笔记,前期的参考书是<Python数据分析基础教程 NumPy学习指南>第二版.<数学分 ...

  8. python3.4学习笔记(二) 类型判断,异常处理,终止程序

    python3.4学习笔记(二) 类型判断,异常处理,终止程序,实例代码: #idle中按F5可以运行代码 #引入外部模块 import xxx #random模块,randint(开始数,结束数) ...

  9. Emacs 笔记二

    Emacs 笔记二 Table of Contents 1. 前言 2. emacs基本操作(常用快捷键) 3. emacs模式讲解 4. emacs缓冲区 5. org mode 5.1. 列表 5 ...

随机推荐

  1. python爬虫18 | 就算你被封了也能继续爬,使用IP代理池伪装你的IP地址,让IP飘一会

    我们上次说了伪装头部 ↓ python爬虫17 | 听说你又被封 ip 了,你要学会伪装好自己,这次说说伪装你的头部 让自己的 python 爬虫假装是浏览器 小帅b主要是想让你知道 在爬取网站的时候 ...

  2. odoo 二次开发小记-----不定时更新

    一.odoo中 页面上字段变化引起其他字段范围变化-onchange @api.onchange('company_id') def onchange_parent_id(self): return ...

  3. JavaSE 学习笔记之多线程(十三)

    多线程: 进程:正在进行中的程序.其实进程就是一个应用程序运行时的内存分配空间. 线程:其实就是进程中一个程序执行控制单元,一条执行路径.进程负责的是应用程序的空间的标示.线程负责的是应用程序的执行顺 ...

  4. N天学习一个Linux命令之帮助命令:man

    前言 工作中每天都在使用常用的命令和非常用的命令,忘记了用法或者参数,都会bing一下,然后如此循环.一直没有真正的系统的深入的去了解命令的用法,我决定打破它.以前看到有人,每天学习一个linux命令 ...

  5. HDU 5200 脑洞题 离线

    线段树,TLE,各种.唉....我真是笨死了.... 我用的线段树是记录左右区间最长连续棵数的...反正TLE #include <iostream> #include <cstdi ...

  6. MFC 小知识总结四

    1 PlaySound  播放WAV格式的音乐 This function plays a sound specified by a file name, resource, or system ev ...

  7. iOS UITableView 去除多余切割线

    在UITableView初始化时加上下面代码就可以: self.tableView.tableFooterView = [[UIView alloc] initWithFrame:CGRectZero ...

  8. Apache日志优化

    apache执行时会记录其处理的全部请求的相关信息.同一时候,也会记录在处理过程中发生异常状况的相关信息. server能够用多种格式将与请求相关的活动信息记录在多个日志文件里,只是却仅仅能记录一份错 ...

  9. 【自己定义控件】android事件分发机制

    自己定义Viewgrou中我们或许会常常碰到这种情况,2个子控件的事件冲突导致滑动没实用了.滑动反应非常慢,点击没用了,要划非常多次才移动一点点等等.或许我们第一反应就是百度,google去搜索下答案 ...

  10. tolua reference

    Using Lua API and tag method facilities, tolua maps C/C++ constants, external variables, functions, ...