分类 C/C++ 下的文章

MSVC中的_BitScanForward和GCC中的__builtin_ctzl


问题

索博尔算法中用到了_BitScanForward这个函数,在做统信UOS适配的时候发现这个函数是MSVC专有的,百度了一下linux下对应的有__builtin_ctz相关的系列函数

头文件引用

*winlinux
头文件intrin.hx86intrin.h
函数_BitScanForward__builtin_ctzl

代码对比

win

#include <iostream>
#include <intrin.h>
using namespace std;

#pragma intrinsic(_BitScanForward)

static const unsigned QRNG_NDMS = 32;
    struct
    {
        unsigned __int64 uValue;
        unsigned uPrevSeed;
    } m_prev[QRNG_NDMS];

unsigned __int64 cjn[QRNG_NDMS][63] = { 0 };

int main()
{
    unsigned long mask = 0;
    unsigned long index;
    unsigned char isNonzero;

    unsigned m_uCurSeed = 2048,m_uCurDim;
    m_uCurDim = 0;
    unsigned grayCode = (m_uCurSeed >> 1) ^ m_uCurSeed;
    unsigned changedBits = m_prev[m_uCurDim].uPrevSeed ^ grayCode;
    unsigned long uBit;
    
    while (_BitScanForward(&uBit, changedBits))
    {
        cout << uBit << endl << changedBits <<endl;
        m_prev[m_uCurDim].uValue ^= cjn[m_uCurDim][uBit];
        changedBits &= ~(1 << uBit);
    }
    
    cout << uBit << endl << changedBits <<endl;

    return 0;
}

Linux

#include <iostream>
#include <x86intrin.h>

using namespace std;

static const unsigned QRNG_NDMS = 32;
    struct
    {
        unsigned long long uValue;
        unsigned uPrevSeed;
    } m_prev[QRNG_NDMS];

unsigned long long cjn[QRNG_NDMS][63] = { 0 };

int main(int, char**) {
    unsigned long mask = 0;
    unsigned long index = 0;
    unsigned char isNonzero;

    unsigned m_uCurSeed = 2048,m_uCurDim;
    m_uCurDim = 0;
    unsigned grayCode = (m_uCurSeed >> 1) ^ m_uCurSeed;
    unsigned changedBits = m_prev[m_uCurDim].uPrevSeed ^ grayCode;
    unsigned long uBit;
    cout << __builtin_ctzl(10) << endl;
    while (true)
    {
        uBit = __builtin_ctzl(changedBits);
        if(uBit >= 64){
            break;
        }
        cout << uBit << endl << changedBits <<endl;
        m_prev[m_uCurDim].uValue ^= cjn[m_uCurDim][uBit];
        changedBits &= ~(1 << uBit);
    }
    
    cout << uBit << endl << changedBits <<endl;
}

C/C++ Linux创建文件夹


描述

系统做linux适配的时候发现不能追迹,最后检查发现不能在对应目录创建相关文件夹导致的。

包含头文件

#include <sys/stat.h>  
#include <sys/types.h>

函数

函数原型:   int mkdir(const char *pathname, mode_t mode);   
函数说明:   mkdir()函数以mode方式创建一个以参数pathname命名的目录,mode定义新创建目录的权限。   
返回值:   若目录创建成功,则返回0;否则返回-1,并将错误记录到全局变量errno中。

mode模式类型:

S_IRWXU 00700权限,代表该文件所有者拥有读,写和执行操作的权限
S_IRUSR(S_IREAD) 00400权限,代表该文件所有者拥有可读的权限
S_IWUSR(S_IWRITE) 00200权限,代表该文件所有者拥有可写的权限
S_IXUSR(S_IEXEC) 00100权限,代表该文件所有者拥有执行的权限
S_IRWXG 00070权限,代表该文件用户组拥有读,写和执行操作的权限
S_IRGRP 00040权限,代表该文件用户组拥有可读的权限
S_IWGRP 00020权限,代表该文件用户组拥有可写的权限
S_IXGRP 00010权限,代表该文件用户组拥有执行的权限
S_IRWXO 00007权限,代表其他用户拥有读,写和执行操作的权限
S_IROTH 00004权限,代表其他用户拥有可读的权限
S_IWOTH 00002权限,代表其他用户拥有可写的权限
S_IXOTH 00001权限,代表其他用户拥有执行的权限

