这可能是一个愚蠢的问题,但我现在在网上和网上搜索了很长一段时间并且无法得出一个明确的答案(我的尽职调查谷歌搜索).
所以我是编程的新手......我的问题是,主函数如何知道不同文件中的函数定义(实现)?
恩.说我有3个文件
//main.cpp
#include "myfunction.hpp"
int main() {
int A = myfunction( 12 );
...
}
Run Code Online (Sandbox Code Playgroud)
-
//myfunction.cpp
#include "myfunction.hpp"
int myfunction( int x ) {
return x * x;
}
Run Code Online (Sandbox Code Playgroud)
-
//myfunction.hpp
int myfunction( int x );
Run Code Online (Sandbox Code Playgroud)
-
我得到预处理器如何包含头代码,但是头和主函数如何知道函数定义是否存在,更不用说它了?
如果不清楚或者我对这里的新事物有很大误解,我会道歉
现代 C++ 新手,试图弄清楚这里发生了什么。以下代码编译正常:
template<int base_num>
class Base{
public:
Base() {}
};
template<int derived_num>
class Derived : public Base<0> { // Integer literal passed to base template
public:
Derived(): Base() {}
};
Run Code Online (Sandbox Code Playgroud)
而以下内容:
template<int base_num>
class Base{
public:
Base() {}
};
template<int derived_num>
class Derived : public Base<derived_num> { // Non-type template parameter passed to base template
public:
Derived(): Base() {}
};
Run Code Online (Sandbox Code Playgroud)
失败:
类 'Derived<derived_num>' 没有任何名为 'Base' 的字段
我推测发生这种情况是因为derived_num
它本身不算作“结构类型”,但不确定。希望有人可以解释这里发生了什么,以及是否有办法将非类型模板参数“传递”到基类模板。
更新:
显式定义模板“修复”了这个
template<int derived_num>
class Derived : public Base<derived_num> { …
Run Code Online (Sandbox Code Playgroud) 我正在std::variant
使用“重载”模式std::visit
,如下所示:
#include <iostream>
#include <variant>
template<class... Ts> struct overloaded : Ts... { using Ts::operator()...; };
template<class... Ts> overloaded(Ts...) -> overloaded<Ts...>;
int main(void) {
std::variant<int, float> var;
auto fs = overloaded {
[](int var) {std::cout << "var is int" << std::endl;},
[](float var) {std::cout << "var is float" << std::endl;}
};
var = 0;
std::visit(fs, var);
var = 0.0f;
std::visit(fs, var);
}
Run Code Online (Sandbox Code Playgroud)
在 cppreference 上,有一个示例:
// explicit deduction guide (not needed as of C++20) …
Run Code Online (Sandbox Code Playgroud) 当前 (Linux) 版本的 SysV i386 ABI 需要在调用之前进行 16 字节堆栈对齐:
输入参数区域的末尾应在 16(32,如果 __m256 在堆栈上传递)字节边界上对齐。换句话说,当控制权转移到函数入口点时,值 (%esp + 4) 始终是 16 (32) 的倍数。
在 GCC 8.1 上,此代码在调用之前将堆栈与 16 字节边界对齐callee
:( Godbolt )
来源 | # 字节 |
---|---|
称呼 | 4 |
推送ebp | 4 |
子特别是,24 | 24 |
子特别, 4 | 4 |
推入eax | 4 |
推入eax | 4 |
推入eax | 4 |
全部的 | 48 |
在 GCC 8.2 及更高版本的所有版本上,它与 4 字节边界对齐:( Godbolt )
来源 | # 字节 |
---|---|
称呼 | 4 |
推送ebp | 4 |
子特别,16 | 16 |
推入eax | 4 |
推入eax | 4 |
推入eax | 4 |
全部的 | 36 |
我正在学习 x64 并且我讨厌 make,所以我试图让 cmake 使用 NASM 构建二进制文件。
cmake 大致支持这一点,但文档很垃圾。这就是我现在所做的工作,将堆栈溢出中的内容拼凑在一起,然后删除不会破坏构建的所有内容:
cmake_minimum_required(VERSION 3.14)
set(CMAKE_ASM_NASM_LINK_EXECUTABLE "ld <LINK_FLAGS> <OBJECTS> -o <TARGET> <LINK_LIBRARIES>")
set(CMAKE_ASM_NASM_OBJECT_FORMAT elf64)
project(test_project ASM_NASM)
set_source_files_properties(test.s PROPERTIES LANGUAGE ASM_NASM)
add_executable(test test.s)
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
target_compile_options(test PRIVATE -g -Fdwarf)
endif()
Run Code Online (Sandbox Code Playgroud)
所以有几个问题,为什么我必须告诉 cmake 使用ld
链接,有没有更好的方法来做到这一点?
有什么target_object_format
可以用来指定对象格式而不是全局设置的内容吗?
有没有办法让 cmake 识别新的扩展名,而不是专门告诉它每个文件是 ASM_NASM?