C++宏乘法发生了什么

Ter*_* Li 2 c++ macros multiplication

#define MAX 265

std::cout << 0 * MAX << std::endl; //to my surprise, the output is 9 rather than 0
Run Code Online (Sandbox Code Playgroud)

这个C++宏乘法有什么问题?

编辑:

以下是完整版本.

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

#define NAME_BYTES 256
#define VERSION_BYTES 256
#define SIZE_BYTES 32
#define USED_LOCK_COUNT_BYTES 32
#define LOCK_NAME_BYTES 256
#define LOCK_TYPE_BYTES 1
#define PID_BYTES 4
#define TID_BYTES 4
#define LOCK_BYTES LOCK_NAME_BYTES + LOCK_TYPE_BYTES + PID_BYTES + TID_BYTES 
#define HEADER_BYTES NAME_BYTES + VERSION_BYTES + SIZE_BYTES + USED_LOCK_COUNT_BYTES

int main() {
  std::cout << "LOCK_BYTES: " << LOCK_BYTES << std::endl;
  std::cout << "HEADER_BYTES: " << HEADER_BYTES << std::endl;
  std::cout << "LOCK_BYTES * 0: " << 0 * LOCK_BYTES << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

这是我刚刚得到的结果和编译器信息.

yifeng @ yifeng-Precision-WorkStation-T3400:〜/ Shared-Memory-Solution/examples/IMPL $ g ++ -v使用内置规格.COLLECT_GCC = g ++ COLLECT_LTO_WRAPPER =/usr/lib/gcc/x86_64-linux-gnu/4.6.1/lto-wrapper目标:x86_64-linux-gnu配置为:../ src/configure -v --with-pkgversion =' Ubuntu/Linaro 4.6.1-9ubuntu3' - with-bugurl = file:///usr/share/doc/gcc-4.6/README.Bugs --enable-languages = c,c ++,fortran,objc,obj-c ++ ,go --prefix =/usr --program-suffix = -4.6 --enable-shared --enable-linker-build-id --with-system-zlib --libexecdir =/usr/lib --without-included -gettext --enable-threads = posix --with-gxx-include-dir =/usr/include/c ++/4.6 --libdir =/usr/lib --enable-nls --with-sysroot =/--enable -clocale = gnu --enable-libstdcxx-debug --enable-libstdcxx-time = yes --enable-plugin --enable-objc-gc --disable-werror --with-arch-32 = i686 --with- tune = generic --enable-checking = release --build = x86_64-linux-gnu --host = x86_64-linux-gnu --target = x86_64-linux-gnu线程模型:posix gcc版本4.6.1(Ubuntu/Linaro 4.6.1-9ubuntu3)

yifeng @yifeng-Precision-WorkStation-T3400:〜/ Shared-Memory-Solution/examples/IMPL $ ./a.out LOCK_BYTES:265 HEADER_BYTES:576 LOCK_BYTES*0:9

编辑:非常感谢你们!我很高兴我决定发布这个,虽然我得到了这么多的downvotes.关于MACRO,需要学到多少教训!

Mik*_*our 11

你应该总是在宏定义周围加上括号:

#define LOCK_BYTES (LOCK_NAME_BYTES + LOCK_TYPE_BYTES + PID_BYTES + TID_BYTES)
Run Code Online (Sandbox Code Playgroud)

否则,代码扩展为:

cout << 0 * LOCK_NAME_BYTES + LOCK_TYPE_BYTES + PID_BYTES + TID_BYTES
Run Code Online (Sandbox Code Playgroud)

输出的值LOCK_TYPE_BYTES + PID_BYTES + TID_BYTES.

更好的是,除非你真的需要,否则不要使用宏.这些更好地表示为常量变量.

  • @TerryLiYifeng:是的,调试宏可能会花费很多时间.你最好避开它们,除非在非常罕见的情况下,常数,函数和模板都不能做你想要的. (5认同)

Xeo*_*Xeo 9

std::cout << "LOCK_BYTES * 0: " << 0 * LOCK_BYTES << std::endl;
Run Code Online (Sandbox Code Playgroud)

扩展到

std::cout << "LOCK_BYTES * 0: " << 0 * LOCK_NAME_BYTES + LOCK_TYPE_BYTES + PID_BYTES + TID_BYTES << std::endl;
Run Code Online (Sandbox Code Playgroud)

反过来扩展到

std::cout << "LOCK_BYTES * 0: " << 0 * 256 + 1 + 4 + 4 << std::endl;
Run Code Online (Sandbox Code Playgroud)

并为优先规则增加了一些parens:

std::cout << "LOCK_BYTES * 0: " << ((((0 * 256) + 1) + 4) + 4) << std::endl;
Run Code Online (Sandbox Code Playgroud)

评估为

std::cout << "LOCK_BYTES * 0: " << 9 << std::endl;
Run Code Online (Sandbox Code Playgroud)

将您的代码更改为

std::cout << "LOCK_BYTES * 0: " << 0 * (LOCK_BYTES) << std::endl;
Run Code Online (Sandbox Code Playgroud)

甚至更好,使用const unsigned int值:

const unsigned int NAME_BYTES = 256;
const unsigned int VERSION_BYTES = 256;
const unsigned int SIZE_BYTES = 32;
const unsigned int USED_LOCK_COUNT_BYTES = 32;
const unsigned int LOCK_NAME_BYTES = 256;
const unsigned int LOCK_TYPE_BYTES = 1;
const unsigned int PID_BYTES = 4;
const unsigned int TID_BYTES = 256;
const unsigned int LOCK_BYTES = LOCK_NAME_BYTES + LOCK_TYPE_BYTES + PID_BYTES + TID_BYTES;
const unsigned int HEADER_BYTES = NAME_BYTES + VERSION_BYTES + SIZE_BYTES + USED_LOCK_COUNT_BYTES;
Run Code Online (Sandbox Code Playgroud)

好哇!突然间,你不再有奇怪的问题了.

  • 'const`讨论的+1.我还要为所有大名单奖励-1.但是我很累,一次投票就足够了......干杯,并且请不要使用它们所有的大名单,因为它就像是SHOUTING而且它也与宏名称的约定相冲突, (2认同)
  • 这是Java惯例,它在C++中不能很好地工作.Java从C语言中获得它,而没有Java人员理解它.当然你可以选择在C++中使用这种非常不合适的约定,但是只要你这样做,并忽略例如FAQ lite,Bjarne的常见问题解答,我在这里的建议等,你知道或者至少会有怀疑你有一些非常基本的东西你无法理解.干杯, (2认同)

App*_*ker 6

我觉得你算错了一点.不像变量那样,它们的值在预处理器编译之前插入到它们的位置.因此,编译器将看到的是:

 0* LOCK_NAME_BYTES + LOCK_TYPE_BYTES + PID_BYTES + TID_BYTES 
Run Code Online (Sandbox Code Playgroud)

这是:

 0 * 256 + 1 + 4 + 4
Run Code Online (Sandbox Code Playgroud)

根据操作顺序,C++的运算符优先级所基于的,乘法首先发生,因此它将等于9而不是0.

PS如果您没有开发嵌入式系统或过时的游戏机,如Gameboy Color(注意我的gravatar),我强烈建议您使用const关键字而不是#defines来表示这类事情.

  • 这不是答案,而是*评论*. (7认同)
  • 这不能证明发布非答案是正确的. (4认同)
  • @DeadMG:有趣的另一个"为我工作"的答案已经收到了赞成票.这个答案甚至更好:可能是提问者确实在控制台字体中误读了0. (3认同)
  • @UncleBens:不是来自我.它可能只收到那些选票,因为它更早.这同样错了.它们都不是"答案",它们毫无价值. (2认同)

sbi*_*sbi 5

问题是你使用宏.您的

#define LOCK_BYTES LOCK_NAME_BYTES + LOCK_TYPE_BYTES + PID_BYTES + TID_BYTES
Run Code Online (Sandbox Code Playgroud)

不做你的想法.它所做的是文字上取代的每一次出现LOCK_BYTESLOCK_NAME_BYTES + LOCK_TYPE_BYTES + PID_BYTES + TID_BYTES.所以

0 * LOCK_BYTES
Run Code Online (Sandbox Code Playgroud)

扩展到

0 * LOCK_NAME_BYTES + LOCK_TYPE_BYTES + PID_BYTES + TID_BYTES
Run Code Online (Sandbox Code Playgroud)

这是C++.尽可能避免使用宏.我们有const这个.


这对我来说很好用:

#include <iostream>

const int name_bytes = 256;
const int version_bytes = 256;
const int size_bytes = 32;
const int used_lock_count_bytes = 32;
const int lock_name_bytes = 256;
const int lock_type_bytes = 1;
const int pid_bytes = 4;
const int tid_bytes = 4;
const int lock_bytes = lock_name_bytes + lock_type_bytes + pid_bytes + tid_bytes;
const int header_bytes = name_bytes + version_bytes + size_bytes + used_lock_count_bytes;

int main() {
  std::cout << "lock_bytes: " << lock_bytes << std::endl;
  std::cout << "header_bytes: " << header_bytes << std::endl;
  std::cout << "lock_bytes * 0: " << 0 * lock_bytes << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

你有一本好的C++书可供学习吗?你应该.

  • +1为_你有一本好的C++书籍可以学习吗?_. (2认同)