【C语言】 操作符的详细知识点

文章目录

  • 12 操作符
    • 🍒算术操作符
    • 🍒关系操作符
    • 🍒逻辑操作符
    • 🍒位操作符
    • 🍒赋值操作符
    • 🍒强制类型转换符
    • 🍒成员访问操作符
    • :fire:操作符优先级
    • 计算大小符`sizeof`
    • 条件操作符 `? :`
    • `const char *`
    • 按位取反
    • `snprintf`字符串输出函数

12 操作符

🍒算术操作符

  • 加法 (+): 加法操作。
  • 减法 (-): 减法操作。
  • 乘法 (*): 乘法操作。
  • 除法 (/): 除法操作。
  • 取模 (%): 返回两个数相除的余数。
#include <stdio.h>int main() {// 算术操作符int a = 10, b = 3;printf("Arithmetic Operators:\n");printf("a + b = %d // Expected: 13\n", a + b); // 加法printf("a - b = %d // Expected: 7\n", a - b);  // 减法printf("a * b = %d // Expected: 30\n", a * b); // 乘法printf("a / b = %d // Expected: 3\n", a / b);  // 除法, 注意这是整数除法printf("a %% b = %d // Expected: 1\n\n", a % b); // 取模, 注意%%用于打印%return 0;
}

🍒关系操作符

在 C 语言中,关系操作符同样用于比较两个值或表达式,并基于比较的结果返回一个布尔值,即 0 (表示 False)或 1 (表示 True)。C 语言中的关系操作符包括:

  • ==:等于。如果两边的值相等,返回 1;否则返回 0。
  • !=:不等于。如果两边的值不相等,返回 1;否则返回 0。
  • <:小于。如果左边的值小于右边的值,返回 1;否则返回 0。
  • >:大于。如果左边的值大于右边的值,返回 1;否则返回 0。
  • <=:小于或等于。如果左边的值小于或等于右边的值,返回 1;否则返回 0。
  • >=:大于或等于。如果左边的值大于或等于右边的值,返回 1;否则返回 0。
#include <stdio.h>int main() {int a = 10, b = 3;printf("Relational Operators:\n");// 等于printf("a == b: %d\n", a == b); // Expected: 0 (false)// 不等于printf("a != b: %d\n", a != b); // Expected: 1 (true)// 大于printf("a > b: %d\n", a > b);   // Expected: 1 (true)// 小于printf("a < b: %d\n", a < b);   // Expected: 0 (false)// 大于等于printf("a >= b: %d\n", a >= b); // Expected: 1 (true)// 小于等于printf("a <= b: %d\n", a <= b); // Expected: 0 (false)return 0;
}

🍒逻辑操作符

在 C 语言中,逻辑操作符用于组合或修改条件表达式的布尔值,以实现复杂的逻辑判断。C 语言中的逻辑操作符包括:

  1. 逻辑与 (&&):如果两个操作数都非零(即都为真),则条件成立(返回 1),否则条件不成立(返回 0)。

  2. 逻辑或 (||):如果两个操作数中至少有一个非零(即至少有一个为真),则条件成立(返回 1),否则条件不成立(返回 0)。

  3. 逻辑非 (!):用于反转操作数的逻辑状态。如果条件为真(非零),则逻辑非操作符将使其变为假(0);如果条件为假(0),则操作符将使其变为真(1)。

示例 1:使用逻辑与(&&

#include <stdio.h>int main() {int age = 25;int score = 85;// 检查年龄是否在20到30之间,并且分数是否高于80if (age >= 20 && age <= 30 && score > 80) {printf("Candidate is selected.\n");} else {printf("Candidate is not selected.\n");}return 0;
}

示例 2:使用逻辑或(||

#include <stdio.h>int main() {float temperature = 35.5;int isRaining = 1; // 用 1 表示下雨,0 表示没有下雨// 检查是否过热或下雨if (temperature > 30 || isRaining) {printf("It's not a good day for a picnic.\n");} else {printf("It's a good day for a picnic.\n");}return 0;
}

示例 3:使用逻辑非(!

#include <stdio.h>int main() {int doorClosed = 1; // 用 1 表示门关闭,0 表示门开启// 检查门是否开启if (!doorClosed) {printf("The door is open.\n");} else {printf("The door is closed.\n");}return 0;
}

注意

