C语言:逗号、sizeof与最高优先级运算符

在C语言中,除了常见的赋值、条件、位运算外,逗号运算符、sizeof运算符以及()[]等最高优先级运算符虽不常被重点提及,但在实际开发和面试中频繁出现。

一、逗号运算符

逗号运算符(,)是C语言中优先级最低的运算符,作用是将多个表达式组合成一个

1.1 核心特性

  1. 执行顺序:从左到右依次执行每个表达式(左侧表达式仅执行,结果丢弃);
  2. 返回值:最终结果为最后一个表达式的值
  3. 优先级:所有运算符中最低,必须通过括号明确作用范围;
  4. 适用场景:for循环中合并多个操作、赋值语句中组合多步计算。

1.2 基本用法示例

int a = (1, 2, 3, 4, 5);
printf("a = (1, 2, 3, 4, 5) → a = %d\n", a);
int b, c, d;
b = (c = 10, d = 20, c + d);// 先执行c=10,再执行d=20,最终返回c+d
printf("b = (c = 10, d = 20, c + d) → b=%d, c=%d, d=%d\n", b, c, d);
return 0;

1.3 与for循环的结合(高频场景)

逗号运算符最常用在for循环中,将初始化、递增/递减操作合并为一行,简化代码:

#include <stdio.h>

int main() {
    printf("=== 逗号运算符与for循环结合 ===\n");
    int i, j;
    for (i = 0, j = 10; i < 5; i++, j--) {
        printf("i=%d, j=%d\n", i, j);
    }
    // 输出结果:
    // i=0, j=10
    // i=1, j=9
    // i=2, j=8
    // i=3, j=7
    // i=4, j=6
    return 0;
}

1.4 经典面试题解析(避坑重点)

逗号运算符的核心坑点是优先级低于赋值运算符,以下4道面试题覆盖所有高频场景:

    int a, b;
    a = 1, 2, 3;  // 等价于 (a=1), 2, 3 → 赋值优先级高于逗号
    b = (1, 2, 3); // 括号提升逗号运算符优先级,返回最后一个表达式
    printf("a = 1, 2, 3 → a = %d\n", a); // 输出:1
    printf("b = (1, 2, 3) → b = %d\n", b); // 输出:3
   
    int x = 5, y = 10;
    // 逗号分隔多个赋值,最终判断x+y>0(恒成立)
    if (x = 1, y = 2, x + y > 0) {
        printf("if条件成立: x=%d, y=%d\n", x, y); // 输出:x=1, y=2
   }
  
    // 逗号分隔多个printf,最终返回100作为函数参数
    printf("函数调用结果: %d\n", (printf("Hello, "), printf("World! "), 100));
    // 输出:Hello, World! 函数调用结果: 100
    
    // 注意:()内是逗号运算符,不是初始化列表!每个元素仅取最后一个值
    int arr[3][4] = {(1,2,3,4), (5,6,7,8), (9,10,11,12)};
    // 等价于:arr[3][4] = {4, 8, 12, 0, ...}(其余元素默认初始化0)
    printf("arr[0][1] = %d, arr[1][1] = %d, arr[2][1] = %d\n", 
           arr[0][1], arr[1][1], arr[2][1]); // 输出:0 0 0
    return 0;
    //二维数组初始化时,`()`会将内部变为逗号表达式,而非多个元素。若需正确初始化,应使用`{1,2,3,4}`(无括号)或`{{1,2,3,4}, {5,6,7,8}, {9,10,11,12}}`。

}

二、sizeof

sizeof是C语言中的单目运算符(不是函数),用于计算数据类型、变量或表达式占用的内存字节数,编译时求值,不执行表达式。

2.1 核心特性

  1. 本质:运算符,而非函数,可省略括号(类型名除外);
  2. 求值时机:编译期计算,表达式仅判断类型,不实际执行;
  3. 关键区别:数组作为函数参数时会退化为指针,sizeof返回指针大小;
  4. 常见用途:计算数组元素个数、跨平台代码中确保类型大小兼容性。

2.2 基本用法示例

#include <stdio.h>

int main() {
    printf("=== sizeof运算符基本用法 ===\n");
    
    int a = 10;
    // 变量可省略括号,类型名必须加括号
    printf("sizeof(a) = %zu\n", sizeof(a));     // 输出:4(int默认4字节)
    printf("sizeof a = %zu\n", sizeof a);       // 输出:4(合法,无括号)
    printf("sizeof(int) = %zu\n", sizeof(int)); // 输出:4
    
    // 关键特性:编译时求值,不执行表达式
    int b = 0;
    printf("sizeof(b = 100) = %zu\n", sizeof(b = 100)); // 输出:4(仅判断int类型)
    printf("b的值仍然是: %d\n", b); // 输出:0(b=100不执行)
    return 0;
}

2.3 不同数据类型的sizeof结果

#include <stdio.h>

int main() {
    printf("=== sizeof与各种数据类型 ===\n");
    
    // 基本数据类型(结果因平台而异,以下为64位系统示例)
    printf("char: %zu bytes\n", sizeof(char));       // 1
    printf("short: %zu bytes\n", sizeof(short));     // 2
    printf("int: %zu bytes\n", sizeof(int));         // 4
    printf("long: %zu bytes\n", sizeof(long));       // 8(64位系统)
    printf("float: %zu bytes\n", sizeof(float));     // 4
    printf("double: %zu bytes\n", sizeof(double));   // 8
    
    // 指针类型(所有指针大小相同,取决于系统位数)一般在32位系统中为4,64位为8
    printf("char*: %zu bytes\n", sizeof(char*));     // 8(64位系统)
    printf("int*: %zu bytes\n", sizeof(int*));       // 8
    printf("double*: %zu bytes\n", sizeof(double*)); // 8
    return 0;
}

