小编use*_*520的帖子

为什么0x55555556除以3 hack工作?

有一个(相对)众所周知的黑客将32位数字除以3.而不是使用实际昂贵的除法,数字可以乘以幻数0x55555556,结果的高32位是我们正在寻找的.例如,以下C代码:

int32_t div3(int32_t x)
{
    return x / 3;
}
Run Code Online (Sandbox Code Playgroud)

与GCC一起编译-O2,结果如下:

08048460 <div3>:
 8048460:   8b 4c 24 04             mov    ecx,DWORD PTR [esp+0x4]
 8048464:   ba 56 55 55 55          mov    edx,0x55555556
 8048469:   89 c8                   mov    eax,ecx
 804846b:   c1 f9 1f                sar    ecx,0x1f
 804846e:   f7 ea                   imul   edx
 8048470:   89 d0                   mov    eax,edx
 8048472:   29 c8                   sub    eax,ecx
 8048474:   c3                      ret 
Run Code Online (Sandbox Code Playgroud)

我猜这个sub指令负责修正负数,因为如果参数是负数,它的作用基本上是加1,NOP否则就是.

为什么这有效呢?我一直试图手动将较小的数字乘以这个掩码的1字节版本,但我看不到一个模式,我无法在任何地方找到任何解释.它似乎是一个神秘的魔术数字,其起源并不为任何人所知,就像0x5f3759df一样.

有人可以解释这背后的算法吗?

algorithm bit-manipulation arithmetic-expressions

7
推荐指数
1
解决办法
762
查看次数

应用与指针相关的运算符时隐式转换为指针类型

请考虑以下代码:

struct X
{
    int x;
};

X xInstance;

class A
{
public:
    operator X*()
    {
        return &xInstance;
    }
};

int main()
{
    A a;
    *a = X();   // ok
    a[0] = X(); // ok
//  a->x = 0;   // error
}
Run Code Online (Sandbox Code Playgroud)

A有一个隐式转换为指针类型.我尝试在三个需要指针的上下文中使用它; 两个第一行很好,但是试图struct X通过operator->依赖隐式转换来引用一个字段是X*行不通的.这是为什么?从概念上讲,在这种背景下有何operator[]不同operator->

经过g++6.3.0和VC++ 2017 测试.

c++ pointers

7
推荐指数
1
解决办法
310
查看次数

未作为最后一个参数传递时的模板参数包扣除

请考虑以下代码:

#include <iostream>
#include <functional>

template<typename... Args>
void testfunc(const std::function<void (float, Args..., char)>& func)
{

}