在逻辑表达式中,C 语言采用短路求值(short-circuit evaluation):

  • 在使用 && 操作符的表达式中,如果第一个操作数的值为假(0),则不会评估第二个操作数,因为整个表达式的结果已确定为假(0)。
  • 在使用 || 操作符的表达式中,如果第一个操作数的值为真(非0),则不会评估第二个操作数,因为整个表达式的结果已确定为真(1)。

这种行为可以用来防止执行可能导致错误的操作,例如在访问数组元素或指针之前先检查它们是否有效。

🍒位操作符

  • 按位与 (&): 对两个操作数中相对应的位执行逻辑与操作。
  • 按位或 (|): 对两个操作数中相对应的位执行逻辑或操作。
  • 按位异或 (^): 对两个操作数中相对应的位执行逻辑异或操作。
  • 按位取反 (~): 对操作数的每一位执行逻辑取反操作。
  • 左移 (<<): 把左操作数的位向左边移动指定的位数。
  • 右移 (>>): 把左操作数的位向右边移动指定的位数。
#include <stdio.h>int main() {unsigned int a = 5; // 二进制: 0101unsigned int b = 9; // 二进制: 1001int result;// 按位与result = a & b; // 二进制: 0001, 十进制: 1printf("a & b = %d\n", result);// 按位或result = a | b; // 二进制: 1101, 十进制: 13printf("a | b = %d\n", result);// 按位异或result = a ^ b; // 二进制: 1100, 十进制: 12printf("a ^ b = %d\n", result);// 按位取反result = ~a;// 注意:由于result是int类型,按位取反的结果将依赖于int的位数(假设是32位,实际的输出会是补码形式的一个负数)printf("~a = %d\n", result);// 左移result = a << 1; // 二进制: 1010, 十进制: 10printf("a << 1 = %d\n", result);// 右移result = a >> 1; // 二进制: 0010, 十进制: 2printf("a >> 1 = %d\n", result);return 0;
}//a& b = 1
//a | b = 13
//a ^ b = 12
//~a = -6
//a << 1 = 10
//a >> 1 = 2

🍒赋值操作符

在 C 语言中,赋值操作符用于给变量赋值。最基本的赋值操作符是等号 (=),它将右侧表达式的值赋给左侧的变量。此外,C 语言还提供了一系列复合赋值操作符,这些操作符结合了算术操作和赋值操作,可以使代码更加简洁。

基本赋值操作符

  • =:将右侧表达式的值赋给左侧的变量。

复合赋值操作符

  • +=:加上后赋值,a += b 等价于 a = a + b
  • -=:减去后赋值,a -= b 等价于 a = a - b
  • *=:乘以后赋值,a *= b 等价于 a = a * b
  • /=:除以后赋值,a /= b 等价于 a = a / b。注意,除以零会导致运行时错误。
  • %=:取模后赋值,a %= b 等价于 a = a % b。对于整数类型,表示取除法的余数。
  • <<=:左移后赋值,a <<= b 等价于 a = a << b。表示将 a 的二进制表示向左移动 b 位。
  • >>=:右移后赋值,a >>= b 等价于 a = a >> b。表示将 a 的二进制表示向右移动 b 位。
  • &=:按位与后赋值,a &= b 等价于 a = a & b。只有在 ab 对应位都为 1 时,结果的对应位才为 1。
  • ^=:按位异或后赋值,a ^= b 等价于 a = a ^ b。只有在 ab 对应位不同时,结果的对应位才为 1。
  • |=:按位或后赋值,a |= b 等价于 a = a | b。只要 ab 的对应位中有一个为 1,结果的对应位就为 1。
