我试图从www.spoj.com解决这个练习:FCTRL - Factorial
你真的不必阅读它,只要你好奇就去做:)
首先我用C++实现它(这是我的解决方案):
#include <iostream>
using namespace std;
int main() {
unsigned int num_of_inputs;
unsigned int fact_num;
unsigned int num_of_trailing_zeros;
std::ios_base::sync_with_stdio(false); // turn off synchronization with the C library’s stdio buffers (from https://stackoverflow.com/a/22225421/5218277)
cin >> num_of_inputs;
while (num_of_inputs--)
{
cin >> fact_num;
num_of_trailing_zeros = 0;
for (unsigned int fives = 5; fives <= fact_num; fives *= 5)
num_of_trailing_zeros += fact_num/fives;
cout << num_of_trailing_zeros << "\n";
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我上传它作为g ++ 5.1的解决方案
结果是: …
我遇到了一个有趣的场景,根据正确的操作数类型我得到了不同的结果,我无法理解它的原因.
这是最小的代码:
#include <iostream>
#include <cstdint>
int main()
{
uint16_t check = 0x8123U;
uint64_t new_check = (check & 0xFFFF) << 16;
std::cout << std::hex << new_check << std::endl;
new_check = (check & 0xFFFFU) << 16;
std::cout << std::hex << new_check << std::endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我在Linux 64bit上使用g ++(gcc版本4.5.2)编译了这段代码:g ++ -std = c ++ 0x -Wall example.cpp -o example
输出是:
ffffffff81230000
81230000
我无法真正理解第一种情况下输出的原因.
为什么在某些时候将任何时间计算结果提升为带符号的64位值(int64_t),从而导致符号扩展?
如果16位值在第一位左移16位然后提升到64位值,我会在两种情况下都接受'0'的结果.如果编译器首先提升checkto uint64_t然后执行其他操作,我也接受第二个输出.
但是如何&使用0xFFFF(int32_t)和0xFFFFU(uint32_t)会导致这两个不同的输出?
假设以下课程:
class Example
{
public:
...
Example& operator=(const Example& rhs);
...
private:
other_type *m_content;
size_t m_content_size;
}
Example& Example::operator=(const Example& rhs)
{
if (this != &rhs)
{
delete m_content;
m_content = nullptr;
m_content = getCopiedContent(rhs);
}
return *this;
}
Run Code Online (Sandbox Code Playgroud)
我知道这不是最好的实现方式,operator=但这是有目的的,因为我的问题是关于这两行:
m_content = nullptr;
m_content = getCopiedContent(rhs);
Run Code Online (Sandbox Code Playgroud)
可以是编译器将优化,m_content = nullptr;即使getCopiedContent未定义为throw()或noexcept:
other_type* getCopiedContent(const Example& obj);
Run Code Online (Sandbox Code Playgroud)
一方面,编译器可以假设如果在m_content = nullptr;我m_content用返回值覆盖值之后getCopiedContent,它可以优化整个m_content = nullptr;表达式.另一方面,如果编译器将其优化并 …
使用宽松的存储顺序,例如对于引用计数指针,是否允许编译器优化掉后续的递增和递减?
std::atomic_int32_t ai;
for (size_t i = 0; i < 10000; i++)
{
ai.fetch_add(1, std::memory_order_relaxed);
ai.fetch_sub(1, std::memory_order_relaxed);
}
Run Code Online (Sandbox Code Playgroud)
看看反汇编它看起来不像.但是由于允许重新排序并且atomic行为类似于计数器,只是线程安全,人们可以争辩说他可以优化,好像它是一个普通的int.
我对ARM处理器的内部细节不是很熟悉,但是我不了解Nvidia Jetson Nano开发板上的以下行为。
C代码示例...
//main.c
#include <stdio.h>
int main()
{
int fred = 123;
int i;
for(i = -10 ; i <= 10 ; i++)
printf("%d / %d == %d\n", fred, i, fred / i);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
编译:
gcc main.c -ggdb
Run Code Online (Sandbox Code Playgroud)
运行生成的a.out可执行文件将产生以下输出...
123 / -10 == -12
123 / -9 == -13
123 / -8 == -15
123 / -7 == -17
123 / -6 == -20
123 / -5 == -24
123 / -4 == -30
123 / …Run Code Online (Sandbox Code Playgroud) 我在看下面的代码:
#include <stdint.h>
void foo(uint32_t *pVal)
{
uint32_t i = 8;
*pVal = i *= 10;
}
Run Code Online (Sandbox Code Playgroud)
乍一看很明显,在返回之前foo(),*pVal将是80以及价值i.这确实是根据godbolt.org发生的事情:
foo: # @foo
push rbp
mov rbp, rsp
mov qword ptr [rbp - 8], rdi
mov dword ptr [rbp - 12], 8
imul eax, dword ptr [rbp - 12], 10
mov dword ptr [rbp - 12], eax
mov rdi, qword ptr [rbp - 8]
mov dword ptr [rdi], eax
pop rbp
ret
Run Code Online (Sandbox Code Playgroud)
但是从这里 …
考虑以下局部变量的声明:
bool a{false};
bool b{false};
bool c{false};
bool d{false};
bool e{false};
bool f{false};
bool g{false};
bool h{false};
Run Code Online (Sandbox Code Playgroud)
在 x86-64 架构中,我希望优化器将这些变量的初始化减少到类似mov qword ptr [rsp], 0. 但相反,我使用所有编译器(无论优化级别如何)得到的结果是某种形式的:
mov byte ptr [rsp + 7], 0
mov byte ptr [rsp + 6], 0
mov byte ptr [rsp + 5], 0
mov byte ptr [rsp + 4], 0
mov byte ptr [rsp + 3], 0
mov byte ptr [rsp + 2], 0
mov byte ptr [rsp + 1], 0
mov byte …Run Code Online (Sandbox Code Playgroud) 假设我有一个宏(更多细节为何,以下是在PS部分)
void my_macro_impl(uint32_t arg0, uint32_t arg1, uint32_t arg2);
...
#define MY_MACRO(arg0, arg1, arg2) my_macro_impl((uint32_t)(arg0), (uint32_t)(arg1), (uint32_t)(arg2))
Run Code Online (Sandbox Code Playgroud)
将要在其上使用该宏的硬件是小尾数法,并使用32位体系结构,以便所有指针的宽度最大为(包括)32位宽度。我的目标是在用户通过uint64_t或int64_t错误输入参数时警告用户。
我想使用sizeof这样的
#define MY_MACRO(arg0, arg1, arg2) do \
{ \
static_assert(sizeof(arg0) <= sizeof(uint32_t)); \
static_assert(sizeof(arg1) <= sizeof(uint32_t)); \
static_assert(sizeof(arg2) <= sizeof(uint32_t)); \
my_macro_impl((uint32_t)(arg0), (uint32_t)(arg1), (uint32_t)(arg2)); \
} while (0)
Run Code Online (Sandbox Code Playgroud)
但是用户可以使用MY_MACRO位域,然后我的代码无法编译:
错误:“ sizeof”对位字段的无效应用
问题:是否可以选择在编译时检测宏参数的大小是否大于(例如)uint32_t?
聚苯乙烯
它的MY_MACRO作用类似于printf实时嵌入式环境。该环境有一个硬件记录器,最多可以接收5个参数,每个参数应为32位。目的是保留的标准格式printf。格式字符串是脱机解析的,并且解析器很清楚每个参数都是32位,因此它将根据%...格式字符串中的进行强制转换。可能的用法如下。
不需要的用法:
uint64_t time = systime_get();
MY_MACRO_2("Starting execution at …Run Code Online (Sandbox Code Playgroud) 假设以下代码:
uint64_t g_global_var;
....
....
void foo(void)
{
uint64_t local_32bit_low = g_global_var & 0xFFFFFFFF;
....
}
Run Code Online (Sandbox Code Playgroud)
使用当前的工具链,此代码可以按预期工作,local_32bit_low实际上包含的低32位g_global_var。
我想知道标准C是否保证该代码将始终按预期工作?我担心的是,编译器可能会将0xFFFFFFFF视为-1的整数,并且提升为uint64_t0xFFFFFFFFFFFFFFFF时。
聚苯乙烯
我知道,为了安全起见,在这种情况下最好使用0xFFFFFFFFULL。关键是我在旧版代码中看到了它,我想知道是否值得修复。
我知道,一旦取消引用,带有对齐冲突的指针转换的结果就会调用未定义的行为。
\n但是仅用于地址计算(不取消引用)的指针转换怎么样?
\nvoid *addr_calc(single_byte_aligned_struct_t *ptr, uint32_t dword_offset)\n{\n uint32_t *dw_ptr = (uint32_t *)ptr;\n\n return dw_ptr + dword_offset;\n}\nRun Code Online (Sandbox Code Playgroud)\n我们假设 的ptr值为X。能保证一定addr_calc()会回来X + sizeof(uint32_t) * dword_offset吗?
我的假设是,但最近我在 C11 标准的J.2 节中看到了以下未定义行为
\n\n\n\xe2\x80\x94 两个指针类型之间的转换会产生不正确对齐的结果 (6.3.2.3)。
\n
如果我理解正确的话,转换本身会调用未定义的行为,而不仅仅是取消引用,这意味着在这种情况下,即使是指针算术也可能表现出不可预测的行为。我对吗?
\nc memory-alignment pointer-arithmetic undefined-behavior c11