这篇博客记录我为 C/C++ 写过的bug
- 源代码:
int check(List L1, List L2)
{
...
}
while ((ret=check(L1,L2)) = NULL)
{
...
}
报错:
expression must be a modifiable lvalue
- 分析:
这里lvalue
应该是 left value
的意思。编译器说您表达式的左值必须是可变的。
发现问题是 == 写成了 =。左边因为存在括号,会先计算出括号内的值。也就是说,(ret = check(L1,L2))
将会被替换为check(L1,L2)
的结果,在此处是一个指针类型的变量。一个普通变量的值不能被更改。(就像我不能写1 = 2;
这样的语句。)
- 修改方法:
while ((ret=check(L1,L2)) == NULL) { ... }
- 源代码
编译器Warning:char *str[10]; str[1] = "Hello";
ISO C++ forbids converting a string constant to 'char*' [-Wwrite-strings]
char *str[10];
定义的是指针数组。因此类似的,
char *p;
p = "Hello";
会报出同样的错误。
- 分析:
"Hello"
在C语言中是字符串常量,在c++中叫做string literal
,类型是const char *
其实际是一个指向首字母'H'
地址的指针。
此处是将一个Const char *
类型强制转换为 char *
类型,有改动常量的可能性。
编译运行的结果会因编译器和操作系统共同决定,有的编译器会通过,有的会抛异常,就算过了也可能因为操作系统的敏感性而被杀掉。
- 修改方法
或者const char *p = "Hello";
char *p = (char *) "Hello";
- 问题
向一个字符指针读入字符串时出现
segment fault
。 例如:scanf("%s",p);
更隐蔽的情况是,我定义了一个字符指针数组。
char * str[10];
for (int i=0;i<10;i++)
{
scanf("%s",str[i]);
}
- 原因
在str数组中的每一个指针都是悬垂指针,没有指向一个已经分配的地址。
就像是我定义一个 char * p;
此时p
指向的是NULL
或者一个随机地址。
此时scanf("%s",p);
是会出问题的。
- 修改方法
for (int i=0;i<10;i++) { str[i]=(char)malloc(MAX_LEN * sizeof(char)); scanf("%s",str[i]); }
C语言:
variably modified 'xxx' at file scope
const int MAXLEN = 50;
char str[MAXLEN];
gcc编译报错。
- 原因
C语言中的const并不是常量的意思。它的本意是只读 read only
The const qualifier really means read-only; an object so qualified is a run-time object which cannot (normally) be assigned to. The value of a const-qualified object is therefore not a constant expression in the full sense of the term, and cannot be used for array dimensions, case labels, and the like. (C is unlike C++ in this regard.) When you need a true compile-time constant, use a preprocessor #define (or perhaps an enum)
- 解决方法:使用
define
int a[3][4], (*num)[4]; num[0]=&a[1][3];
编译器报错:expression must be a modifiable Ivalue
- 原因
int (*p)[4];
指的是一个指针, 指向4个int
类型数据
所以p = &a[0]
就是正确的。
(TYPE) malloc(SIZE);
用法: 在动态内存(堆)中开辟 SIZE 字节的空间,返回首地址
注意: TYPE 一般是一个指针,指针变量存储一个8字节整数。
SIZE我们一般使用N*sizeof(TYPE),注意这里TYPE一不用指针,而是本体代表的数据类型。