在C11 / gnuC11中,可以编写一个宏,该宏分别返回值1或0的整数常量表达式,如果该宏参数是或不是类型名称,或者至少一个宏可以区分整数常量表达式和类型名称(即,如果可以检测到参数不是其中之一,则可以假设是另一个)?
#define IS_TYPENAME(X) /*???*/
_Static_assert( IS_TYPENAME(int), "" );
_Static_assert( !IS_TYPENAME(42), "" );
Run Code Online (Sandbox Code Playgroud)
动机:
我的动机是用_Alignas 包装一个宏,如果建议的对齐方式(类型或整数表达式)小于当前_Alignas对齐方式(正常且对齐方式较小会导致错误),则该宏将不执行任何操作,因此我也想接受类型名称或整数expr,但现在我想简单地要求使用整数expr(您可以始终通过应用来从类型名称中获取整数_Alignof)。
我注意到std::容器往往有public类内类型别名(typedef/ using).例如,请参阅http://en.cppreference.com/w/cpp/container/vector上的"成员类型" .
它们有用吗?他们不是只是一个时代的遗物时,C++没有之类的东西auto和decltype?
实现自定义容器时,是否应该有这样typedef的?如果我没有提供,我会失去什么?
换句话说,静态(=文件范围)全局变量可以从一个下划线开始,而不会产生C实现的名称冲突的可能性吗?
https://www.gnu.org/software/libc/manual/html_node/Reserved-Names.html 表示"...保留名称包括以下划线开头的所有外部标识符(全局函数和变量)('_' )......(强调我的).
我注意到Linux内核启动的功能可能不应该直接用双下划线调用.
我发现这个概念很有用,而且我发现它比识别"私有"标识符_(_)something更容易阅读something_,但我理解(?)双下划线邀请名称与C实现冲突.
全球性,静态性 _variables和_functions安全性?
考虑以下代码示例:
#include <stdio.h>
typedef struct A A;
struct A {
int x;
int y;
};
typedef struct B B;
struct B {
int x;
int y;
int z;
};
int main()
{
B b = {1,2,3};
A *ap = (A*)&b;
*ap = (A){100,200}; //a clear http://port70.net/~nsz/c/c11/n1570.html#6.5p7 violation
ap->x = 10; ap->y = 20; //lvalues of types int and int at the right addrresses, ergo correct ?
printf("%d %d %d\n", b.x, b.y, b.z);
}
Run Code Online (Sandbox Code Playgroud)
我曾经认为像将B*转换为A*并使用A*来操纵B*对象这样的事情是严格的别名违规.但后来我意识到标准真的只需要:
对象的存储值只能由具有以下类型之一的左值表达式访问:1)与对象的有效类型兼容的类型,(...)
和表达式ap->x如果有正确的类型和地址,ap那里的类型应该不重要(或者它是什么?).在我看来,这意味着只要子结构不作为一个整体被操纵,这种类型的重叠继承就是正确的. …
在我的每个主要函数中,我想捕获某些类别的异常并将它们转换为退出代码.
有没有一个更优雅的解决方案,比使用宏来开始和结束每个主要功能,将粘贴try {} catch我想要的隐含?
我能以某种方式实现这一std::set_terminate功能吗?
例:
int main(){
try { //<- insert this
/*
the business logic goes here
*/
//-> and insert this
}
catch(const Someclass1& e){ return 2; }
catch(const Someclass2& e){ return 3; }
//...
catch(...){ return 1; }
}
Run Code Online (Sandbox Code Playgroud) 如果我自己写,我想我会做类似的事情:
template<typename T, typename Dtor = std::default_delete<T> >
class Uptr : private Dtor {
T* vl_;
public:
explicit Uptr(T* vl = nullptr) noexcept : vl_(vl) {}
~Uptr() noexcept { Dtor::operator()(vl_); }
Uptr& swap(Uptr& o) noexcept { T* tmp; tmp = vl_; vl_=o.vl_; o.vl_ = tmp; }
Uptr& operator=(Uptr&& o) noexcept { o.swap(*this); }
Uptr& operator=(nullptr_t) noexcept { vl_=nullptr; return *this; }
Uptr(Uptr&& o) noexcept : Uptr(nullptr) { *this = std::move(o); }
Uptr(const Uptr& o) = delete;
Uptr& operator=(const Uptr& o) …Run Code Online (Sandbox Code Playgroud) C++ 14中的方法可以判断它们是在L值还是R值上调用:
struct A{
A() { puts("Ctor"); }
void m() const & { puts("L-value"); }
void m() const && { puts("R-value"); }
};
int main(){
A a; //Ctor
a.m() //L-value
A().m(); //Ctor; R-value
}
Run Code Online (Sandbox Code Playgroud)
ctor可以告诉它正在构建哪种类型?我可以完全禁用我班级的L值构造吗?
我有一个代理类(实际上是几个),它应该总是转换为其他东西.使用它而不转换是一个错误.我可以在运行时,如检测到错误,加入了bool used_ = 0;会员#ifndef NDEBUG;,并在我的用户指定的强制设置它,然后做assert(used_)代理类的Dtor,但是它会好得多,如果我能得到编译器来防止instatiation L-value的情况下,那个代理首先是:
auto x = Proxy().method1().method2(); // no
Proxy p; // no
Target x = Proxy(); //yes
Target x = Proxy().method1().method2(); //yes
Run Code Online (Sandbox Code Playgroud)
我可以用C++ 14做类似的事吗?
在C++1y,我可以绑定到一个字符串而不是引用类char*或char[]&或类似的?
class LitRf{
const char* data_;
size_t size_;
public:
LitRf(const char* /*?*/ s) : data_{s},size_{sizeof(s)} { /*?*/ }
};
Run Code Online (Sandbox Code Playgroud) 我希望能够将一些字符串、易于提取的键值对与我的 ELF 可执行文件关联起来。
我注意到 gcc 编译的 ELF 有一个.comment部分
$ readelf -p .comment a.out
Run Code Online (Sandbox Code Playgroud)
所以我尝试复制这一点:
主要.c:
#include <stdio.h>
int main(){ puts("Hello world"); return 0; }
const char str[] __attribute__((section(".meta"))) = "hello meta world";
Run Code Online (Sandbox Code Playgroud)
测试:
$ readelf -p .meta a.out
String dump of section '.meta':
[ 0] hello meta world
Run Code Online (Sandbox Code Playgroud)
或者
$ readelf -p .meta a.out | sed -n 's/^[^]]*] //p'
hello meta world
Run Code Online (Sandbox Code Playgroud)
这有效。
是否有更好的方法将此类字符串键值对附加到 ELF 文件(而不将其分解为多个文件)?用户部分是否有一个命名空间(例如.user.meta)可以防止我破坏某些东西?
我以为我可以通过在main中获取变量的地址并向上舍入到页面边界来获得我的进程堆栈的开始(考虑到我的堆栈增长).
我将其与报告的边界进行了比较,/proc/self/maps并且它总是偏离1,2或3页(每页4096字节),从不偏移.差异随每次运行而变化,以下(混乱,非简约)管道中使用的此C程序证明了差异.
stacksz.c:
#include <stdlib.h>
#include <unistd.h>
#include <stdint.h>
#include <stdio.h>
#define CAT "cat /proc/XXXXXXXXXXX/maps"
#define CATP "cat /proc/%ld/maps"
#define MASK ((sizeof(char)<<12)-1)
int main()
{
uintptr_t top = (uintptr_t)&top + MASK & ~MASK;
char cat[sizeof CAT];
sprintf(cat,CATP,(long)getpid());
if(system(cat)) return 1;
printf(" %lx stack\n", top);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
bash管道:
gcc stacksz.c && echo "$(( $(./a.out |grep stack |tr '-' ' ' |cut -d' ' -f2 |sed 's/^/0x/'|tr '\n' -|sed 's/-$//') ))"
Run Code Online (Sandbox Code Playgroud)
我很好奇是否有人能解释这种现象.机器是Linux precision 4.15.0-43-generic #46-Ubuntu SMP x86_64.`(我在1000次运行中获得了以下偏移分布: …