C - Charles-Charmless/Charles-Charmless.github.io GitHub Wiki
C语言技巧
- 判断逻辑关系的时候将常量写在前面,变量写在后面
- 合法的赋值形式要求两个操作数都是指向有限定符或无限定符的相容类型的指针,左边指针所指向的类型必须具有右边指针所指向类型的全部限定符。
gets以一行为单位,可以读取有空格的字符串, getchar以字符为单位读取,可以避免长度限制 scanf以空格为间隔,在读取到行末时不会读取换行符,而是在下一次读取时取出
将char型声明为整型可以确保不会由多个字符连接被误认为EOF
地址按照字节来计算而不是按照位来计算
如果只创建指针但是没有初始化,那么程序并不会给指针创建存储空间
NULL表示某个特定的指针目前并未指向任何东西
Cbug
在C语言的宏中,#的功能是将其后面的宏参数进行字符串化操作(Stringfication)
而##被称为连接符(concatenator),用来将两个Token连接为一个Token
| Name | Tags | Files |
|---|---|---|
| _LINE_ | 正在编译的文件的行号 | |
| _FILE_ | 正在编译的文件的名字 | |
| _DATE_ | 编译时可的日期字符串 | |
| _TIME_ | 编译时刻的时间字符串 | |
| _STDC_ | 判断程序是否为标准的c程序 |
gcc
| 预处理指令 | 含义 |
|---|---|
| define | 宏定义 |
| undef | 撤销已定义的宏名 |
| include | 使编译程序将另一个源文件嵌入到带有#include的源文件中 |
| if | |
| else | |
| elif | |
| endif | |
| ifdef | |
| ifndef | |
| line | |
| error | |
| pragma |
无符号数和有符号数一起运算会转换成无符号数进行转换
-
定义全局静态变量:在全局变量前面加上关键字static,该全局变量变成了全局静态变量。全局静态变量有以下特点。a.在全局区分配内存。b.如果没有初始化,其默认值为0.c.该变量在本文件内从定义开始到文件结束可见。
-
定义局部静态变量:在局部变量前面加上关键字static,其特点如下:a.该变量在全局数据区分配内存。b.它始终驻留在全局数据区,直到程序运行结束。c. 其作用域为局部作用域,当定义它的函数或语句块结束时,其作用域随之结束。
-
定义静态函数:在函数返回类型前加上static关键字,函数即被定义为静态函数,其特点如下:
a.静态函数只能在本源文件中使用 b.在文件作用域中声明的inline函数默认为static类型
用static定义的全局和局部静态变量的区别是,全局的静态变量的作用域和可见域都是从文件的定义开始到整个文件结束;而局部的静态变量可见域是从文件的定义开始到整个文件结束,作用域是从该语句块的定义开始到该语句块结束。
static关键字定义静态常量,存储在系统的全局初始化区
可以定义const常量,具有不可变性。
c语言中const全局变量存储在只读数据段,编译期最初将其保存在符号表中,第一次使用时为其分配内存,在程序结束时释放。
==const 从左向右结合,不考虑定义符int ,float等==
- const int * p;
int a=10;
const int *p=20;
*p=30;//错误
p=&a; //正确- int const * p;同const int *p
- int * const p;
int a=10;
int * const p=20;
*p=30;//正确
p=&a;//错误- int const * const p;
int a=10;
int const * const p;
*p=30;//错误
p=&a;//错误一个定义为volatile的变量是说这变量可能会被意想不到地改变,这样,编译器就不会去假设这个变量的值了。精确地说就是,优化器在用到这个变量时必须每次都小心地重新读取这个变量的值,而不是使用保存在寄存器里的备份。
例如中断改变寄存器数据;
共享内存
汇编的任意操作
将可能不同类型的对象聚合到一个对象中
允许用多种类型来引用一个对象
while
for
goto
- 函数前面加两个下划线表示内部函数
关键字:inline,__inline,__forceinline
任何地方只要调用内联函数,就直接把该函数的机器码插入到调用它的地方。这样程序执行更有效率,就好像将内联函数中的语句直接插入到了源代码文件中需要调用该函数的地方一样。
inline 修饰符并非强制性的:编译器有可能会置之不理。
区别于宏
内联函数时代码被插到调用者代码处的函数。避免调用的开销
宏由预处理器对宏进行替换,内联函数通过编译器控制实现,内联函数是真正的函数,只是在需要用到的时候,内联函数像宏一样的展开,所以取消了函数的参数压栈,减少了调用的开销。你可以象调用函数一样来调用内联函数,而不必担心会产生于处理宏的一些问题。
宏不检查参数类型,内联函数检查参数类型。
==‘[]’的优先级比'*'的优先级高==
/*****************************************/
int *p1[10]; //数组指针
int (*p2)[10]; //指针数组
int main(void){
int *p1[4];
int (*p2)[4];
printf(" the byte of the pointer of array is %d\n",sizeof(p1));
printf(" the byte of the pointer in the array is %d",sizeof(p2));
return 0;
}
the byte of the pointer of array is 32
the byte of the pointer in the array is 8int main(void){
char *m='m';
printf("%d\n",m+1);
printf("%d\n",(int*)(m+1));
printf("%d\n",(int *)m+1);
return 0;
}
============================================
110
110
113指针的强制类型转换只改变类型,不改变他的值
强制类型转换的一个效果是改变指针运算的伸缩
\#include < > 直接从编辑器自带的函数库中寻找文件#include " " 先从自定义的文件中找,如果找不到再从库函数中寻找文件,并且可以在 #include “ “中使用相对路径或者绝对路径来指定头文件所在的位置