注释


编译器会用空格代替代码中原来的注释,并先于预处理指令执行
/*…*/ 这种形式的注释不能嵌套
只要斜杠(/)和星号(*)之间没有空格,都会被当作注释的开始。例如这样:
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. JavaScript学习笔记之DOM对象

    目录 1.Document 2.Element 3.Attribute 4.Event 1.Document 每个载入浏览器的 HTML 文档都会成为 Document 对象,Document 对象允 ...

  2. AtCoder ABC 085C/D

    C - Otoshidama 传送门:https://abc085.contest.atcoder.jp/tasks/abc085_c 有面值为10000.5000.1000(YEN)的纸币.试用N张 ...

  3. 4 pandas模块,Series类

      对gtx图像进行操作,使用numpy知识 如果让gtx这张图片在竖直方向上进行颠倒.   如果让gtx这张图片左右颠倒呢?   如果水平和竖直方向都要颠倒呢?   如果需要将gtx的颜色改变一下呢 ...

  4. BUAA_OO_博客作业二

    1.作业设计策略 1.1第一次作业 ​ 第一次作业指导书要求是一个单部多线程傻瓜调度(FAFS)电梯的模拟,由于为了可扩展性和模块化设计,第一次作业我采用了三线程,即输入处理线程,调度器线程,电梯线程 ...

  5. TSP服务商

    1.何为TSP? TSP([1] Service Provider),在Telematics产业链居于核心地位,上接汽车.车载设备制造商.网络运营商,下接内容提供商.谁掌控了TSP,谁就能掌握Tele ...

  6. android NDK开发在本地C/C++源码中设置断点单步调试具体教程

    近期在学android NDK开发,折腾了一天,最终可以成功在ADT中设置断点单步调试本地C/C++源码了.网上关于这方面的资料太少了,并且大都不全,并且调试过程中会出现各种各样的问题,真是非常磨人. ...

  7. 2.1-VLAN/TRUNK/VTP

    2.1-VLAN/TRUNK/VTP     注意:配置VLAN时要退出VLAN配置模式才会执行 如果VLAN被删除或者shutdown,那么属于这个vlan的接口将被阻塞(灯一直是橙色,变不了绿色) ...

  8. 2014 北京 DevFest 大会能够报名啦,小伙伴们还在等什么

    一年一度的大型开发人员活动,2014 北京 DevFest 大会站点正式上线: http://devfest.gdgbeijing.org/. 还等什么,開始报名了! 今年 DevFest 大会将再次 ...

  9. 浏览器最小字体小于12px解决方案

    <style> p{font-size:10px;-webkit-transform:scale(0.8);} /*这里的数字0.8,是缩放比例,可以根据情况变化.*/ </styl ...

  10. 冒泡排序Vs直接选择排序

    什么是排序?为什么要使用排序?事实上我们生活中处处都用到了排序.拿字典来说,如今,我们要在字典中查找某个字(已经知道这个字的读音),首先.我们须要依据这个字的读音,找到它所所在文件夹中的位置,然后依据 ...