当询问C中常见的未定义行为时,灵魂比我提到的严格别名规则更加开明.
他们在说什么?
我总是不确定,在C++中,restrict关键字是什么意思?
是否意味着赋予函数的两个或更多指针不重叠?还有什么意思?
我是linux系统编程的新手,在阅读Linux系统编程时遇到了API和ABI .
API的定义:
API定义了一个软件在源级别与另一个软件通信的接口.
ABI的定义:
API定义源接口,而ABI定义特定体系结构上两个或多个软件之间的低级二进制接口.它定义了应用程序如何与自身交互,应用程序如何与内核交互以及应用程序如何与库交互.
程序如何在源级别进行通信?什么是源级别?它无论如何都与源代码有关?或者库的源代码包含在主程序中?
我所知道的唯一区别是API主要由程序员使用,而ABI主要由编译器使用.
memcpy如下所示使用它是否更好,或者std::copy()在性能方面更好用?为什么?
char *bits = NULL;
...
bits = new (std::nothrow) char[((int *) copyMe->bits)[0]];
if (bits == NULL)
{
cout << "ERROR Not enough memory.\n";
exit(1);
}
memcpy (bits, copyMe->bits, ((int *) copyMe->bits)[0]);
Run Code Online (Sandbox Code Playgroud) 有没有人见过任何关于restrictgcc/g ++实际使用C/C++ 关键字的数字/分析是否能在现实中提供任何显着的性能提升(而不仅仅是在理论上)?
我已经阅读了各种推荐/贬低其使用的文章,但我没有碰到任何实际数字,实际上证明了任何一方的论点.
编辑
我知道这restrict不是C++的正式部分,但它得到了一些编译器的支持,我读过Christer Ericson的一篇论文,强烈推荐使用它.
int pthread_create(pthread_t *restrict thread,
const pthread_attr_t *restrict attr,
void *(*start_routine)(void*), void *restrict arg);
Run Code Online (Sandbox Code Playgroud)
我想知道限制的含义是什么?
我restrict对此有一个大致的了解,但我希望澄清一些细节.我有一个函数从一个缓冲区读取一个以null结尾的字符串,并在另一个缓冲区中写出一个URL编码的版本.该函数具有此签名(当前没有restrict):
char const *StringUrlEncode(char const *unencoded,
char *encoded,
char *encodedEnd);
Run Code Online (Sandbox Code Playgroud)
unencoded是我的以null结尾的源字符串.目标缓冲区由encoded和表示encodedEnd,其中encoded指向char缓冲区encodedEnd中的第一个并指向缓冲区后的第一个字符,即函数将写入char但不包括指向的位置encodedEnd- 这是您的基本begin/ end迭代器如果您熟悉C++ STL约定,请配对.
如果我添加restrict到此函数,它应该只应用于前两个参数:
char const *StringUrlEncode(char const *restrict unencoded,
char *restrict encoded,
char *encodedEnd);
Run Code Online (Sandbox Code Playgroud)
或者通过将它添加到所有三个参数中我是否有一些好处?
我可以看到制作输入和输出缓冲区restrict有助于编译器知道它们不重叠.但是由于最后一个参数,encodedEnd仅用于标记输出缓冲区的结尾,我认为这restrict对编译器没有任何帮助(虽然我认为它不会受到伤害,除了添加不必要的噪声到函数声明).
该restrict关键字的行为在C99定义由6.7.3.1:
设D是普通标识符的声明,它提供了一种将对象P指定为类型T的限制限定指针的方法.
如果D出现在块内并且没有存储类extern,则让B表示该块.如果D出现在函数定义的参数声明列表中,则让B表示关联的块.否则,让B表示主块(或在独立环境中在程序启动时调用的任何函数块).
在下文中,指针表达式E被称为基于对象P if(在评估E之前执行B中的某个序列点)修改P以指向其先前指向的数组对象的副本将改变E.119的值)注意''based''仅为具有指针类型的表达式定义.
在每次执行B期间,让L为具有基于P的&L的任何左值.如果L用于访问它指定的对象X的值,并且X也被修改(通过任何方式),则以下要求适用:T不应该是const限定的.用于访问X值的每个其他左值也应具有基于P的地址.出于本子条款的目的,每次修改X的访问也应被视为修改P. 如果为P分配了指针表达式E的值,该指针表达式E基于与块B2相关联的另一个受限指针对象P2,则B2的执行应在执行B之前开始,或者B2的执行应在该执行之前结束.分配.如果不满足这些要求,则行为未定义.
就像其他人一样,我很难理解这个定义的所有复杂性.作为这个问题的答案,我希望看到第4段中每个要求违反要求的一些好例子.本文:
在"编译器可能假设......"方面做得很好.扩展该模式并将编译器可以做出的假设以及它们如何无法保持,每个示例都很棒.
如果我做
typedef void Cb();
int foo(int const& a, Cb cb) {
int x = a;
cb();
return x - a;
}
Run Code Online (Sandbox Code Playgroud)
并编译g++ -O3 -save-temps -c foo.cpp,我看到减法被保留,而如果cb();被注释掉,整个函数优化为
xorl %eax, %eax
Run Code Online (Sandbox Code Playgroud)
我可以对参数的规范做些什么,a这样无论调用是什么,都可以优化减法cb(),并且不会强制a成为唯一的引用(即,它可能被引用到其他地方,但是没有那些引用会被修改)?
我想编写一个函数,输入一个数据数组并使用指针输出另一个数据数组。
我想知道如果两者都指向同一个地址会产生什么结果src,dst因为我知道编译器可以针对 const 进行优化。这是未定义的行为吗?(我标记了 C 和 C++,因为我不确定它们之间的答案是否不同,我想了解两者。)
void f(const char *src, char *dst) {
dst[2] = src[0];
dst[1] = src[1];
dst[0] = src[2];
}
int main() {
char s[] = "123";
f(s,s);
printf("%s\n", s);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
除了上面的问题,如果我删除const原来的代码,这个定义是否明确?
c ×6
c++ ×5
c99 ×2
optimization ×2
abi ×1
api ×1
c++11 ×1
constants ×1
g++ ×1
gcc ×1
linux ×1
performance ×1
pointers ×1
reference ×1
type-punning ×1
ubuntu-10.04 ×1