#include <stdio.h>int main() {int a = 2;printf("Initial value of a: %d\n", a);// 加上后赋值a += 3; // 等价于 a = a + 3;printf("After a += 3: %d\n", a);// 减去后赋值a -= 1; // 等价于 a = a - 1;printf("After a -= 1: %d\n", a);// 乘以后赋值a *= 2; // 等价于 a = a * 2;printf("After a *= 2: %d\n", a);// 除以后赋值a /= 4; // 等价于 a = a / 4;printf("After a /= 4: %d\n", a);// 取模后赋值a %= 3; // 等价于 a = a % 3;printf("After a %%= 3: %d\n", a);// 左移后赋值a = 1; // Reset a for shift operationsa <<= 2; // 等价于 a = a << 2;printf("After a <<= 2: %d\n", a);// 右移后赋值a >>= 1; // 等价于 a = a >> 1;printf("After a >>= 1: %d\n", a);// 按位与后赋值a &= 5; // 等价于 a = a & 5; (5 in binary: 101) printf("After a &= 5: %d\n", a);// 按位异或后赋值a ^= 3; // 等价于 a = a ^ 3; (3 in binary: 011)printf("After a ^= 3: %d\n", a);// 按位或后赋值a |= 8; // 等价于 a = a | 8; (8 in binary: 1000)printf("After a |= 8: %d\n", a);return 0;
}//Initial value of a : 2
//After a += 3 : 5
//After a -= 1 : 4
//After a *= 2 : 8
//After a /= 4 : 2
//After a %= 3 : 2//a=1
//After a <<= 2 : 4
//After a >>= 1 : 2// 与 &
// 0010 2
// 0101 5
// 0000 0//After a &= 5 : 0//异或 ^
// 0000 0
// 0011 3 异或不同为1
// 0011//After a ^= 3 : 3// 或 |
// 0011 3
// 1000 8
// 1011 11 //After a |= 8 : 11

binary 二进制

🍒强制类型转换符

强制类型转换(Type Casting)允许程序员手动改变一个值的数据类型。

虽然 C 语言在执行表达式时会自动进行类型转换(称为隐式类型转换或自动类型转换),但在某些情况下,程序员需要显式地指定类型转换,以避免自动转换可能带来的精度损失或类型不匹配的问题。

(目标类型) 表达式

示例 1:整数与浮点数之间的转换

将整数 i 强制转换为浮点数,以便在进行除法操作时保留小数部分,避免整数除法的截断行为。

#include <stdio.h>int main() {int i = 10;float f;// 将整数转换为浮点数进行除法操作以保持小数部分f = (float)i / 3;printf("The result of (float)i / 3 is: %f\n", f);return 0;
}//The result of i / 3 is: 3.000000
//The result of (float)i / 3 is: 3.333333

示例 2:字符类型与整数之间的转换

强制类型转换处理字符的 ASCII 值,以及如何将整数转换回字符类型。

#include <stdio.h>int main() {char c = 'A';int x;// 将字符转换为其 ASCII 码的整数值x = (int)c;// 将整数值转换回字符c = (char)(x + 1);printf("Original character was 'A', next character is: '%c'\n", c);return 0;
}
//Original character was 'A', next character is: 'B'

示例 3:提高表达式的计算精度

i1 被强制转换为 double 类型,以保证除法操作的精度,从而避免因为都是整数而导致的结果自动向下取整。

#include <stdio.h>int main() {int i1 = 2, i2 = 3;double result;// 通过强制类型转换确保结果的精度result = (double)i1 / i2;printf("The precise result of 2 / 3 is: %lf\n", result);//The precise result of 2 / 3 is: 0.666667return 0;
}

因为 i1 被强制转换为 double 类型,而 i2 仍然是 int 类型,根据 C 语言的类型提升规则,i2 也会被隐式地转换为 double 类型来执行运算。

示例 4:大小不同的数据类型之间的转换

将一个较大的整数值强制转换为一个字符。由于字符类型的存储空间较小,这样的转换可能会导致数据的丢失。这里 1024 转换为字符后的结果依赖于其在字符类型能表示的范围内的值。

#include <stdio.h>int main() {int i = 1024;char c;// 整数转换为字符,可能会丢失数据c = (char)i; // 只会保留 i 的低8位printf("The character representation of 1024 is: '%c'\n", c);return 0;
}
  1. 整数到字符的转换
  • 通过 (char)i 强制类型转换,整数 1024 被转换为 char 类型。这种转换只保留整数值的低 8 位
  1. 数据的“丢失”
  • 因为 1024(二进制表示为 100 0000 0000)转换为 8 位意味着只保留低 8 位,所以实际上你得到的是 0(二进制的 0000 0000
  1. 输出结果
  • 输出的字符实际上是 ASCII 值为 0 的字符,这是一个控制字符(NULL 字符),在控制台上不会显示为可见字符。

🍒成员访问操作符

  • 使用.操作符来访问一个结构体变量的成员。
  • 使用->操作符来访问一个指向结构体的指针所指向的成员。

使用.操作符

当你有一个结构体变量时,可以使用.操作符直接访问其成员。假设有一个结构体Person,其中包含两个成员:nameage

#include <stdio.h>typedef struct {char* name;int age;
} Person;int main() {Person person;person.name = "Alice";person.age = 30;printf("%s is %d years old.\n", person.name, person.age);return 0;
}