2.4 sizeof与数组的关键细节

数组在函数内外的sizeof结果不同,字符串数组与字符串指针的sizeof差异也是面试热点:

#include <stdio.h>
#include <string.h>

// 数组作为函数参数退化为指针
void testArray(int arr[]) {
    printf("函数内sizeof(arr): %zu\n", sizeof(arr)); // 输出:8(指针大小)
}

int main() {
    printf("=== sizeof与数组 ===\n");
    // 1. 普通数组:函数外sizeof返回整个数组大小
    int arr[10];
    printf("函数外sizeof(arr): %zu\n", sizeof(arr)); // 输出:40(10*4)
    printf("数组元素个数: %zu\n", sizeof(arr) / sizeof(arr[0])); // 输出:10(通用计算方式)
    // 函数调用验证数组退化
    testArray(arr);
    // 2. 字符串数组 vs 字符串指针
    char str[] = "Hello";    // 字符串数组,包含'\0'
    char* pstr = "Hello";    // 字符串指针,指向常量区
    
    printf("\n字符串相关sizeof对比:\n");
    printf("sizeof(str) = %zu\n", sizeof(str));     // 输出:6(H e l l o \0)
    printf("sizeof(pstr) = %zu\n", sizeof(pstr));   // 输出:8(指针大小)
    
    // 与strlen的区别(strlen计算有效字符数,不含'\0')
    printf("strlen(str) = %zu\n", strlen(str));     // 输出:5
    printf("strlen(pstr) = %zu\n", strlen(pstr));   // 输出:5
    
    return 0;
}

2.5 sizeof与strlen的区别

特性sizeofstrlen
类型编译时运算符运行时函数
作用计算内存占用字节数计算字符串有效长度
处理\0包含空字符(计入大小)遇到\0停止(不计入)
数组返回整个数组大小返回字符串实际字符数
指针返回指针本身大小计算指针指向的字符串长度

三、最高优先级运算符:()[]->.

C语言中优先级最高的四类运算符是()[]->.,它们的优先级高于所有算术、赋值运算符,核心用于“访问数据”或“改变运算规则”。

3.1 四类运算符的作用

运算符名称核心用途
()括号运算符改变优先级、类型转换、函数调用、宏定义
[]数组下标运算符访问数组元素(arr[i]等价于*(arr+i)
.结构体成员运算符结构体变量访问成员
->结构体指针成员运算符结构体指针访问成员(ps->age等价于(*ps).age

3.2 基本用法示例

// 定义结构体
struct Student {
    char name[20];
    int age;
};

int main() {
    printf("=== 最高优先级运算符基本用法 ===\n");
    // 1. 括号运算符 ():改变优先级
    int a = (2 + 3) * 4;
    printf("(2 + 3) * 4 = %d\n", a); // 输出:20(优先计算括号内)
    // 2. 数组下标运算符 []
    int arr[5] = {1, 2, 3, 4, 5};
    printf("arr[2] = %d\n", arr[2]); // 输出:3(访问第3个元素)
    // 3. 结构体成员访问 . 和 ->
    struct Student s = {"张三", 20};    // 结构体变量
    struct Student *ps = &s;           // 结构体指针
    printf("学生姓名: %s\n", s.name);  // 变量用.访问
    printf("学生年龄: %d\n", ps->age); // 指针用->访问
    return 0;
}

3.3 括号运算符的4大核心用途

#include <stdio.h>
#define SQUARE(x) ((x) * (x)
int main() {
    printf("=== 括号运算符的多种用途 ===\n");
    // 用途1:改变运算优先级
    int a = 2 + 3 * 4;  // 14(默认先乘后加)
    int b = (2 + 3) * 4; // 20(括号改变顺序)
    printf("2 + 3 * 4 = %d\n", a);
    printf("(2 + 3) * 4 = %d\n", b);
    // 用途2:类型转换
    double result = (double)5 / 2; // 强制转换为double,避免整数除法
    printf("(double)5 / 2 = %.1f\n", result); // 输出:2.5
    // 用途3:复合表达式(与条件运算符结合)
    int x = 5, y = 10;
    int max = (x > y) ? x : y; // 括号提升可读性
    printf("%d和%d中较大的是: %d\n", x, y, max); // 输出:10
    // 用途4:函数式宏定义(双重括号避免陷阱)
    printf("SQUARE(3+2) = %d\n", SQUARE(3+2)); // 输出:25(等价于(3+2)*(3+2))
    // 若宏定义为(x*x),则会变成3+2*3+2=11,双重括号是关键!
    return 0;
}

四、总结与避坑指南

  1. 逗号运算符:优先级最低,必须加括号;返回最后一个表达式值,避免在数组初始化中误用。
  2. sizeof运算符:编译时求值,不执行表达式;数组作为函数参数退化为指针,字符串数组与指针的sizeof结果不同。
  3. 最高优先级运算符()可改变优先级、类型转换;[]访问数组;.->访问结构体成员,优先级最高无需括号。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值