【问题标题】:Sizeof(SIMD vector) issue in macros [duplicate]宏中的 Sizeof(SIMD 向量)问题 [重复]
【发布时间】:2021-03-17 03:26:58
【问题描述】:

我想定义几个宏来计算一个类型的大小。下面是一个正常运行的例子。

#include <stdio.h>

#define A sizeof(long long) / sizeof(int)
#define B 36 / A

int main(){
    printf("%zu %zu\n", A, B); // print out: 2 1
}

虽然在使用 SIMD 向量时会变得很奇怪,例如(A 的定义)

#include <x86intrin.h>
#include <stdio.h>

#define A sizeof(__m128i) / sizeof(int)
#define B 36 / A

int main(){
    printf("%zu %zu\n", A, B); // print out 4 0
}

有什么问题?

【问题讨论】:

  • 提示:算子评估顺序。
  • an example running normally 如果您希望B 在第一种情况下是1,那么我想我不明白您认为B 在第二种情况下可能是什么,其他比0.

标签: c c-preprocessor simd


【解决方案1】:

请记住,宏不是变量:它们只是被替换的标记。所以B 扩展为

36 / sizeof(__m128i) / sizeof(int)

C 和 C++ 中的除法是从左到右关联的,所以这相当于

(36 / sizeof(__m128i)) / sizeof(int) 

如果sizeof(__m128i) 是16 而sizeof(int) 是4,那么这个表达式就是(36 / 16) / 4。现在 C 和 C++ 中的整数除法会被截断,所以 36/1622/40

因此,您应该始终为展开为表达式的宏加上括号:

#define A (sizeof(__m128i) / sizeof(int))
#define B (36 / A)

如果使用 C++,更好的解决方案是根本不使用宏; C++ 中的常量功能非常齐全,可以避免这个问题。

constexpr std::size_t A = sizeof(__m128i) / sizeof(int);
constexpr std::size_t B = 36 / A;

【讨论】:

  • constexpr std::size_t :)
  • 宏替换替换预处理器标记,而不是文本。 (错误地认为它替换了文本会导致学生提出其他问题,他们不明白为什么他们期望像文本替换一样起作用的东西却没有。让我们避免从一开始就给人们错误的想法。)
【解决方案2】:

#define A sizeof(__m128i) / sizeof(int)
#define B 36 / A

然后宏B 将扩展为36 / sizeof(__m128i) / sizeof(int),其评估为(36 / sizeof(__m128i)) / sizeof(int)

第一次除法的结果为零,零除以任何东西都是零。你得到的结果是什么。

解决方案,几乎总是在遇到宏时遇到问题,是在宏定义中添加显式括号:

#define A (sizeof(__m128i) / sizeof(int))
#define B (36 / A)

【讨论】:

    猜你喜欢
    • 2021-08-23
    • 2022-08-17
    • 2014-10-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多