那些年C语言走过的坑

一、逗号运算符

在C语言中,多个表达式可以用逗号分开,其中用逗号分开的表达式的值分别结算,但整个表达式的值是最后一个表达式的值。
例如:

  1. int a1, a2, b = 2,c = 7, d = 5;

  2. a1 = (++b, c–, d++);

  3. a2 = ++b, c–, d++;

其中第 2,3行就是使用了逗号运算符。

但是这两个表达式表达的意思不尽相同。

注意:

逗号运算的结合性是从左至右,完毕后整个表达式的值根据有无括号而不同。如果加上括号,则返回最后一个运算,没有就返回第一个。
例题中的计算结果a1 = 5,a2 = 4,其原理就是在计算a1的时候返回的是最后一个运算即d++(a1 = d++ = 5(先赋值再再进行加一操作)),但是此时b已经进行过了++b运算 值为3,c进行了c–运算 值为6);计算a2的时候返回的是第一个运算即++b(先加一再赋值),得a2值为4, 但是计算从左至右直到分号结束,则再进行c–操作,接着就是d++操作。

二、宏定义

概念

宏定义是C语言提供的三种预处理功能的其中一种(宏定义,文件包含,条件编译),宏定义和操作符的区别在于宏定义是替换,不做计算,也不做表达式求解,故又称宏代换、宏替换。

格式

#define 标识符 内容
其中标识符又可称为宏名, 一般采用的是大写
例:#define PI 3.1415926 

注意

  1. 宏定义能提高程序的通用性和可读性,减少输入错误,便于修改
  2. 在编译前处理,即不尽兴语法检查
  3. 宏定义可以使用#undef命令终止其作用范围
  4. 宏定义允许嵌套
  5. 宏定义中不存在变量类型,也没有类型转换
  6. 宏定义中可以使用变量进行使用,调用的时候传参就好
  7. *宏定义只替换, 不做计算,也不做表达式求解

例子:

#define M(x,y,z) x*y+z
#include<stdio.h>
int main()
{
    int a=1, b=2, c=3;  
    printf("%d\n",M(a+b,b+c,c+a));
}
只替换,不计算->a+b*b+c+c+a = 12;
而不是(a+b)*(b+c)+(c+a) = 19;

三、传参问题

当我们把一个指针作为参数传给一个函数的时候,其实只是把指针的副本传递了过去,也可以说传递指针是指针的按值传递。尽管它是一个指针,但如果我们在函数内部修改指针会出现问题,在方法里做修改只是修改指针的副本而不是指针本身,原来的指针还保留着原来的值。如果想用真正传递,可以使用二级指针或者指针的引用。
如果进行的是指针的引用,这个时候传入的不是指针的副本了,而是指针的本身,相当于取了个别的名字而本质未改变,改变了它的指向或者值,相应的全部都改变了。

例题:

#include   <string.h>
#include   <stdio.h> 
#include   <stdlib.h> 
void getmemory(char*p)  {    
    p=(char *) malloc(100);    
    strcpy(p,"hello world"); 
} 
int main( ) {
    char *str=NULL;
    getmemory(str);        
    printf("%s\n",str);      
    free(str);       
    return 0;    
}
ps:这个时候输出的就是null了,因为strcpy(p, "hello world")改变的只是主函数中str的副本,而不是它本身,当函数结束后返回主函数,str依旧指向空。

四、数组指针

例题:

#include<stdio.h>
main(void)
{
     int a[5]={1,2,3,4,5};
     int *ptr=(int *)(&a+1);
     printf("%d,%d",*(a+1),*(ptr-1));
}

分析

数组名就是一个指针,这样假设有个 p = int()(&a)这个时候p就是指向a这个一维数组的指针,即数组指针, 而这个时候p的步长就是a数组的长度,即(p+1)将跨过n个整型数据的长度; ptr也是一个数组指针,不过进行了加一操作,即跳出了数组a的范围,进行(ptr-1)操作则回到数组,此时指向的是a数组的末尾元素即a[4];所以输出的结果是 2, 5;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值