在这个例子中,person是一个Person类型的变量。通过使用.操作符(例如person.nameperson.age),可以访问和修改这个结构体的成员。

使用->操作符

当你有一个指向结构体的指针时,应该使用->操作符来访问其成员。继续使用上面的Person结构体为例,但这次我们将使用一个指针来访问它。

#include <stdio.h>typedef struct {char* name;int age;
} Person;int main() {Person person;Person *ptr = &person;ptr->name = "Bob";ptr->age = 25;printf("%s is %d years old.\n", ptr->name, ptr->age);return 0;
}

在这个例子中,ptr是一个指向Person类型的指针。通过使用->操作符(例如ptr->nameptr->age),可以访问和修改指针所指向的结构体的成员。

🔥操作符优先级

在 C 语言中,不同的操作符有不同的优先级。这意味着,如果在一个表达式中同时使用了多个操作符,那么操作符的优先级将决定了这些操作符的执行顺序。以下是 C 语言中各种操作符的优先级列表,从高到低:

  1. 圆括号 ():最高优先级,用于改变默认的优先级顺序。

  2. 单目操作符:如递增 (++), 递减 (--), 逻辑非 (!), 取反 (~), 正负号 (+, -), 引用 (&), 解引用 (*), sizeof 等。

  3. 算术操作符:乘 (*), 除 (/), 取模 (%), 加 (+), 减 (-)。其中,乘、除、取模的优先级高于加、减。

  4. 移位操作符:左移 (<<), 右移 (>>).

  5. 关系操作符:小于 (<), 小于等于 (<=), 大于 (>), 大于等于 (>=), 等于 (==), 不等于 (!=). 其中,小于、小于等于、大于、大于等于的优先级高于等于、不等于。

  6. 位操作符:按位与 (&), 按位异或 (^), 按位或 (|).

  7. 逻辑操作符:逻辑与 (&&), 逻辑或 (||).

  8. 条件操作符(三元操作符):? :

  9. 赋值操作符:=,以及复合赋值操作符如 +=-=*=/=%=<<=>>=&=^=|=

  10. 逗号操作符:,

  11. 算术操作符优先级

int a = 2;
int b = 3;
int c = a + b * 2;  // 首先计算 b * 2,然后将结果加上 a,所以 c 的值是 8,而不是 10。
  1. 关系操作符和逻辑操作符
int a = 2;
int b = 3;
int c = 4;
int result = a < b && b < c;  // 首先计算 a < b 和 b < c,然后将两个结果进行逻辑与操作,所以 result 的值是 1。
  1. 使用括号改变优先级
int a = 2;
int b = 3;
int c = (a + b) * 2;  // 首先计算括号内的 a + b,然后将结果乘以 2,所以 c 的值是 10,而不是 8。
  1. 赋值操作符和算术操作符
int a = 2;
int b = 3;
a *= b + 2;  // 首先计算 b + 2,然后将结果乘以 a,所以 a 的新值是 10。
  1. 位操作符和关系操作符
int a = 2;  // 二进制表示为 0010
int b = 3;  // 二进制表示为 0011
int result = a & b > 1;  // 首先计算 a & b,然后将结果和 1 进行比较,所以 result 的值是 1。
  1. 移位操作符和算术操作符
int a = 1;
int b = a << 2 + 1;  // 首先计算 2 + 1,然后将 a 左移得到的位数,所以 b 的值是 8。
  1. 三元操作符和算术操作符
int a = 2;
int b = 3;
int c = a > b ? a + b : a - b;  // 首先计算 a > b,根据结果选择执行 a + b 还是 a - b,所以 c 的值是 -1。
  1. 解引用操作符和算术操作符
int a = 2;
int b = 3;
int *p = &a;
int c = *p + b;  // 首先获取 p 指向的值,然后将结果加上 b,所以 c 的值是 5。
  1. 逻辑非操作符和关系操作符
int a = 2;
int b = 3;
int result = !a < b;  // 首先计算 !a,然后将结果和 b 进行比较,所以 result 的值是 0。

这些例子应该能帮助你更好地理解操作符优先级在 C 语言中的应用。