示例结果

屏幕截图 2023-03-29 071402.png


CMake: 使用install-export和find_package查找并链接到库


摘要

一个库生成后然后find_package来引用。下边的示例代码涉及到

dome代码下载

testLib.zip
GIT项目地址

库导出cmake说明

cmake_minimum_required(VERSION 3.5)
project(testLib VERSION 0.1.1 LANGUAGES C CXX)

set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(CMAKE_INSTALL_PREFIX ${CMAKE_BINARY_DIR}/../install)    # 指定安装目录

OPTION(BUILD_MODULE_test "test" OFF)                # 设置编译子模块
if (NOT BUILD_LIBRARY_TYPE)                         # 判定是否配置生成类型下拉项
    set (BUILD_LIBRARY_TYPE "Static" CACHE STRING "${BUILD_LIBRARY_TYPE_DESCR}" FORCE)  # 设置默认类型为静态库
    SET_PROPERTY(CACHE                              # 配置下拉选项
        BUILD_LIBRARY_TYPE PROPERTY STRINGS Shared Static   # 配置生成选择类型下拉项
    )
endif()

if ("${BUILD_LIBRARY_TYPE}" STREQUAL "Shared")
    set (BUILD_SHARED_LIBS ON)                      # 配置生成动态库(OFF/默认为静态库)
endif()

include_directories(include)                        # 添加头文件路径
file(GLOB FILES_SRC "src/*.cpp")                    # 添加当前目录下的源文件至FILES_SRC

add_library(${PROJECT_NAME} ${FILES_SRC})

ADD_CUSTOM_COMMAND(                                 # 用于将自定义构建规则添加到生成的构建系统
    TARGET ${PROJECT_NAME} POST_BUILD
    COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_LIST_DIR}/config $<TARGET_FILE_DIR:${PROJECT_NAME}>/config   # 复制配置目录到可执行目录下
)

############################## 安装部分 ##############################

TARGET_INCLUDE_DIRECTORIES(                         # 目标头文件搜索路径
    ${PROJECT_NAME} PUBLIC                          
    $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>  # 指定构建接口头文件路径, 可以add_subdirectory后直接头文件
    $<INSTALL_INTERFACE:include>                    # install会自动引用include头文件
)

SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES    # 设置目标的属性
    # DEBUG_POSTFIX d                                 # debug声称是添加d后缀
    RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}    # 二进制执行文件目录
    ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}    # 静态库目录
    LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}    # 动态库目录
)

INSTALL(
    TARGETS ${PROJECT_NAME}                         # 安装目标名称
    EXPORT ${PROJECT_NAME}Targets                   # 导出项目名
    PUBLIC_HEADER DESTINATION include               # 指定头文件目录
    RUNTIME DESTINATION "bin/$<$<CONFIG:Release>:Release>$<$<CONFIG:Debug>:Debug>"  # 二进制执行文件目录
    ARCHIVE DESTINATION "lib/$<$<CONFIG:Release>:Release>$<$<CONFIG:Debug>:Debug>"  # 静态库目录
    LIBRARY DESTINATION "lib/$<$<CONFIG:Release>:Release>$<$<CONFIG:Debug>:Debug>"  # 动态库目录
)

INSTALL(
    DIRECTORY                                       # 安装目录
    include DESTINATION ${CMAKE_INSTALL_PREFIX}     # 指定头文件安装目录
)

INSTALL(
    EXPORT ${PROJECT_NAME}Targets                   # 导出项目名
    FILE ${PROJECT_NAME}Targets.cmake               # 生成xxxTargets.cmake文件
    # NAMESPACE Ftest::                               # 添加命名空间
    DESTINATION cmake                               # 指定相对路径cmake目录
)


