c/c++易错点收集(持续更新)

本文总结了C/C++编程中常见的错误案例,包括控制语句、变量使用、输入输出处理等方面,帮助开发者避免常见陷阱。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

杂言

易错点

1. 分支和控制语句里面=和!=优先级比较

2. 判断或者循环语句中需要==,但是写成了 = 

3. 变量没有初始化,直接使用,导致结果错乱

4. scanf注意分隔符和&地址符号

5.有些vc和编译器不允许定义变量在语句之后

6. float变量赋值失败的问题

7. 不能直接给字符数组赋值,需要fprintf ,memcpy等

8. c++类中构造函数调用时机分析

9. 定义变量的数组不能初始化

10. strlen函数返回值之间计算结果是大于等于0

11. cin输入变量的时候后面不能有endl

12. 大数整数计算越界问题

13. 打印飞机出现错位

14. 判断字符串结束很容易把'\0' 写成 '0'

15 c++ stack 没有数据直接top会导致异常

16. static变量不能跨文件直接引用,需要用函数获取

17. 交换两个整数的值不成功,没有用地址

18. 一个非常好的理解指针地址的例子

19. 理解c++重载运算符顺序

20. 更改指针本身的值需要传入指针的指针

21.  常考点(++i)+(++i)的输出结果,比较有意思

22. 多层循序,break只会跳出最近的循序

23. switch语句执行顺序理解

24. scanf_s读入赋值问题

25. 指针运算的跨度问题

26.  这种 10<=x<=100 判断的写法问题,永远都是真

27. 结构体作为返回值浅拷贝的问题,成员赋值错误

28. 变量作用域的问题,导致程序执行错误

29. externel变量的作用域问题

30. 浮点数输出四舍五入的问题


杂言

  对它简单处理,它就简单;
  对它复杂处理,它就复杂;
  复杂难以把控,无法预测;
  可预测的程度,关系成败; 

           大风歌
 大风起兮      云飞扬
 威加海内兮  归故乡
 安得猛士兮  守四方!!!
                        ----- 刘邦

  楚汉刘项相争,刘邦前面输了100次,但是赢得了最后一次 

易错点

收集网上和总结了c/c++易错点,会持续更新。 有错误的地方麻烦请指出

1. 分支和控制语句里面=和!=优先级比较

#include <stdio.h>
#include <iostream>

using namespace std;

int main()
{
    char ch;

    // != 优先级要大于 = ,要达到预期 (ch = getchar())加上扩号
    if (ch = getchar() != 'y') {  
        cout << "ch is " << (int)ch << endl;
    } else {
        cout << "ch is " << (int)ch << endl;
    }
    
    return 0;
}

输出结果: (ch = 1) or (ch = 0)
y
ch is 0
x
ch is 1

2. 判断或者循环语句中需要==,但是写成了 = 

#include <stdio.h>
#include <iostream>

using namespace std;

int main()
{
    char ch;

    ch = getchar();
    
    // = 需要改成 == 
    if (ch = 'y') {
        cout << "ch is y" << endl;
    } else {
        cout << "ch is n" << endl;
    }
    
    return 0;
}

输出结果:
y
ch is y
x
ch is y

3. 变量没有初始化,直接使用,导致结果错乱

#include <stdio.h>
#include <iostream>

using namespace std;

int main()
{
    char ch;
    
    // 声明后需要赋值在使用 比如 ch = 'y'

    if (ch == 'y') {
        cout << "ch is y" << endl;
    } else {
        cout << "ch is n" << endl;
    }
    
    return 0;
}

输出结果:
-

4. scanf注意分隔符和&地址符号

/*********************输入分隔符代码**************/
#include <stdio.h>

int main()
{
    char ch;
    int  test;

    //注意输入用逗号隔开
    scanf("%c,%d", &ch, &test);

    printf("ch = %c, test = %d\n", ch, test);

    return 0;
}