int main(int argc, char* argv[])
{
    auto func = [](float, int, char) {};
    auto sfunc = static_cast<std::function<void (float, int, char)>>(func);
    testfunc<int>(sfunc);

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

我明确指定了类型,因为(/sf/answers/2833325841/):

当参数包没有出现在参数声明的最后时,它是一个非推导的上下文.非推断的上下文意味着必须明确给出模板参数.

MSVC成功编译它,而gcc和clang都拒绝代码:

source_file.cpp: In function ‘int main(int, char**)’:
source_file.cpp:14:24: error: no matching function for call to ‘testfunc(std::function<void(float, int, char)>&)’
     testfunc<int>(sfunc);
                        ^
source_file.cpp:5:6: note: candidate: template<class ... Args> void testfunc(const std::function<void(float, Args ..., char)>&)
 void testfunc(const std::function<void (float, …
Run Code Online (Sandbox Code Playgroud)

c++ templates variadic-templates c++11

7
推荐指数
1
解决办法
392
查看次数

使用void*的C队列实现 - 好的还是坏的做法?

我使用void指针在C中实现了一个基本的队列结构.程序如下:

  • 初始化结构 - 我设置要存储在队列中的变量类型的大小
  • push - 我将指针传递给要存储的变量,然后队列为自己抓取一个副本
  • front - 结构将void*返回给前面的元素.我可能只是抓住指针,或者memcpy()它有一个本地副本.

结构本身看起来像这样:

struct queue
{
    void* start;    //pointer to the beginning of queue
    void* end;      //-||- to the end
    size_t memsize; //size of allocated memory, in bytes
    size_t varsize; //size of a single variable, in bytes
    void* initial_pointer;      //position of the start pointer before pop() operations
};
Run Code Online (Sandbox Code Playgroud)

start和end只是指向当前分配的内存块中某个位置的void指针.如果我在队列上推送元素,我将结束指针递增varsize.如果我pop(),我只是递减结束指针varsize.

我不认为我应该在这里发布功能代码,它超过100行.

问题:这被认为是好的还是坏的做法?为什么不)?

注意:我知道C中的队列还有很多其他选项.我只是询问这个的质量.

编辑:可以在这里获得实现:http:// 89.70.149.19 /stuff/queue.txt(删除空格)

c queue pointers void

6
推荐指数
1
解决办法
1837
查看次数

转发在该命名空间中的另一个函数内声明命名空间中的函数

我有两个源文件,a.cppb.cpp.在a.cpp,我有一个功能,foo:

namespace ns { void foo() { std::cout << "foo!"; } }
Run Code Online (Sandbox Code Playgroud)

b.cpp,我在命名空间ns中有另一个函数,我想在其中进行原型化和调用foo:

namespace ns
{

void bar()
{
    void foo();
    foo();       
}

}
Run Code Online (Sandbox Code Playgroud)

虽然上面的语法有效,但它foo会让编译器认为它位于全局命名空间中(或者至少这是我从我执行此操作时获得的链接器错误中推断出来的).我的第一个两个思路来解决这个问题是void ns::foo();namespace ns { void foo(); },但也不是有效的.是否有可能在内部正确原型化这个功能bar

请注意,我知道我可以简单地将其移动到文件范围或头文件中,已经有很多问题要问这个,但我想在另一个函数中专门对其进行原型设计.我的编译器是带有最新更新的MSVC 14.0.

编辑:基于我已经完成的一些测试以及我们在评论中的讨论,我相信这是一个MSVC错误.相比:

namespace ns
{

void bar()
{
    void foo();   // link error, MSVC assumes global namespace
    foo();
}

void foo() { }

} // …
Run Code Online (Sandbox Code Playgroud)

c++ namespaces visual-c++ function-prototypes

6
推荐指数
1
解决办法
754
查看次数

在SPA中使用MSAL.js进行Azure B2C身份验证 - 弹出窗口有问题吗?

所以我在考虑使用MSAL对AZURE B2C身份提供程序进行身份验证,但是通过查看代码我可以看到,MSAL依赖于弹出窗口进行登录.(如果我错了,请纠正我).

我的问题是,考虑到B2C网站是面向消费者的,因为许多潜在的网站用户可能会弹出禁用状态,所以不会高度劝阻使用弹出窗口吗?我很难找到一个很好的例子,说明如何在没有弹出窗口的情况下将Azure B2C插入angular2应用程序.

popup single-page-application azure-ad-b2c azure-ad-msal

6
推荐指数
1
解决办法
1465
查看次数

在插槽中调用QDialog :: exec会阻塞主事件循环吗?

我的Qt应用程序的主窗口是一个普通的QMainWindow子类.在那个窗口我有几个按钮; 每个clicked插槽的信号都连接自己的插槽,每个插槽创建一个不同的插槽QDialog:

void onButtonA_clicked()
{
    MyADialog* dialog = new MyADialog(this);
    dialog->exec();
    delete dialog;
}
Run Code Online (Sandbox Code Playgroud)

我一直在读这篇文章:https://wiki.qt.io/Threads_Events_QObjects#Events_and_the_event_loop和作者说

你永远不应该阻止事件循环

哪个让我担心; exec是一个阻塞函数,所以根据他所说的(他的例子Worker::doWork做了很多工作,需要一些时间来完成)我的代码阻止了事件循环,但我没有注意到任何暗示这一点; 相反,主窗口似乎表现正常,并且当我更改代码以使用该show()方法时没有区别.

我阻止了事件循环吗?我应该在这里使用不同的方法吗?

c++ qt event-loop blocking qeventloop

5
推荐指数
1
解决办法
3295
查看次数

检测 scanf 格式字符串中常量的不匹配

man页面scanf

\n\n
\n

指令是以下之一:

\n\n
    \n
  • 一系列空白字符(空格、制表符、换行符等;请参阅 isspace(3))。该指令匹配输入中任意数量的空格,包括无空格。

  • \n
  • 普通字符(即除空格或\'%\'之外的字符)。该字符必须与输入的下一个字符完全匹配。(强调我的)

  • \n
  • 转换规范,以“%”(百分比)字符开头。输入的字符序列将根据此规范进行转换,并将结果放置在相应的指针参数中。如果下一项输入与转换规范不匹配,则转换失败\xe2\x80\x94这是匹配失败。

  • \n
\n
\n\n

现在,考虑以下代码:

\n\n
#include <stdio.h>\n\nint main(void)\n{\n    const char* fmt = "A %49s B";\n    char buf[50];\n\n    printf("%d\\n", sscanf("A foo B", fmt, buf));            // 1\n    printf("%d\\n", sscanf("blah blaaah blah", fmt, buf));   // 0\n    printf("%d\\n", sscanf("A blah blah", fmt, buf));        // 1\n\n    return 0;\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

第 1 行和第 3 行会打印出来1,因为“A”与“A”的匹配成功,“foo”/“blah”与 的匹配也成功%s。第 2 行打印,0因为“A”无法与“blah”匹配,因此解析在那里停止。

\n\n

这一切都很好,也很符合逻辑,但是我有什么办法可以检测到在所有转换规范都成功匹配和分配之后发生了匹配失败吗?在这种情况下,返回的值scanf将是我的格式字符串中的转换说明符的数量,因此直到最后我都无法使用它来判断匹配是否成功。

\n\n …

c io scanf

5
推荐指数
2
解决办法
2550
查看次数

std::filesystem::path::u8string 可能不会返回有效的 UTF-8?

考虑在 Linux 系统上运行的这段代码(编译器资源管理器链接):

#include <filesystem>
#include <cstdio>

int main()
{
    try
    {
        const char8_t bad_path[] = {0xf0, u8'a', 0};  // invalid utf-8, 0xf0 expects continuation bytes
        std::filesystem::path p(bad_path);

        for (auto c : p.u8string())
        {
            printf("%X ", static_cast<uint8_t>(c));
        }
    }
    catch (const std::exception& e)
    {
        printf("error: %s\n", e.what());
    }
}
Run Code Online (Sandbox Code Playgroud)

它故意std::filesystem::path使用具有不正确的 UTF-8 编码的字符串构造一个对象(0xf0 开始一个 4 字节字符,但'a'不是连续字节;更多信息请参见此处)。

调用时u8string,不抛出异常;我发现这令人惊讶,因为cppreference 的文档指出:

  1. u8string() 的结果编码始终为 UTF-8。

检查LLVM 的 libcxx 的实现,我发现确实没有执行验证 - 内部保存的字符串 …

c++ character-encoding c++20

5
推荐指数
1
解决办法
1068
查看次数

WinMain入口点 - 汇编代码看起来好像没有传递给入口点的参数

我正在玩Win32程序集.

一段时间以来,我一直在努力处理WinMain的汇编入口点.从我手写的asm和MSVC提出的NASM和link.exe之间的区别,有一个奇怪的 - 对我而言.

1)C(++)代码 - 只是另一个MessageBox hello世界

#include <Windows.h>

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
    MessageBoxA(NULL, "Hello world", "Window title", MB_OK | MB_ICONEXCLAMATION);
}
Run Code Online (Sandbox Code Playgroud)


2)装配等效

global _main
    extern  _MessageBoxA@16
    extern _ExitProcess@4

section .text
_main:
    push 0x30
    push wintitle
    push message
    push 0
    call _MessageBoxA@16

    push    0
    call    _ExitProcess@4

    section .data
message:
    db      'Hello, World', 0
wintitle:
    db      'Window title', 0
Run Code Online (Sandbox Code Playgroud)


技术"规范":
- 操作系统是32位Win7
- C++程序已经用MS VC++ 2013编译
- 汇编程序已经编译nasm -fwin32 msgbox.asm,然后链接到link …

c assembly winapi entry-point visual-c++

3
推荐指数
1
解决办法
939
查看次数