C语言进阶:18、三目运算符和逗号表达式

三目运算符(a?b:c)可以作为逻辑运算的载体。

规则:当a的值为真时,返回b的值,否则返回c的值。

观察下面代码:

int main()
{   
    int a=1;
    int b=2;
    int c=0;
    
    c = (a<b ? a:b);
    
    // (a<b ? a:b) = 3;
    *(a<b ? &a : &b) = 3;
    
    printf("%d\n", a);
    printf("%d\n", b);
    printf("%d\n", c);
	
	return 0;
}
需要注意的是,三目运算符返回的是一个值,而不是一个变量。但是,可以使用地址来操作变量。

上述代码的运行结果为:

3
2
1

也就是说,通过对三目运算符地址的操作,可以修改三目运算符输出变量(a)的值。

三目运算符的返回类型:

    通过隐式类型转换规则返回b和c中的较高数据类型;

    当b和c不能隐式类型转换为同一类型时将会发生编译错误。

运行下面代码:

int main()
{   
    char c = 0;
    short s = 0;
    int i = 0;
    double d = 0;
    char* p ="str";

    printf("%d\n", sizeof(c ? c : s));
    printf("%d\n", sizeof(i ? i : d));
    //printf("%d\n", sizeof(d ? d : p));    	error!
    
    printf("sizeof(char) = %d\n", sizeof(char));
    printf("sizeof(short) = %d\n", sizeof(short));
	
	return 0;
}

结果为:

			4
			8
			sizeof(char) = 1
			sizeof(short) = 2

逗号表达式:

逗号表达式是C语言中的“粘贴剂”,用于将多个表达式连接为一个表达式,其值为最后一个子表达式的值。

逗号表达式的前n-1个子表达式 都没有返回值,并且从左往右顺序计算每个子表达式的值。

观察下面代码,判断输出:(注意二维数组逗号和分号的使用)

int hello()
{
    printf("hello world!\n");
}

int main()
{   
    int a[3][3] = 		//逗号表达式
    {
        (0, 1, 2),   	        //2
        (3, 4, 5),		//5
        (6, 7, 8)		//8
    };
    
    int b[3][3] = 
    {
        {0, 1, 2},
        {3, 4, 5},
        {6, 7, 8}
    };
    
    int i=0;
    int j=0;
    
    while( i<5 )                      //注意,此处不是死循环,循环顺序执行。
	    printf("i = %d\n", i),
	    
	    hello(),
	    
	    i++;
	
	for(i=0; i<3; i++)
	{
            for(j=0; j<3; j++)
            {
                printf("a[%d][%d] = %d\n", i, j, b[i][j]);
            }
         }   
	
	return 0;
}
hello world!
i = 3
hello world!
i = 4
hello world!
a[0][0] = 0
a[0][1] = 1
a[0][2] = 2
a[1][0] = 3
a[1][1] = 4
a[1][2] = 5
a[2][0] = 6
a[2][1] = 7
a[2][2] = 8

笔试题:一行代码实现strlen()函数:

#include <stdio.h>

int strlen(const char* s)
{
    return (*s ? strlen(s+1)+1 : 0);
}

上面的代码基本可以实现strlen()的功能,但是对于空指针参数的话,会出现什么结果呢?

int main()
{   
    printf("len = %d\n", strlen("willwilling"));
    printf("plen = %d\n", strlen(NULL));  //传入空指针
	
	return 0;
}

运行结果:

len = 11
段错误

所以针对这种情况,应该修改代码如下:

int strlen(const char *s)  //
{  
    assert(NULL);
	return (*s ? strlen(s +1) + 1 : 0);  //递归
}

但是并不是一条语句,也无法完成要求,所以这个时候可以使用逗号表达式,将代码修改如下:

int strlen(const char *s)  //
{      
	return assert(NULL), (*s ? strlen(s +1) + 1 : 0);  //递归
}

运行结果如下:

len = 11
a.out: test.c:6: strlen: Assertion `((void *)0)' failed.
已放弃
值得注意的地方:
    int a = 1;
    int b = 2;
    int c[4] = {0};

    int m = ((a++) < (b) ? (a++) : (b));
	
	运行后m=2,a=3.

小结:

三目运算符返回变量的值,而不是变量本身;

三目运算符通过隐式类型转换规则确认返回值的类型;

逗号表达式按照从左往右的顺序运行每个子表达式;

逗号表达式的值为最后一个子表达式的值,所以说前n-1个子表达式可以没有返回值。

猜你喜欢

转载自blog.csdn.net/qq_28388835/article/details/80204252