输出结果:
y 100
ch = y, test = 0
y,100
ch = y, test = 100

/*********************输入少了取地址&**************/
#include <stdio.h>

int main()
{
    char ch;
    int  test = 0;

    //test输入少了 &, 需要加上&,因为只有传入地址scanf函数才能改变test值, 
    scanf("%c,%d", &ch, test);

    printf("ch = %c, test = %d\n", ch, test);

    return 0;
}

输出结果:
y,100
段错误

这里段错误的原因是 scanf把传入的值作为地址,test这时候是0, 尝试在0存值出现段错误

5.有些vc和编译器不允许定义变量在语句之后

#include <stdio.h>

int main()
{
    char ch;
    int  test;

    scanf("%c,%d", &ch, &test);

    //出现编译错误,这句需要放到scanf那句上面
    char ch1 = 'n';

    printf("ch = %c, ch1 = %c, test = %d\n", ch, ch1, test);

    return 0;
}

6. float变量赋值失败的问题

#include <stdio.h>

int main()
{
    float f;
    
    //10改成10.0, 或者1.0*10
    f = 10/3;

    printf("f = %f\n", f);

    return 0;
}

输出结果
f = 3.000000

期望结果
f = 3.333333

7. 不能直接给字符数组赋值,需要fprintf ,memcpy等

#include <stdio.h>

int main()
{
    char chs[10];
    
    //需要用sprintf(chs, "aaaa")
    chs = "aaaa";

    return 0;
}

输出结果
    编译错误

8. c++类中构造函数调用时机分析

#include <iostream>
using namespace std;

class A
{
public:
    A() {cout << "无参数构造函数" << endl;}
    A(int x) {data = x; cout << "有参数构造函数" << endl;}
    A(A &a) {data = a.data; cout << "拷贝构造函数" << endl;}
    A add(A a) {A temp; temp.data = data + a.data; return temp;}
    void used() {};
private:
    int data;
};

int main()
{
    A a1;  //无参数构造函数
    A a2(2);  //有参数构造函数
    A a3(a2); //拷贝构造函数

    a1 = a2.add(a3); //拷贝构造函数
                     //无参数构造函数
    a1.used();
    return 0;
}

输出结果:
无参数构造函数
有参数构造函数
拷贝构造函数
拷贝构造函数
无参数构造函数

9. 定义变量的数组不能初始化

#include <stdio.h>

int main()
{
    int n = 10;
    char chs[n] = {0};  //可以改成 char chs[n]; 只是声明

    chs[1] = 'A';

    printf("chs index 1 is %c\n", chs[1]);
    return 0;
}

结果输出:

    错误:可变大小的对象不能被初始化
         char chs[n] = {0};

     有些会提示chs数组声明用n出错,需要常量才行

10. strlen函数返回值之间计算结果是大于等于0

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

int main() {
    char a[] = "we go";
    char b[] = "here wo go";

    //strlen返回是无符号的,两个无符号的计算出来都是大于等于0
    //可以改成 (int)strlen(a) - (int)strlen(b)
    if (strlen(a) - strlen(b) > 0) {
        printf("a>b\n");
    }
    else {
        printf("b>a\n");
    }

    return 0;
}


结果输出:
    a>b

期望输出
    b<a

11. cin输入变量的时候后面不能有endl

#include <stdio.h>
#include <iostream>

using namespace std;

int main()
{
    char ch;
    
    // 不能像cout加endl
    cin >> ch >> endl;

    cout << "ch is " << ch << endl;
    
    return 0;
}

输出结果:
    编译错误

12. 大数整数计算越界问题

#include <stdio.h>

/*计算20的阶乘*/
int main() {
    int n = 20;
    int i = 1;
    int result = 1;  //声明为long long类型

    for (i = 1; i <= n; i++) {
        result *= i;
    }
    printf("20! = %d\n", result); %d改为 %ld

    return 0;
}