include (CMakePackageConfigHelpers)
configure_package_config_file (                     # 生成 xxxConfig.cmake文件
    cmake/Config.cmake.in ${PROJECT_NAME}Config.cmake   # 根据.make.in 生成对应Config.cmake文件
    INSTALL_DESTINATION cmake                       # 安装目录
    # PATH_VARS INCLUDE_DIRS LIB_DIR
    # INSTALL_PREFIX ${CMAKE_INSTALL_PREFIX}
)

write_basic_package_version_file(                   # 生成 xxxConfigVersion.cmake文件
    ${PROJECT_NAME}ConfigVersion.cmake              # 指定文件名
    VERSION ${PACKAGE_VERSION}                      # 指定版本号
    COMPATIBILITY SameMajorVersion                  # 指定兼容性
)

INSTALL(
    FILES
    ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake         # 复制xxxConfig.cmake文件到安装目录的cmake
    ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake  # 复制xxxConfigVersion.cmake文件到安装目录的cmake
    DESTINATION cmake                               # 指定相对路径
)

INSTALL(
    DIRECTORY
    config/                                         # 复制配置文件夹
    DESTINATION static                              # 指定目录
)

引入

直接find_package就可以直接将lib和头文件引入。

find_package(testLib REQUIRED)
target_link_libraries(${PROJECT_NAME} testLib::testLib)

使用

#include <iostream>
#include "testLib.h"

using namespace std;

int main(int, char**){
    std::cout << "Hello, from testMain!\n";
    auto pTestLib = make_shared<testLib>();
    pTestLib->say();
}

最终调用成功!
屏幕截图 2023-06-17 090831.jpg


CMake: 文件及文件夹的复制


需求

代码编写过程中写了GTest相关的东西,涉及到了调用三方库的dll及其他相关的东西。这就需要将三方内包含的目录及文件在编译前复制到exe的执行文件目录内。这就需要cmake的add_custom_target命令了。

官方文档:https://cmake.org/cmake/help/v3.22/command/add_custom_target.html?highlight=add_custom

代码

# 归拢需要复制的文件
FILE(GLOB RUNTIME_DEBUG_DLL_FILES CONFIGURE_DEPENDS
    ${ZsOverdrive_CONFIG_PATH}/../../bin/Releasex64/*
)

# 归拢需要复制的文件夹
FILE(GLOB RUNTIME_DEBUG_DLL_DIRS CONFIGURE_DEPENDS
    ${ZsOverdrive_CONFIG_PATH}/../../bin/Releasex64
    ${ZsOverdrive_CONFIG_PATH}/../../driver
)

# 复制相关文件
ADD_CUSTOM_TARGET(CopyRuntimeFiles ALL
    VERBATIM
    COMMAND_EXPAND_LISTS
    # 创建目录
    COMMAND ${CMAKE_COMMAND} -E
        make_directory "${PROJECT_BINARY_DIR}/$<$<CONFIG:Release>:Release>$<$<CONFIG:Debug>:Debug>/"
    # 复制文件
    COMMAND ${CMAKE_COMMAND} -E
        copy_if_different
            "$<$<CONFIG:Release>:${RUNTIME_RELEASE_DLL_FILES}>"
            "$<$<CONFIG:Debug>:${RUNTIME_DEBUG_DLL_FILES}>"
            "${PROJECT_BINARY_DIR}/$<$<CONFIG:Release>:Release>$<$<CONFIG:Debug>:Debug>/"
    # 复制文件夹
    COMMAND ${CMAKE_COMMAND} -E
        copy_directory
            "$<$<CONFIG:Release>:${RUNTIME_DEBUG_DLL_DIRS}>"
            "$<$<CONFIG:Debug>:${RUNTIME_DEBUG_DLL_DIRS}>"
            "${PROJECT_BINARY_DIR}/$<$<CONFIG:Release>:Release>$<$<CONFIG:Debug>:Debug>/"
)

C++: 指针转换


1. 摘要

2. 转换函数

|普通指针|智能指针|说明|
|static_cast|static_pointer_cast|进行上行转换|
|dynamic_cast|dynamic_pointer_cast|进行下行转换|
|const_pointer_cast|const_pointer_cast|一般用于修改底指针|
|reinterpret_cast|reinterpret_pointer_cast|强制类型转换符(慎用)|

3. 示例