计算大小符sizeof

  1. 计算变量的大小:使用sizeof可以获取任意变量占用的内存大小。这不仅适用于基本数据类型,如intfloatdouble等,也适用于结构体、联合体和数组。

    int a;
    size_t size = sizeof(a); // 计算int类型变量a的大小
    
  2. 计算数据类型的大小:除了变量,sizeof还可以直接用于数据类型,来获取该类型占用的内存大小。

    size_t intSize = sizeof(int); // 直接计算int类型的大小
    
  3. 计算数组的总大小:对于数组,sizeof返回整个数组占用的内存大小。这对于计算数组中元素的数量特别有用,尤其是当数组的大小不是手动指定的时候。

    int arr[10];
    size_t arrSize = sizeof(arr); // 计算整个数组的大小
    
  4. 计算数组单个元素的大小:结合数组的总大小和单个元素的大小,可以计算出数组中元素的总数。

    int arr[10];
    size_t numElements = sizeof(arr) / sizeof(arr[0]); // 计算数组中元素的数量
    
  5. 计算结构体和联合体的大小sizeof同样适用于结构体和联合体,用于计算它们所占用的内存大小。这对于动态内存分配非常有用。

    struct MyStruct {int a;double b;
    };
    size_t myStructSize = sizeof(struct MyStruct); // 计算结构体的大小
    
  6. 在动态内存分配中的应用:在使用malloccalloc进行动态内存分配时,sizeof操作符常用于指定需要分配的内存大小。

    int *p = (int *)malloc(sizeof(int) * 10); // 分配10个int大小的内存
    
  7. 类型安全的内存分配:使用sizeof还可以增强代码的类型安全性,避免在内存分配时出现类型错误。

    int *p = malloc(sizeof(*p) * 10); // 使用*p来确定分配的类型和大小,更安全
    

条件操作符 ? :

条件操作符 ? :,也称为三元操作符,它允许在单个表达式内进行简单的条件判断。基本语法是:

condition ? expression1 : expression2;

这里的condition是一个布尔表达式。如果condition为真(非0值),则整个条件表达式的结果是expression1的值;如果为假(0值),则结果是expression2的值。

示例 1: 基础用法

int score = 75;
const char *result = score >= 60 ? "Passed" : "Failed";
printf("The student has %s the exam.", result);

在这个例子中,如果score大于或等于60,result将被赋值为"Passed";否则,result的值将是"Failed"

示例 2: 嵌套条件操作符

三元操作符也可以嵌套,以处理更复杂的条件。假设我们现在除了判断是否通过外,还要区分优秀(分数大于等于85分):

int score = 90;
const char *result = score >= 85 ? "Excellent" : score >= 60 ? "Passed" : "Failed";
printf("The student's performance was: %s.", result);

这里,第一个条件判断是否score >= 85,如果是,结果是"Excellent"。如果不是,就会进行下一个判断:score >= 60,如果这个条件为真,结果是"Passed",否则是"Failed"

const char *

  1. 初始化和赋值

char *用于可变字符串:

当你需要一个可修改的字符串时,可以使用char *配合动态内存分配或使用字符数组。

  • 使用动态内存分配:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>int main() {char *str = (char *)malloc(20); // 分配 20 个字节的内存空间strcpy_s(str, 20, "Hello"); // 初始化字符串,安全地复制strcat_s(str, 20, ", world!"); // 修改字符串,安全地连接printf("%s\n", str); // 打印字符串free(str); // 释放内存return 0;
}

错误 C2440:“初始化”: 无法从“void *”转换为“char *”

在C++中(看起来您是在使用C++编译器编译C代码),malloc返回的是void *类型,而C++是强类型语言,需要显式地将void *转换为其他类型的指针。因此,需要对malloc的返回值进行类型转换:

char* str = malloc(20); // 错误 C2440:“初始化”: 无法从“void *”转换为“char *”
char *str = (char *)malloc(20); // 强制转换 malloc 返回值为 char *

const char *用于不可变字符串:

当你仅需要访问或传递字符串,而不需要修改它时,应该使用const char *

#include <stdio.h>int main() {const char *str = "Hello, world!";printf("%s\n", str); // 打印字符串// str[0] = 'h'; // 这将产生编译错误return 0;
}

这个例子中,str指向的字符串是不可修改的,任何尝试修改它的操作都会导致编译错误。

  1. 函数参数