输出结果:
 20! = -2102132736

期望结果:
  2432902008176640000

还有类似的情况
  1. 比如计算指数 pow函数
  2. 随机数很大情况

13. 打印飞机出现错位

#include <stdio.h>
#include <stdlib.h>
int main()
{

   printf("\n\
      *\n\
      **\n\
*      ***\n\
**    ****\n\
***************\n\
**    ****\n\
*      ***\n\
      **\n\
      *\n");
 
    return 0;
}


这种打印有时候会出现错位, 每一行前面不能有tab等其它字符,
最好顶格开始都用空格,这样基本不会错
   

14. 判断字符串结束很容易把'\0' 写成 '0'

#include <stdio.h>

int main() {
    char a[] = "abcdef";
    int i = 0;

    for (i = 0; a[i] != '0'; i++) { //'0' 改成 '\0'
        printf("%c ", a[i]);
    }
    printf("\n");

    return 0;
}


输出结果: 后面有乱码,打印还是比较容易看出来,有时候是计算会有越界等就比较难看出来
 a b c d e f
                              U   T ]            � p �  �            �  @              * � � : � � � _ �  @      � p �  �                    * � � � ] � a � * � �

期望结果:
 a b c d e f

15 c++ stack 没有数据直接top会导致异常

#include <iostream>
#include <stack>
 
using namespace std;
 
int main()
{
    stack <char> s;
    char ch;
    
    //top之前需要判断是否有数据 s.empty() != 1 
    ch = s.top();
    
    return 0
}


结果输出:
  段错误(吐核)

16. static变量不能跨文件直接引用,需要用函数获取

main文件:

#include <stdio.h>

static int test = 1;

int main()
{
    printf("test is %d\n", test);//输出1
    return 0
}

/**************/
test文件

static int test;
int test_static() 
{
    printf("test is %d\n", test) //输出0
}

分析:
   static变量只有在本地有效, 在结构体里面定义变量也是在本地文件生效

17. 交换两个整数的值不成功,没有用地址

#include <stdio.h>

void swap(int a, int b)
{
     int tmp;
     tmp = a;
     a = b;
     b =tmp;
}

void swap_p(int *a, int *b)
{
     int tmp;
     tmp = *a;
     *a = *b;
     *b =tmp;
}

int main()
{
    int a = 1, b = 2;
    printf("before swap a = %d, b = %d\n", a, b);
    swap(a, b);
    printf("after swap a = %d, b = %d\n", a, b);
    swap_p(&a, &b);
    printf("after swap_p a = %d, b = %d\n", a, b);
    return 0;
}

输出结果:
    before swap a = 1, b = 2
    after swap a = 1, b = 2
    after swap_p a = 2, b = 1

18. 一个非常好的理解指针地址的例子

#include <stdio.h>

int main()
{
    int x;  //x为整数,占用4个字节
    char y,z; //y,z为字符,占用一个字节

    //x本来是用%d读入,y,z本来用%c读入
    scanf("%c%c%d",&x,&y,&z);
    
    printf("\tAscii\tchar\n");
    printf("x:\t%d\t%c\n",x,x);
    printf("y:\t%d\t%c\n",y,y);
    printf("z:\t%d\t%c\n",z,z);
    return 0;
}

结果输出:
输入:96 97 98 
输出:
   Ascii	char
x:	0
y:	0
z:	97	      a


结果分析:
 为啥 z 结果是对的,但是x,y都被影响了呢,这个就要看 x, y, z在scanf时候地址分布情况了
 通过debug信息如下:
    x的地址是0x7fffffffe2bc, y的地址是0x7fffffffe2bb, z的地址是0x7fffffffe2ba
    1. x, y, z顺序存储是相邻的地址
    2. z是按照%d读入的,所以会占用4个字节,原来是1个字节,这样y被设置成了0,x的前两个字节
       被设置了0
 通过分析有如上结果

