标题说明了一切.我很好奇为什么restrict关键字不是C++的一部分?我对C++知之甚少,而且我仍然无法在网上找到任何阻止这种情况的理由.有没有人知道会发生什么可怕的事情,如果C++标准会像C一样使用这个关键字?它根本不需要吗?
更多解释:这不是关于使用它,也许在我的一生中我不会从这个关键字中获益.这个问题只是关于好奇心,因为自C99以来,限制是C的一部分,即15年.
阅读本文:我对技术原因感兴趣,而不是像"他们只是不喜欢,它不够酷"这样的意见
restrictC++中缺少C中的关键字,所以出于兴趣,我一直在寻找一种在C++中模拟相同功能的方法.
具体来说,我希望以下内容相同:
// C
void func(S *restrict a, S *restrict b)
// C++
void func(noalias<S, 1> a, noalias<S, 2> b)
Run Code Online (Sandbox Code Playgroud)
哪里 noalias<T, n>
T*用->和访问时一样*T*(这样函数可以被称为func(t1, t2),where t1和t2are都是类型T*)n指定变量的"混叠类",使类型的变量noalias<T, n>和noalias<T, m>可从未假定为别名对于n!=米.这是我的严重缺陷解决方案:
template <typename T, int n>
class noalias
{
struct T2 : T {};
T *t;
public:
noalias(T *t_) : t(t_) {}
T2 *operator->() const {return static_cast<T2*>(t);} …Run Code Online (Sandbox Code Playgroud) 首先是一些参考.在C99标准说,这大约restrict在第6.7.3:
通过限制限定指针访问的对象与该指针具有特殊关联.此关联在下面的6.7.3.1中定义,要求对该对象的所有访问都直接或间接使用该特定指针的值.117)
restrict限定符(如register存储类)的预期用途是促进优化,并且从构成符合程序的所有预处理转换单元中删除限定符的所有实例不会改变其含义(即,可观察行为).
然后(§6.7.3.1"正式定义restrict"):
让
D是提供指定的对象的装置的一个普通标识符的声明P作为限制限定指针输入T.如果
D出现在块内并且没有存储类extern,则B表示该块.如果D出现在函数定义的参数声明列表中,则B表示关联的块.否则,让我们B表示main块(或在独立环境中在程序启动时调用的任何函数块).在下文中,指针表达式
E被称为基于对象Pif(在B评估之前的执行中的某个序列点E)修改P为指向其先前指向的数组对象的副本将改变其值E.119)注意''based''仅针对具有指针类型的表达式定义.在每次执行期间
B,L设为任何&L基于的 左值P.如果L用于访问X它指定的对象的值,并且X也被修改(通过任何方式),则以下要求适用:T不应该是const限定的.用于访问值的每个其他左值X也应该具有基于的地址P.出于本子条款的目的,每次修改的访问也X应被视为修改P.如果P …
以下代码是否定义良好?
#include <stdio.h>
int ScanFirstOrSecond(const char *s, int *dest) {
return sscanf(s, "%d%d", dest, dest);
}
int main(void) {
int x = 4;
ScanFirstOrSecond("5", &x);
printf("%d\n", x); // prints 5
// Here is the tricky bit
ScanFirstOrSecond("6 7", &x);
printf("%d\n", x); // prints 7
return 0;
}
Run Code Online (Sandbox Code Playgroud)
换句话说,这些...论点是否暗示restrict了它们?
我发现最适用的C规范是
fscanf函数依次执行格式的每个指令.......C11dr§7.21.6.24
gcc 5和clang 3.6都不会在restrict限定符的约束被违反的情况下发出警告,即使在调用时也是如此-Wall.请考虑以下代码片段:
extern void f(char *restrict p, char *restrict q);
void g(char *p)
{
f(p, p);
}
Run Code Online (Sandbox Code Playgroud)
天真地,我希望可以静态地确定违规行为,我期待这-Wall会发出警告.我在某个地方错过了一面旗帜,还是在发出一些我没有看到警告的问题?
有没有办法告诉C99编译器我要访问给定数组的唯一方法是使用myarray [index]?说这样的话:
int heavy_calcualtions(float* restrict range1, float* restrict range2)
{
float __I promise I won't alias this__ tmpvalues[1000] = {0};
....
heavy calculations using range1, range2 and tmpvalues;
....
}
Run Code Online (Sandbox Code Playgroud)
通过使用restrict我承诺我不会为range1和range2设置别名但是我如何为我的函数内部声明的数组做同样的事情?
我在Windows平台上使用GoDaddy Web托管计划.这不是我的选择 - 它与使用ASP.NET的实际站点的不同部分有关(也不是我的选择).
我有一个SQL数据库,其中包含一些带有一些非敏感客户信息的条目.这个主键是一个AutoIncrement整数,我有一系列与这些整数相匹配的PDF文件(例如555.pdf,7891.pdf等).
我的目标是限制对这些文件的直接访问,我希望用户必须首先完成搜索和登录过程(PHP).最初我打算把文件放在PUBLIC_HTML文件夹上面,但GoDaddy拒绝在没有专用服务器的情况下给我root访问权限(每月20美元).
我接下来要研究的是HTACCESS.我打算仅通过允许访问服务器的IP地址(或localhost/127.0.0.1)来限制只能访问PHP脚本的文件.不幸的是,这不起作用,因为GoDaddy不在其Windows服务器上运行Apache.
我可以将文件放入数据库中的BLOB中,但是当我需要快速处理它们时,这会变得非常混乱(加上我对这种方法有些麻烦).
是否有任何限制只能访问PHP脚本(readfile())的建议?
我正在尝试排除以下设备品牌/型号,因为它与我的应用程序不兼容:
Brand: Trend
Model: TaintArt for x86
Run Code Online (Sandbox Code Playgroud)
但是,尽管此设备不断出现在我的 Crashlytics 报告中,但我在设备目录中找不到它,因此我无法排除/限制它。
导航到设备目录:
1. Login to Google Play Console
2. Select app
3. Release Management
4. Device Catalog
5. Search for Device (Trend, Taintart, etc.)
6. Result: 0 match your criteria
Run Code Online (Sandbox Code Playgroud)
有没有其他方法可以排除这个品牌/型号?
编辑(2020 年 3 月 27 日):与“Batmobile Defy Mini”相同的问题,由于 android.content.res.Resources$NotFoundException 在充气类时引起的奇怪错误,它总是崩溃。
这将是一个长期的语言律师问题,所以我想快速说明为什么我发现它是相关的.我正在开展一个严格的标准合规性至关重要的项目(编写一种编译成C的语言).我要提供的示例似乎是clang部分的标准违规,因此,如果是这种情况,我想确认一下.
gcc说,带有指向限定限定指针的指针的条件不能与带有void指针的条件语句共存.另一方面,clang编译好的东西.这是一个示例程序:
#include <stdlib.h>
int main(void){
int* restrict* A = malloc(8);
A ? A : malloc(8);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
对于GCC,选项-std=c11和-pedantic可包括或不以任何组合,同样地对于铛和选项-std=c11和-Weverything.在任何情况下,clang编译没有错误,gcc给出以下内容:
tem-2.c: In function ‘main’:
tem-2.c:7:2: error: invalid use of ‘restrict’
A ? A : malloc(8);
^
Run Code Online (Sandbox Code Playgroud)
关于条件陈述,c11标准说明如下,强调增加:
6.5.15条件运算符
...
- 下列之一应适用于第二和第三操作数:
- 两个操作数都有算术类型;
- 两个操作数具有相同的结构或联合类型;
- 两个操作数都有空洞类型;
- 两个操作数都是兼容类型的限定或非限定版本的指针;
- 一个操作数是指针,另一个是空指针常量; 要么
- 一个操作数是指向对象类型的指针,另一个是指向合格或非限定版本的void的指针.
...
- 如果第二个和第三个操作数都是指针,或者一个是空指针常量而另一个是指针,则结果类型是指向使用两个操作数引用的类型的所有类型限定符限定的类型的指针.此外,如果两个操作数都是兼容类型的指针或兼容类型的不同限定版本,则结果类型是指向复合类型的适当限定版本的指针; 如果一个操作数是空指针常量,则结果具有另一个操作数的类型; 否则,一个操作数是指向void的指针或void的限定版本,在这种情况下,结果类型是指向适当限定版本的void的指针.
...
我看到它的方式,上面的第一个粗体部分表示两种类型可以一起使用,第二个粗体部分将结果定义为指向限制限定版本的void的指针.但是,如下所示,此类型不能存在,因此表达式被gcc正确识别为错误:
6.7.3类型限定词,第2段
引用类型为对象类型的指针类型以外的类型不应受限制.
现在,问题是这个示例程序违反了"不应该"的条件,因此需要通过以下方式产生错误:
5.1.1.3诊断,第1段
如果预处理转换单元或转换单元包含违反任何语法规则或约束的情况,则符合要求的实现应生成至少一条诊断消息(以实现定义的方式标识),即使该行为也明确指定为未定义或实现 - 定义.在其他情况下不需要产生诊断消息.
通过静默处理错误类型,似乎clang不符合标准.这让我想知道铿锵有什么其他的默默无闻.
我在x86-64 Ubuntu机器上使用gcc版本5.4.0和clang版本3.8.0.
我刚碰巧看了printf(和其他fprintf类函数)的原型-
int printf(const char * restrict format, ...);
Run Code Online (Sandbox Code Playgroud)
restrict如果我理解正确的关键字,如果标记了其中一个,则禁止通过两个指针访问同一个对象restrict.
这里引用了与C标准相同的例子.
restrict我认为标记格式的一个好处是保存函数,使其不会在执行期间修改格式字符串(比如因为%n格式说明符).
但这是否会产生更大的约束?这会使以下函数调用无效吗?
char format[] = "%s";
printf(format, format);
Run Code Online (Sandbox Code Playgroud)
因为这里有明显的别名.为什么将restrict关键字添加到format参数中printf?