使用char *作为函数参数允许函数修改字符串:

#include <stdio.h>
#include <string.h>void appendExclamationMark(char *str) {strcat(str, "!");
}int main() {char greeting[20] = "Hello, world";appendExclamationMark(greeting);printf("%s\n", greeting); // 输出 "Hello, world!"return 0;
}

使用const char *作为函数参数防止函数内部修改字符串:

#include <stdio.h>void printString(const char *str) {printf("%s\n", str);// str[0] = 'h'; // 这会产生编译错误
}int main() {const char *message = "Hello, world!";printString(message); // 安全地打印字符串,不担心被修改return 0;
}

按位取反

当你对一个无符号整数进行按位取反操作时,你实际上是将所有的位从0变为1,以及从1变为0。在C语言中,整数默认是以补码(two’s complement)形式表示的。补码是一种用二进制表示有符号整数的方法,使得负数的表示和加法运算都变得简单。下面是分析过程:

假设unsigned int a = 5;,且我们的系统中int类型是32位的。

  1. 原始的二进制表示:

    • 在32位系统中,a的完整32位二进制表示(包括前导零): 00000000 00000000 00000000 00000101
  2. 进行按位取反操作:

    • a进行~a操作后的结果是将所有位翻转
    • 变成11111111 11111111 11111111 11111010`。
    • 得到的是一个负数的补码(整数默认是以补码形式表示的)
  3. 理解补码表示:

    • 在补码表示中,11111111 11111111 11111111 11111010 (或者取反+1)
    • 先减1: 11111111 11111111 11111111 11111001
    • 取反码得到: 00000000 00000000 00000000 000001106的二进制表示)
    • 十进制-6 11111111 11111111 11111111 11111010

因此,当你在代码中执行printf("~a = %d\n", result);后,输出会是-6,前提是int类型是32位的,并且我们假设系统使用补码表示负数。这个解释依赖于int类型具体的位数以及补码表示法,这两者在现代计算机系统中都是非常通用的假设。

snprintf字符串输出函数

snprintf 是一个在 用于格式化字符串输出的函数,属于 stdio.h 头文件。它的主要功能是将格式化的数据写入一个字符串中。

函数原型

int snprintf(char *str, size_t size, const char *format, ...);
  • str:目标字符串的指针,格式化后的输出将存储在这里。
  • size:目标字符串缓冲区的最大长度。snprintf 会确保不会向 str 写入超过 size - 1 个字符,最后一个位置留给空字符 \0
  • format:格式字符串,控制后续参数如何格式化并插入到 str
  • ...:可变数量的额外参数,这些参数的类型和数量取决于格式字符串中的格式指定符。

返回值

  • 成功时,返回欲写入的字符串长度(不包括空字符),即使这个长度大于 size,也不会实际写入超出 size-1 的内容。
  • 出错时,返回负值。

使用示例

snprintf 将一个整数和一个浮点数格式化为一个字符串,存储在 buffer 中。同时,它还检查格式化后的字符串是否会超出缓冲区的大小,并相应地处理。

#include <stdio.h>int main() {char buffer[50];int a = 10;float b = 3.14159;// 使用 snprintf 将整数和浮点数格式化到字符串中int num_chars = snprintf(buffer, sizeof(buffer), "Integer: %d, Float: %.2f", a, b);if (num_chars >= 0 && num_chars < sizeof(buffer)) {printf("Formatted string: %s\n", buffer);} else if (num_chars >= sizeof(buffer)) {printf("Buffer too small, required %d characters.\n", num_chars);} else {printf("An error occurred.\n");}return 0;
}

细节

要修改代码以更清晰地表达其意图并解释相关的知识点,我们可以对原始代码进行一些调整。我们将重点放在:

  1. 缓冲区大小:确保有足够的空间存储整个字符串和末尾的空字符 \0
  2. snprintf 的返回值:理解它表示的是尝试写入的字符数,不包括末尾的空字符。
  3. 条件判断:清楚地处理各种情况,包括成功写入、缓冲区过小以及其他潜在错误。
#include <stdio.h>int main() {char buffer[3];char buffer2[4];// 使用 snprintf 将整数和浮点数格式化到字符串中int num_chars = snprintf(buffer, sizeof(buffer), "abc");int num_chars2 = snprintf(buffer2, sizeof(buffer2), "abc");printf("buffer1 %d \n", num_chars);printf("buffer1 %s \n", buffer);printf("buffer2 %d \n", num_chars2);printf("buffer2 %s \n", buffer2);return 0;}
//char buffer[3];
//buffer1 3
//buffer1 ab
//char buffer2[4];   
//buffer2 3
//buffer2 abc

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/774833.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Mac上的Gatekeeper系统跟运行时保护

文章目录 问题&#xff1a;无法打开“xxx.xxx”&#xff0c;因为无法验证开发者。macOS无法验证此App是否包含恶意软件。如何解决&#xff1f; 参考资料门禁运行时保护 问题&#xff1a;无法打开“xxx.xxx”&#xff0c;因为无法验证开发者。macOS无法验证此App是否包含恶意软件…

Leetcode - 2580. 统计将重叠区间合并成组的方案数

文章目录 思路AC CODE总结 题目链接&#xff1a;2580. 统计将重叠区间合并成组的方案数 思路 一个区间合并的板子&#xff0c;计算出区间数目之后&#xff0c;每个区间都有放左和放右两种选法&#xff0c;所以最后的答案就是 2 k 2^k 2k。但是需要用c进行二维数组的排序&…

深入浅出(四)VTK库—3D可视化

VAT库 1. VTK简介1.1 下载 2. 编译和安装&#xff1a;3. C示例3.1 显示立方体3.2 VTK显示3D点云 1. VTK简介 VTK&#xff08;Visualization Toolkit&#xff09;是一个开源的跨平台的软件系统&#xff0c;用于3D计算机图形学、图像处理和可视化。它提供了丰富的功能和工具&…

【正点原子FreeRTOS学习笔记】————(4)FreeRTOS中断管理

这里写目录标题 一、什么是中断&#xff1f;&#xff08;了解&#xff09;二、中断优先级分组设置&#xff08;熟悉&#xff09;三、中断相关寄存器&#xff08;熟悉&#xff09;四、FreeRTOS中断管理实验&#xff08;掌握&#xff09; 一、什么是中断&#xff1f;&#xff08;…

深入理解C语言宏定义

目录 一、前言 二、宏的相关语法 2.1 #define 2.2 #undef 2.3 #运算符 2.4 ##运算符 三、宏替换的规则 四、宏与函数 一、前言 我们都知道#define语句可以定义常量&#xff0c;在编译器预处理时会全部将名字替换为常量。与此同时&#xff0c;#define也允许把参数替换到…

【八股】2024春招八股复习笔记3(测试、运维、安全、游戏、客户端)

【2023秋招-2024春招】八股系列&#xff0c;共8篇 【八股】2023秋招八股复习笔记1&#xff08;CSBase部分WXG题&#xff09;【八股】2023秋招八股复习笔记2&#xff08;C基础 & 操作系统&#xff09;【八股】2023秋招八股复习笔记3&#xff08;智力题 & 非技术题50道&…

开放大学2024年春《数控技术 060253》综合大作业参考答案

答案&#xff1a;更多答案&#xff0c;请关注【电大搜题】微信公众号 答案&#xff1a;更多答案&#xff0c;请关注【电大搜题】微信公众号 答案&#xff1a;更多答案&#xff0c;请关注【电大搜题】微信公众号 单选题 1数控系统的核心是&#xff08; &#xff09; …

【项目管理——时间管理】【自用笔记】

1 项目时间管理&#xff08;进度管理&#xff09;概述 过程&#xff1a;&#xff08;2—6&#xff09;为规划过程组&#xff0c;7为监控过程组 题目定义&#xff1a;项目时间管理又称为进度管理&#xff0c;是指确保项目按时完成所需的过程。目标&#xff1a;时间管理的主要目标…

SQLAlchemy修改postgres表的jsonb字段失效

今天遇到一灵异事件&#xff0c;ORM更新操作&#xff0c;一字段始终不生效&#xff0c;最后发现问题原因是postgres的jsonb导致的 表结构&#xff1a; CREATE TABLE XX(value jsonb default {},...)ORM: from flask_sqlalchemy import SQLAlchemy from sqlalchemy.dialects.…

Rust GUI学习 小部件系列(一):如何在iced窗口中使用颜色选择器colorpicker

注&#xff1a;此文适合于对rust有一些了解的朋友 iced是一个跨平台的GUI库&#xff0c;用于为rust语言程序构建UI界面。 前言&#xff1a; 本系列是iced的小部件应用介绍系列&#xff0c;主要介绍iced、iced_aw两个库中涉及的各种小部件的使用及实例演示。 本文所介绍的是co…

安捷伦Agilent E5071B网络分析仪

181/2461/8938产品概述&#xff1a; Agilent E5071B 网络分析仪可为射频组件提供快速、准确的测量。与同类网络分析仪相比&#xff0c;其宽动态范围和低迹线噪声可实现更高的测试质量和吞吐量。内置 2、3 和 4 个测试端口可同时测量具有最多四个端口的组件的所有信号路径。Agi…

中国土壤厚度空间分布数据

土壤层次分为覆盖层 林溶层 淀积层 母质层&#xff0c;其中在林溶层中的最上面那层就是我们通常说的土壤厚度在这一层中&#xff0c;这一层也被称为腐殖层&#xff0c;是肥力性质最好的一层&#xff0c;植物根系和微生物也集中在这一层。至于覆盖层在森林土壤中比较常见&#x…

2024年【G3锅炉水处理】考试题及G3锅炉水处理考试报名

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 G3锅炉水处理考试题参考答案及G3锅炉水处理考试试题解析是安全生产模拟考试一点通题库老师及G3锅炉水处理操作证已考过的学员汇总&#xff0c;相对有效帮助G3锅炉水处理考试报名学员顺利通过考试。 1、【多选题】锅筒…

ClickHouse 最全面试题及参考答案全解析

1. 请简述 ClickHouse 的核心特性及其适用场景 ClickHouse 是一个开源的列式数据库管理系统(DBMS),专为在线分析处理(OLAP)场景设计。其核心特性包括: 列式存储:数据按列存储,优化了分析查询的性能,因为只需读取查询中涉及的列。数据压缩:列式存储天然适合压缩,大幅…

记录一次Vcenter跨VDS网络迁移

纯文字叙述&#xff1a; 1、客户的网络需要迁移vds.但物理网卡已经分配给了其他的VDS。 2、操作思路&#xff1a; 1.先创建好新的VDS以及对应的旧VDS的业务端口组以及Vmker。 2.将Esxi主机加入到新的VDS&#xff0c;不选择物理网卡&#xff0c;只是加入。 3.在Esxi主机侧选中新…

vivado 在远程主机上启动作业、ISE命令图、实施类别,战略描述和指令映射

在远程主机上启动作业 一旦配置了远程主机&#xff0c;使用它们启动Vivado作业就很容易了。下图显示了启动运行对话框。启动跑步时&#xff0c;选择“在远程上启动跑步”hosts或Launch在群集上运行&#xff0c;然后选择特定的群集。这些作业将使用您的要执行的预配置设置。 作业…

Leetcode70. 爬楼梯(动态规划)

Leetcode原题 Leetcode70. 爬楼梯 标签 记忆化搜索 | 数学 | 动态规划 题目描述 假设你正在爬楼梯。需要 n 阶你才能到达楼顶。每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢&#xff1f;示例 1&#xff1a;输入&#xff1a;n 2 输出&#xff1a;2 解…

阿里云服务器安装MySQL(宝塔面板)

只写关键步骤 1. 创建一个云服务器实例 2 修改密码&#xff0c;登录服务器 3. 安装宝塔面板 进入https://www.bt.cn/new/index.html 进入宝塔面板地址 4. 安装Mysql 5. 创建数据库&#xff08;可导入数据库&#xff09; 6. 测试连接数据库 打开Navicat&#xff08;或其他数据…

谈谈 Python 中的 McNemar 检验(三)

前两个文章主要讲的是 McNemar 的原理&#xff0c;文章参考如下&#xff1a; 谈谈 Python 中的 McNemar 检验(一)-CSDN博客 谈谈 Python 中的 McNemar 检验(二)-CSDN博客 这一篇主要说一说 McNemar 的具体算法。 引用上面第一篇文章里的例子&#xff0c;关键是看数据 b 和 …

centos安装jdk的坑

文章目录 一、安装jdk二、查找jdk的目录三、配置JAVA_HOME 一、安装jdk 我们一般用yum search java | grep jdk查询可以安装的jdk 但是一定要注意如下图&#xff0c;必须知道jdk和jre的区别 yum install java-1.8.0-openjdk-devel.x86_64二、查找jdk的目录 用如下命令 sudo…