这个例子对于理解指针和代码运行逻辑还是需要比较深入

19. 理解c++重载运算符顺序

#include <iostream>
 
using namespace std;
 
int main()
{
    string s;
    char ch1 = 'A', ch2 = 'B';
    
    //编译错误
    //s = ch1 + ch2;
    cout << s << endl;

    s = s + ch1 + ch2;
    cout << s << endl;

    //编译错误
    //s = ch1 + ch2 + s;
    cout << s << endl;
    
    return 0
}


输出结果:
  
  AB
  AB

结果分析:
  要有重载函数, 运算符从左到右,所以其它两种情况都是编译不过

20. 更改指针本身的值需要传入指针的指针

#include <stdio.h>

void modify(int *a)
{
     a = (int*)1;
}

void modify_p(int **a)
{
     *a = (int*)1;
}

int main()
{
    int a;
    int *p = &a;
    printf("before modify p = %p\n", p);
    modify(p);
    printf("after modify p = %p\n", p);
    modify_p(&p);
    printf("after modify_p p = %p\n", p);
    return 0;
}

输出结果:
    before modify p = 0x7ffea5b827ac
    after modify p = 0x7ffea5b827ac
    after modify_p p = 0x1

21.  常考点(++i)+(++i)的输出结果,比较有意思

#include <stdio.h>

int main()
{
    int i=3;
    int a=0;

    a=(++i)+(++i)+(++i); 

    printf("%d",a);
    return 0;
}

输出结果:(非15)
16

结果分析:
  gdb通过查看简单的汇编跟踪了一下
  a=(++i)+(++i)+(++i); 改写成 a = a1 + a2 + a3
  过程应该是这样:
    1.先计算 a= a1 + a2, 这个时候是计算两次++是5, 也就是 a1=a2=5,算的10
    2.在计算 a= 10 + a3, 这个时候是计算1次++是6, 原来是5, 所以是 a = 10 + 6 =16

  看起来编译器是取了两个操作数就开始计算

有不同意见一起讨论讨论

  对于这个问题,收集了csdn上问题区提的问题做了一个总结文档,

  可以看看 http://t.csdn.cn/hjqPw

22. 多层循序,break只会跳出最近的循序

#include <stdio.h>

int main() 
{
    int i,j;
    for(i = 0; i < 10; i++)
        for(j = 0; j < 10; j++) {
            if(j == 1) break;
    }
    return 0
}


i那一层循序是不会中断,直到运行完成

23. switch语句执行顺序理解

#include<stdio.h>

void main()
{
    int x = 1, y = 0, a = 0, b = 0;
    switch (x)
    {
        case 1:
            switch (y)
            {
                case 0:a++; break;
                case 1:b++; break;
            }
        case 2:a++; b++; break;
    }
    printf("a=%d, b=%d\n", a, b);
}

输出结果:
    a=2, b=1

结果分析
    对 x case的时候, case 1执行完后没有break,还需要执行case 2

24. scanf_s读入赋值问题

#include<stdio.h>
int main()
{
    int a, b;
    scanf_s("%2d%*3d%1d", &a, &b);
    printf("a=%d, b=%d/n", a ,b);

}

输出结果:
    1234567
    a=12, b=6

结果分析:
    scanf_s里面 * 表示跳过3个字符, nd, n表示字符宽度

25. 指针运算的跨度问题

#include<stdio.h>
int main()
{
    unsigned int a = 0x12345678;
    unsigned char ch;
    unsigned short sh;
    unsigned int *p = &a;
    
    ch = *((unsigned char*)p + 1);
    sh = *((unsigned short*)p + 1);

    printf("ch=%x, sh=%x/n", ch ,sh);

}

输出结果:
    ch=56, sh=1234

结果分析:
    1. 指针在类型转换后走的宽度不一样
    2. a的值在内存存储的地址,高位存储在高地址

26.  这种 10<=x<=100 判断的写法问题,永远都是真

