[置顶文章]打豆豆的一些小问题、不小心会忘记的知识点
2010-12-20 11:45
246 查看
1、错写比较、赋值
经典地,要比较一个数,使用“==”,赋值使用“=”,两都本来相关十万八千里,也没什么关系。可惜,它们太像了,不小心会写错(多写?少写?)。
比如,if (foo=0)与if (foo==0),前者为假,后者可能为真,可能为假。
if(foo=x)是将x赋值给foo,如果x为非零,那么,if语句永远是真的,但如果x是0,它就是假。
而if(foo==x)就是将foo与x比较,如果它们相等,if语句就是真的,反之,就是假。
2、
char *f="a";
char *p = f;
int i;
for (i=0; i<26; i++)
printf("%c ", *p+i);
putchar('\n');
测试结果是显示26个字母,从a开始。
将第一行改为
char f={'a','/0'};
结果也是一样。
(注:在vc和gcc下编译结果一样)
查看这些变量所在的内存,没初始化的都是乱七八糟的数据。但编译后得到的那些地址却是有数据的。我怀疑是编译器做了手脚。
研究了好一会,没什么重大收获,不研究了。
3、对结构体进行memset时,最好是使用结构体的名称,而不是结构体的变量,如果那个变量的个结构体指针的,不小心传递进去就出问题了。指针一般情况下为4字节。
4、Linux下有许多函数指针,如创建线程pthread_create的第三个参数,以及signal的第二个参数。现在写一下函数指针的声明使用真正的函数形式。
signal的第二个参数是指向信号处理函数的指针,声明为
typedef void (*sighandler_t)(int);
实际中的函数形式应该是这样:
void sig_handler(int sig_num)
{
// your code
}
使用是像这样:
signal(SIGINT, sig_handler);
该函数处理的是按下Ctrl+C时的信号。
而pthread_create中的函数指针是这样的:
void *(*start_routine)(void*)
真正函数是这样:
void *start_thread(void* argc)
{
// your code
}
注意,可由pthread_create最后一个参数传递到这个函数中,如果参数有多个,可以考虑结构体。
////////////////////////////////////////////////////////////////////////////////////////////
2011-3-19
数组初始化出现warning: missing braces around initializer:
数组原来形式:
char *b[][10] = {
"linux",
"unix",
"windows",
"mac os",
};
改为:
char *b[][10] = {
{"linux"},
{"unix"},
{"windows"},
{"mac os"},
};
后无警告。
如果追求严格的话,使用数组时还是加上{}比较好一些。
2012-05-02
1、数组作为参数时,会退化为指针,此时万不可用sizeof求“数组”大小。
示例:
int copy_foo(int me[128])
{
int you[128] = {0};
memcpy(you, me, sizeof(me));
return 0;
}
该函数中,仅仅拷贝了前4个字节(32位平台)数据,并非全部数据。这个问题造成项目中的某个bug,印象较深。
PS:这篇文章前面也讲到这个问题,但还是没有牢记,看来“学而时习之”,真的很有必要,特别是像我这样写代码的人。
2、按位与运算
在单片机或嵌入式中,按位与用得比较多,自恃学过两年单片机,自信在这个问题上不会有什么错误。不过还是栽了几个跟头。
1)、有效位
有效位是与一个掩码按位与而得到的。在很多情况,比如一个寄存器,一个IO口,只有某几个位(如低24位,低8位)有效。比如,将一个数的低10位发送到data中,可以按位与0x3ff。如下所示:
SendYouToHell(data, iTemp&0x3ff);
但是,并不是所有的数据都是低10位有效,当数据较多时,很容易出错。我就曾经搞错过。那时需要将一些数据发送到外设的指定地址,有的是10位有效,有的是24位有效,有的是低2位有效。后来调试时发现数据不正常,就是因为按位与的位数搞错了。本来是低10位有效,应该&0x3ff,但实际的代码却是&0x1ff,这样,最高位(第9位)永远是0,就不能反映出设置的值了。
2)、比较
从外设的某个地址获取状态,只有最低位(第0位)有效,此时不能直接将获取到的值与1比较,如下代码所示:
int GetMeFromHell(bool& fLive)
{
BYTE8 bTemp = 0;
int iRet = 0;
iRet = DieOrNot(&bTemp, 0x02);
bTemp &= 0x01; // 注:必须&0x01,下面的bTemp == 1才正常
if (iRet < 0)
{
return -1;
}
else
{
fLive = bTemp == 1;
return bTemp;
}
}
DieOrNot函数从0x02地址中获取到一个状态,存放到bTemp中,bTemp虽然是1个字节,但只有第0位才是我们关心的。如果该变量不与0x01按位与的话,函数后面的bTemp==1不会成立。因为不能保证bTemp一定是0或1。在调试时发现,当第0位为1时,bTemp的值是0xff,为0时是0xfe。这说明,第0位的确发生了变化,但0xff或0xfe不能直接与1作比较,应该在比较前与0x01相与才行。
PS:为何会出现像示例代码那么奇怪的代码?我写这个函数时,只是将返回值作为状态的值,-1出错,0是一个状态,1是另一个状态。但另一同事说这样不好,于是加了一个参数,在这个参数是保存状态值,于是就变成上述那个样子了,我也懒得再改了。
2012-10-08
关于if比较语句写法
if (tmp == 0)与if (0 == tmp)
在项目中常用第二种写法,我也一度习惯使用这种方法。这几天在CU论坛上看帖,有人说用第一种,我觉得他们讲得的确有些道理,于是在自己的代码中也尽量使用第一种。个人认为这更符合阅读习惯,至于有人担心会将“==”写成“=”,本人不作解释。
未使用的函数参数警告问题
有些编译可以检查函数的形参有没有被使用,GCC默认不检查,除非开启-Wunused-parameter。但有些编译器却检查,为了避免其恶心的警告,需要在代码中去掉,如下:
void do_gotohell(int argc, char* argv[])
{
(void)argc; (void)argv; /* Quiet unused warning */
}
这种情况常用于一些固定参数的接口函数。
经典地,要比较一个数,使用“==”,赋值使用“=”,两都本来相关十万八千里,也没什么关系。可惜,它们太像了,不小心会写错(多写?少写?)。
比如,if (foo=0)与if (foo==0),前者为假,后者可能为真,可能为假。
if(foo=x)是将x赋值给foo,如果x为非零,那么,if语句永远是真的,但如果x是0,它就是假。
而if(foo==x)就是将foo与x比较,如果它们相等,if语句就是真的,反之,就是假。
2、
char *f="a";
char *p = f;
int i;
for (i=0; i<26; i++)
printf("%c ", *p+i);
putchar('\n');
测试结果是显示26个字母,从a开始。
将第一行改为
char f={'a','/0'};
结果也是一样。
(注:在vc和gcc下编译结果一样)
查看这些变量所在的内存,没初始化的都是乱七八糟的数据。但编译后得到的那些地址却是有数据的。我怀疑是编译器做了手脚。
研究了好一会,没什么重大收获,不研究了。
3、对结构体进行memset时,最好是使用结构体的名称,而不是结构体的变量,如果那个变量的个结构体指针的,不小心传递进去就出问题了。指针一般情况下为4字节。
4、Linux下有许多函数指针,如创建线程pthread_create的第三个参数,以及signal的第二个参数。现在写一下函数指针的声明使用真正的函数形式。
signal的第二个参数是指向信号处理函数的指针,声明为
typedef void (*sighandler_t)(int);
实际中的函数形式应该是这样:
void sig_handler(int sig_num)
{
// your code
}
使用是像这样:
signal(SIGINT, sig_handler);
该函数处理的是按下Ctrl+C时的信号。
而pthread_create中的函数指针是这样的:
void *(*start_routine)(void*)
真正函数是这样:
void *start_thread(void* argc)
{
// your code
}
注意,可由pthread_create最后一个参数传递到这个函数中,如果参数有多个,可以考虑结构体。
////////////////////////////////////////////////////////////////////////////////////////////
2011-3-19
数组初始化出现warning: missing braces around initializer:
数组原来形式:
char *b[][10] = {
"linux",
"unix",
"windows",
"mac os",
};
改为:
char *b[][10] = {
{"linux"},
{"unix"},
{"windows"},
{"mac os"},
};
后无警告。
如果追求严格的话,使用数组时还是加上{}比较好一些。
2012-05-02
1、数组作为参数时,会退化为指针,此时万不可用sizeof求“数组”大小。
示例:
int copy_foo(int me[128])
{
int you[128] = {0};
memcpy(you, me, sizeof(me));
return 0;
}
该函数中,仅仅拷贝了前4个字节(32位平台)数据,并非全部数据。这个问题造成项目中的某个bug,印象较深。
PS:这篇文章前面也讲到这个问题,但还是没有牢记,看来“学而时习之”,真的很有必要,特别是像我这样写代码的人。
2、按位与运算
在单片机或嵌入式中,按位与用得比较多,自恃学过两年单片机,自信在这个问题上不会有什么错误。不过还是栽了几个跟头。
1)、有效位
有效位是与一个掩码按位与而得到的。在很多情况,比如一个寄存器,一个IO口,只有某几个位(如低24位,低8位)有效。比如,将一个数的低10位发送到data中,可以按位与0x3ff。如下所示:
SendYouToHell(data, iTemp&0x3ff);
但是,并不是所有的数据都是低10位有效,当数据较多时,很容易出错。我就曾经搞错过。那时需要将一些数据发送到外设的指定地址,有的是10位有效,有的是24位有效,有的是低2位有效。后来调试时发现数据不正常,就是因为按位与的位数搞错了。本来是低10位有效,应该&0x3ff,但实际的代码却是&0x1ff,这样,最高位(第9位)永远是0,就不能反映出设置的值了。
2)、比较
从外设的某个地址获取状态,只有最低位(第0位)有效,此时不能直接将获取到的值与1比较,如下代码所示:
int GetMeFromHell(bool& fLive)
{
BYTE8 bTemp = 0;
int iRet = 0;
iRet = DieOrNot(&bTemp, 0x02);
bTemp &= 0x01; // 注:必须&0x01,下面的bTemp == 1才正常
if (iRet < 0)
{
return -1;
}
else
{
fLive = bTemp == 1;
return bTemp;
}
}
DieOrNot函数从0x02地址中获取到一个状态,存放到bTemp中,bTemp虽然是1个字节,但只有第0位才是我们关心的。如果该变量不与0x01按位与的话,函数后面的bTemp==1不会成立。因为不能保证bTemp一定是0或1。在调试时发现,当第0位为1时,bTemp的值是0xff,为0时是0xfe。这说明,第0位的确发生了变化,但0xff或0xfe不能直接与1作比较,应该在比较前与0x01相与才行。
PS:为何会出现像示例代码那么奇怪的代码?我写这个函数时,只是将返回值作为状态的值,-1出错,0是一个状态,1是另一个状态。但另一同事说这样不好,于是加了一个参数,在这个参数是保存状态值,于是就变成上述那个样子了,我也懒得再改了。
2012-10-08
关于if比较语句写法
if (tmp == 0)与if (0 == tmp)
在项目中常用第二种写法,我也一度习惯使用这种方法。这几天在CU论坛上看帖,有人说用第一种,我觉得他们讲得的确有些道理,于是在自己的代码中也尽量使用第一种。个人认为这更符合阅读习惯,至于有人担心会将“==”写成“=”,本人不作解释。
未使用的函数参数警告问题
有些编译可以检查函数的形参有没有被使用,GCC默认不检查,除非开启-Wunused-parameter。但有些编译器却检查,为了避免其恶心的警告,需要在代码中去掉,如下:
void do_gotohell(int argc, char* argv[])
{
(void)argc; (void)argv; /* Quiet unused warning */
}
这种情况常用于一些固定参数的接口函数。
相关文章推荐
- PHP中最容易忘记的一些知识点总结
- OC中一些容易混淆和忘记的知识点总结
- 自我感觉hibernate的一些容易忘记的问题
- 遇到的一些小问题及一些忘记的东西
- [置顶] 高效编程之hashmap你不看就会忘记的知识点
- PHP中最容易忘记的一些知识点总结
- C语言学习中碰到的一些知识点与问题汇总
- [置顶] ubuntu 上cuda安装出现的一些问题
- 新文章尚邮使用评论 ,包含Gmail的设置以及存在的一些问题
- WordPress文章置顶功能的一些应用代码
- [置顶] 直播技术总结(三)ijkplayer的一些问题优化记录
- android学习好的文章及一些问题的解决方法书签整理
- [置顶] 转载文章保存问题
- 信息系统项目管理师一些重要问题和知识点
- [置顶] 有关业余技术开发的一些问题
- 我的JAVA学习笔记(记下一些容易忘记的知识点)持续更新
- [置顶] 图像卷积与滤波的一些知识点
- 织梦前台注册会员上传文章遇到的一些问题
- [置顶] html/css知识点问题及答案汇总
- 浏览器兼容问题,一直是自己最头疼,一直回避的问题,今天看得到了一些启发,发奋今天开始研究这个,哈哈,以下为转载文章,好好学习。