c关键词c

c基础

gcc编译的四个过程

gcc在执行编译工作的时,分为以下四个过程:
1.预处理,生成.i的文件
编译#字开头的指令,如拷贝#include包含的头文件代码,#define宏定义的替换,条件编译ifndef
2.将预处理后的文件转换成汇编语言,生成.s文件
3.汇编变为目标代码(机器代码),生成.o的文件
4.连接目标代码,生成可执行程序

# 与 ##的区别以及作用

# :把宏参数变成一个字符串;
##:把两个宏参数连接到一起(只能两个)

#define hehe(x,y)  x##y
int main()
{
  char string[]="hello world!";
  printf("%s\n",hehe(str,ing)); 
  
  return 0;
}
c

关键字

1.static关键字的作用

static最主要功能是隐藏,其次因为static变量存放在静态存储区,具备持久性和默认值为0

局部变量

静态局部变量使用static修饰符定义,即使在声明时未赋初值,编译器也会把它初始化为0。且静态局部变量存储于进程的全局数据区,即使函数返回,它的值也会保持不变。

全局变量

静态全局变量仅对当前文件可见,其他文件不可访问,其他文件可以定义与其同名的变量,两者互不影响。

在定义不需要与其他文件共享的全局变量时,加上static关键字能够有效地降低程序模块之间的耦合,避免不同文件同名变量的冲突,且不会误使用。

函数

静态函数只能在声明它的文件中可见,其他文件不能引用该函数
不同的文件可以使用相同名字的静态函数,互不影响

2.const关键字的作用

①对变量加以限定不能被修改,常量必须在定义的时候同时被初始化。
②const和指针一起使用。

const int *p1;	    //常量指针  不能通过这个指针改变变量的值
int const *p2;	    //常量指针
int *const p3;      //指针常量   指针常量指向的地址不能改变
const int* const p4; //指向常量的常指针 指针指向的位置不能改变也不能通过这个指针改变变量的值

在三种情况中,第三种指针是只读的,p3本身的值不能被修改;
第一二种情况,指针所指向的数据是只读的,p1,p2的值可以修改,但指向的数据不能被修改。
③const和函数形参一起使用
使用const单独定义变量可以用#define命令替换,const通常放在函数形参中。
如果形参是一个指针,为了防止在函数内部修改指针指向的数据就可以用const来限制。

const修饰谁,谁就是const类型的

  1. const如果放在*的左边,修饰的是指针指向的内容(常量指针),保证指针指向的内容不能通过指针来改变。但是指针变量本身的内容可变。
  2. const如果放在*的右边,修饰的是指针变量本身(指针常量),保证了指针变量的内容不能修改,但是指针指向的内容,可以通过指针改变。
常量指针与指针常量

常量指针是指针指向的内容是常量。

常量指针说的是不能通过这个指针改变变量的值,但是还是可以通过其他的引用来改变变量的值的。
常量指针指向的值不能改变,但是这并不是意味着指针本身不能改变,常量指针可以指向其他的地址。

指针常量是指指针本身是个常量,不能在指向其他的地址

修饰函数的参数

1、防止修改指针指向的内容
void StringCopy(char *strDestination, const char *strSource);
strSource 加上 const 修饰后,如果函数体内的语句试图改动 strSource 的内容,编译器将指出错误。
2、防止修改指针指向的地址
void swap ( int * const p1 , int * const p2 )
指针p1和指针p2指向的地址都不能修改。

修饰函数的返回值

如果给以“指针传递”方式的函数返回值加 const 修饰,那么函数返回值(即指针)的内容不能被修改,该返回值只能被赋给加const 修饰的同类型指针。
const char * GetString(void);
char * str = GetString(); // error
const char *str = GetString();

修饰全局变量

尽量避免使用全局变量,因为一旦有函数改变了全局变量的值,会导致其它函数在引用它时产生影响,从而出现bug;

3.volatile关键字的作用

确保本条指令不会因编译器的优化而省略,且要求每次直接读值。
编译器的优化: 内存访问速度远远比不上cpu处理的速度,为了提高性能,从硬件上引入高速缓存cache,加速对内存的访问。
编译优化的方法 将内存变量缓存到寄存器;调整指令顺序充分利用CPU指令流水线。

因为访问寄存器要比访问内存单元要快的多,编辑器会作减少存取的优化。
当使用volatile声明函数变量的时候,系统总是重新从它所在的内存读取数据。遇到这个关键字声明的变量,编译器对访问该变量的代码不再进行优化,从而提供对特殊地址的稳定访问;
如果不使用valatile,编译器将对所声明的语句进行优化,以免出错。

MYBYTE[2]=0x52;
MYBYTE[2]=0x53;
MYBYTE[2]=0x54;
MYBYTE[2]=0x55;

对外部硬件而言,上述四条语句分别表示不同的操作,会产生四种不同的动作,但是编译器却会对上述四条语句进行优化,认为只有MYBYTE[2]=0x55(即忽略前三条语句,只产生一条机器代码)。如果键入volatile,则编译器会逐一地进行编译并产生相应的机器代码(产生四条代码)。
for(int i=0; i<100000; i++);对于编译器来说会优化,根本就不执行,需要加上volatile
for(volatile int i=0; i<100000; i++);

int square(volatile int *ptr)
{
   return ((*ptr) * (*ptr));
}

该函数被用来计算某个整数的平方,它能实现预期设计目标吗?
编译器可能会产生类似下面的伪代码:

{
    int a,b;
    a = *ptr;
    b = *ptr;
    return a*b;
}

由于ptr的值可能在两次取值语句之间发生改变,因此a和b可能是不同的。结果,这段代码可能返回的不是你所期望的平方值!

long square(volatile intptr)
{
    int a;
    a = *ptr;
    return a*a;
}

4.extern关键字的作用

函数内的局部变量,函数外定义的变量为全局变量,为静态存储方式,生存周期为整个程序,有效范围为定义变量的位置开始到本源文件结束。
如果在定义前想要引用该全局变量,则应该加上 extern作为 “外部变量声明”。
多个源文件的工程想要引用一个源文件的外部变量也只许引用变量的文件中加入extern关键字加以声明,但是可以在引用的模块内修改其变量的值,慎用。

extern “C”: C++代码调用C语言代码。在C++的头文件中使用。

sizeof和strlen的区别

1、sizeof是运算符,strlen是C语言标准库函数。
2、strlen 测量的是字符串的实际长度,以’\0’ 结束,返回结果不包括’\0’ 。
3、而sizeof 测量的是字符的分配大小,

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值