#include <stdio.h>

int main()
{
    int x = 3, y;
    
    do {
        y = x--;
        if (!y) {
            printf("y ", y);
            continue;
        }
    } while (1<=x<=2); //正确的写法 :改成1<=x && x<=2

    printf("\n");
    return 0;
}

输出结果:
    y y y y y y y y y y y y y y y y y y y y y y y y 死循环了

结果分析:
    执行上面的语句后 x = 0; 
    1<=x<=2 对于这个判断是 先判断 1<=x 值为0, 然后 0<=2 值为真, 所以循环条件一直为真

    就算x = 3也是一样的结果

27. 结构体作为返回值浅拷贝的问题,成员赋值错误

#include <stdio.h>
#include <stdlib.h>

typedef struct _node {
     int data;
     int arr[2];
     int *p_arr; //记录arr的地址,用于测试非地址的结构体返回的问题
}node;

node getNode(int data)
{
    node temp;
    temp.data = data;
    temp.p_arr = temp.arr;
    
    printf("getNode temp p_arr = %p\n", temp.p_arr);

    return temp;
}

node* getNode_p(int data)
{
    node *temp = (node *)malloc(sizeof(node));
    temp->data = data;
    temp->p_arr = temp->arr;

    printf("getNode_p temp p_arr = %p\n", temp->p_arr);    

    return temp;
}

int main()
{
    node n1;
    node *n2;

    n1 = getNode(1);//通过非地址获取一个node
    printf("getNode n1 p_arr = %p, n1 arr = %p\n\n", n1.p_arr, n1.arr);

    n2 = getNode_p(2);//通过指针获取一个node
    printf("getNode_p n2 p_arr = %p, n2 arr = %p\n", n2->p_arr, n2->arr);

    return 0;
}

输出结果:
    getNode temp p_arr = 0x7ffe12bd4db4
    getNode n1 p_arr = 0x7ffe12bd4db4, n1 arr = 0x7ffe12bd4e44

    getNode_p temp p_arr = 0xfa7014
    getNode_p n2 p_arr = 0xfa7014, n2 arr = 0xfa7014

结果分析:
    调试发现 n1里面的p_arr 不是指向 n1里面的arr的地址。 非地址传递的时候会发生值拷贝,会重新分配一个新的node地址会改变,所以造成指向的地址发生了改变

28. 变量作用域的问题,导致程序执行错误

#include <stdio.h>

int main()
{
    int i=0; // i 外层定义

    for (int i = 0; i <= 10; i++) { // i 内层定义
    }

    if (i >= 10) {
        printf("ok\n")
    }
    else {
        printf("no\n")
    }
    printf("%d\n", i);

    return 0;
}

结果输出:
    no
    0

结果分析:
    for循环里面虽然对i做了++操作,但是这个i也只有在for循环里有效
    出了for循序是外面定义的i有效,所以i还是等于0
    

29. externel变量的作用域问题

#include <stdio.h>

int fun_test()
{
    extern int x, y;
    int a = 5, b=4;
    x = a - b;
    y = a + b;
    return 0;
}

int x=0, y=0;

int main()
{
    int a=6, b=3;
    
    x = a + b;
    y = a - b;
    fun_test();  //执行

    printf("x=%d, y=%d\n", x, y);

    return 0;
}

输出结果
    x=1, y=9  //非x=9, y=3

结果分析
    extern int x, y; extern只是声明变量,不是定义变量.
    定义变量的是main上面那个定义,注意变量声明和定义的区别

30. 浮点数输出四舍五入的问题

#include <stdio.h>

int main()
{
    float x, y;
    x = 12.234f;
    y = 12.245f;

    printf("x=%.2f, y=%.2f\n", x, y); //输出2位小数
    return 0;
}

输出结果:
    x=12.23, y=12.25

结果分析:
    float输出自动会四舍五入, double也是一样

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

X-道至简

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值