C语言初学习——易错点合集(持续更新中)

转义字符
例题一

int main()
{
    char s[] = "012xy\08s34f4w2";
    int i, n = 0;
    for (i = 0; s[i] != 0; i++)
    {
        if (s[i] >= '0' && s[i] <= '9')
        {
            n++;
        }
    }
    printf("n=%d\n", n);
}

输出:
——
n=3
——

例题二

int main()
{
    char s[] = "\01234";
    for (int i = 0; s[i]; i++)
    {
        printf("1");
        printf("%c\n", s[i]);
    }
}

输出:
——
1

13
14

——

总结:
八进制值的判断取决于后续是否为合法的八进制。
以\开始,最少1位,最多3位,且必须是合法的8进制数字,即0~7,如"\012"。
例:在"\08"中,’\0’为结束符。

自增与自减
例题一

int main()
{
    int k = 5, n = 4;
    while (k--)
    {
        printf("%d\n", k -= 1);
    }
    printf("---------\n");
    while (--n)
    {
        printf("%d\n", --n);
    }
}

输出:
——
死循环
——

总结:
自增与自减也同样应用在循环体判断里,后置--时先根据当前值进行判断,是否进入循环体,再改变自身的值,最后执行循环体语句。

例题二

int main()
{
    int a = 0;
    printf("%d %d %d %d", ++a, a, a++, ++a, a);
}

输出:
——
3 3 1 3
——
总结:
在C语言中有个很常用的函数printf,使用时从右向左压栈,依次从右向左开始计算,计算完后才会往%d中输出,因为有多条赋值语句,所以它是个累加过程,直到压栈结束后输出最终得累加值,而遇到a++这种先使用再变化的量则优先输出。
参考:
https://blog.csdn.net/weixin_43919932/article/details/88544728

问:

#include <stdio.h>

main()
{
    char a[] = "abc", *t;
    int m = 3, j = 0;
    while (j < m)
    {
        t[j] = a[j++];
        // j++;
        printf("%d\n", j);
        printf("%c, %c\n", t[j], a[j]);
    }
    printf("%s\n", t);
    printf("%d\n", j);
    t[j] = 0;
    printf("%s", t);
}

输出:
——
a, b
1
b, c
2
c,
3
abc
3
ab
——
疑问:
为什么t[j]的索引j的值在a[j++]之后没有改变?

指针
例题一

main()
{
    int m = 0;
    int *n = &m;
    printf("value:%d\taddress:%d\n", m, &m);
    *n += 1;
    printf("value:%d\taddress:%d\n", *n, n);
    *n++;
    printf("value:%d\taddress:%d\n", *n, n);
}

输出:
——
value:0 address:6422036
value:1 address:6422036
value:6422040 address:6422040
——
总结:
因为后置 ++ 运算符的优先级高于 * ,所以在编译器的语句实际上是:*(n++);

问:浮点数
例题一

float fun(float h)
{
    return (int)(h * 100) / 100.0;
}
main()
{

    printf("%f\n", fun(22.223000));
    printf("%f", (int)(22.223000 * 100) / 100.0);
}

输出:
——
22.219999
22.220000
——
疑问:
为什么相同的操作,使用函数进行封装后导致了精度缺失

精度缺失

#include <iostream>
#include <vector>

using namespace std;

int main() {
    vector<int> bins = {1000000, 1000000, 1000000}; // 示例数据
    long long ans = 0;

    for (int i = 0; i < bins.size(); ++i) {
        // 下面的计算可能会导致 int 溢出,因为进行的是 int 乘法
        ans += i * bins[i] * i; // 先计算 i * bins[i],结果为 int,可能导致溢出
    }

    return 0;
}

输出:
——
runtime error: signed integer overflow
——
总结:
C++ 中进行算术运算时,运算符(如 * 和 +)会根据参与运算的操作数的类型来选择适当的类型。对于整型(例如 int 类型),即使结果存储在 long long 中,参与运算的 int 类型数字在计算时仍然保留其原有的 int 类型。

posted @ 2024-03-14 23:37  lanying24  阅读(265)  评论(0编辑  收藏  举报