在Section 6.7.3.1 of the C language standardä¸æœ‰å…³restrict
的内容是:
 Â Â
- Â Â
让Dæ˜¯ä¸€ä¸ªæ™®é€šæ ‡è¯†ç¬¦çš„å£°æ˜Žï¼Œè¯¥å£°æ˜Žæ供了一ç§å°†å¯¹è±¡P指定为类型Tçš„å—é™é™å®šæŒ‡é’ˆçš„方法。
- Â Â
...
- Â Â
éšåŽï¼Œå¦‚果(在评估E之å‰æ‰§è¡ŒBçš„æŸä¸ªé¡ºåºç‚¹ä¸Šï¼‰ä¿®æ”¹P使其指å‘数组的副本,则认为指针表达å¼E基于对象På…ˆå‰æŒ‡å‘的对象会更改E的值。
我ä¸æ˜Žç™½è¿™æ˜¯ä»€ä¹ˆæ„æ€-从å—é¢ä¸Šçœ‹ï¼š
有人å¯ä»¥å¸®æˆ‘解释一下这段文å—å—?
(å—this answerå¯å‘)
ç”案 0 :(得分:1)
 Âè°è¯´P指å‘“数组对象的副本â€ï¼Ÿ
æ ¹æ®æ•°ç»„å…ƒç´ çš„æŒ‡é’ˆå®šä¹‰äº†æŒ‡é’ˆç®—æœ¯ï¼ˆåœ¨C 2018 6.5.6 8å’Œ9ä¸ï¼‰ã€‚为æ¤ï¼Œå°†å•ä¸ªå¯¹è±¡è§†ä¸ºä¸€ä¸ªå…ƒç´ çš„æ•°ç»„ã€‚å› æ¤ï¼Œåªè¦æˆ‘们有任何éžç©ºå¯¹è±¡æŒ‡é’ˆï¼Œå°±åœ¨æ¤æ¨¡åž‹ä¸å°†å…¶æŒ‡å‘数组。
 Â为什么P“以å‰â€æŒ‡å‘任何东西?也就是说,è°è¯´æˆ‘们改å˜äº†å®ƒçš„价值?
您引述的文å—是“è¦å¼„清E
是å¦åŸºäºŽP
,让我们å‡è®¾å¤åˆ¶P
所指å‘的数组,然åŽåˆ†é…ç»™{ {1}}指å‘副本ä¸ç›¸åº”ä½ç½®çš„指针。â€å› æ¤ï¼Œæ‚¨å¼•ç”¨çš„文本是说我们æ£åœ¨æ›´æ”¹P
的值,然åŽæˆ‘们将P
的值与æ¤æ›´æ”¹è¿›è¡Œæ¯”较没有它。
 Â让我们å‡è®¾E是局部范围的指针。为什么修改除E指针本身之外的任何指针表达å¼éƒ½ä¼šâ€œæ›´æ”¹E的值â€ï¼Ÿå®ƒå¯èƒ½ä¼šæ›´æ”¹E指å‘的值。对å§ï¼Ÿ
å¯¹è±¡å’Œå€¼æ²¡æœ‰ä½œç”¨åŸŸã€‚æ ‡è¯†ç¬¦å…·æœ‰èŒƒå›´ã€‚ä½†æ˜¯ï¼Œè®©æˆ‘ä»¬è€ƒè™‘ä¸€ä¸ªå…·æœ‰å—èŒƒå›´çš„æ ‡è¯†ç¬¦ï¼š
E
为便于说明,å‡è®¾// P is a pointer into A.
// S is the size of A.
// A is the start of an array not contained in any other array.
void foo(char *P, size_t S, char *A)
{
void *E = P+2;
}
的值为0x1004,而P
为0x1000。 A
是å¦åŸºäºŽE
?好å§ï¼Œé‰´äºŽä»¥ä¸Šæ‰€è¿°ï¼ŒP
为0x1006。å‡è®¾æˆ‘们在定义E
之å‰è€ƒè™‘以下代ç :
E
å‡è®¾ char *N = malloc(S);
memcpy(N, A, S);
P = P - A + N;
返回0x2000。 malloc
的值是什么?它将是0x2006。这与0x1006ä¸åŒã€‚å› æ¤E
是基于E
的。
å¦ä¸€æ–¹é¢ï¼Œè¯·è€ƒè™‘以下问题:
P
现在,void foo(char **P, size_t S, char **A)
{
#if OnOrOff
char *N = malloc(S);
memcpy(N, A, S);
P = P - A + N;
#endif
char **E = P[3];
}
çš„å€¼ä¼šæ ¹æ®E
是true还是false改å˜å—?å¦ï¼Œæ— 论哪ç§æƒ…况,它都将直接或从副本ä¸æŽ¥æ”¶åˆ°OnOrOff
çš„å¼•ç”¨å…ƒç´ çš„å€¼ã€‚ A
å¯èƒ½æŒ‡å‘P
或A
的事实并ä¸å½±å“N
çš„å€¼ã€‚å› æ¤ï¼Œæ¤E
并éžåŸºäºŽE
。
ç”案 1 :(得分:1)
“基于â€çš„å®šä¹‰æ—¨åœ¨å®šä¹‰æŒ‡é’ˆä¹‹é—´çš„ä¼ é€’å…³ç³»ï¼Œä½†æ˜¯å…¶å®žé™…æŽªè¾žå°†äº§ç”Ÿä¸å¯è¡Œçš„定义,æ®æˆ‘所知,该定义与任何实际的编译器行为都ä¸åŒ¹é…。
ä»¥ä¼ é€’æ–¹å¼åº”用以下规则会更简å•ï¼ˆè¿™å°±æ˜¯ç¼–译器似乎è¦åšçš„):如果*p
是类型T*
的指针,则以下指针“基于†{ {1}}:
p
或p+(intExpr)
p-(intExpr)
(otherType*)p
&*p
或&p->structMemberofNonArrayType
&p->unionMemberofNonArrayType
或p->structMemberofArrayType
p->unionMemberofArrayType
我认为&p[intExpr]
çš„æ ‡å‡†ä¸æ˜¯å¾ˆæ˜Žç¡®ï¼Œç¼–译器的编写者也ä¸æ¸…楚。
请注æ„,通过上述任何一ç§è¡¨è¾¾å¼ä»Ž(someType*)someIntegerFunction((uintptr_t)p)
派生的任何q
,除了涉åŠé€šè¿‡p
进行强制转æ¢çš„uintptr_t
和(char*)p
之间的区别将与(char*)q
æŒæœ‰çš„地å€æ— 关。
顺便说一下,这是一个有问题的æžç«¯æƒ…况的示例:
p
使用过渡方法基于å¦ä¸€ä¸ªæ–¹æ³•å½¢æˆæŒ‡é’ˆï¼Œå¦‚æžœint test1(int * restrict p1, int * restrict p2, int n)
{
int *restrict p3 = p1+n;
// How would p4 and p5 be affected if p3 were replaced
// with a pointer to a copy here?
int *p4 = p3;
if (p3 != p1) p4=p1;
int *p5 = p2 + (p3 == p1);
*p3 = 1;
*p5 = 2;
return *p4;
}
为零,则n
显然将基于p4
。但是,指针p3
ä¸ä¼šä»Žp5
æ´¾ç”Ÿï¼Œå› ä¸ºæ²¡æœ‰åºåˆ—å¯ç”¨æ¥æŽ¨å¯¼å…¶å€¼çš„“基于â€æ¥éª¤ã€‚
å°è¯•é€šè¿‡å°†p3
替æ¢ä¸ºæŒ‡å‘数组副本的指针æ¥å°†æ ‡å‡†ä¸çš„规则应用于n==0
ä¸ä¼šå½±å“p3
的值,但会影å“p4
的值。这æ„味ç€p5
ä¸æ˜¯åŸºäºŽp4
的,而是p3
是基于的。
æˆ‘è®¤ä¸ºè¿™æ ·çš„ç»“æžœæ˜¯è’è°¬çš„ï¼Œæˆ‘è®¤ä¸ºæ ‡å‡†çš„ä½œè€…ä¹Ÿä¼šè¿™æ ·åšï¼Œä½†æ˜¯å®ƒéµå¾ªäº†æ ‡å‡†ä¸æŽªè¾žæ˜Žç¡®çš„规则。
ç”案 2 :(得分:0)
åœ¨é˜…è¯»äº†å‡ æ¡è¯„论以åŠ@EricPostpischilçš„ç”案之åŽï¼Œæˆ‘å°è¯•ç»¼åˆäº†ä¸€äº›æˆ‘认为更清晰(虽然更长一点)的内容,以é˜æ˜Žæƒ…况并回ç”所æ出的问题。
原始文本:
 Â接下æ¥ï¼Œå¦‚果(在评估E之å‰æ‰§è¡ŒBçš„æŸä¸ªé¡ºåºç‚¹å¤„)修改P使其指å‘数组对象的副本,则指针表达å¼Eå¯ä»¥åŸºäºŽå¯¹è±¡P。它以å‰æŒ‡å‡ºä¼šæ”¹å˜E的值。
澄清的文å—:
 Â接下æ¥ï¼Œå¦‚果在评估E之å‰æ›´æ”¹P(具有æŸäº›é™åˆ¶ï¼‰ä¼šä½¿E评估为其他值,则认为指针表达å¼E基于对象P。é™åˆ¶æ˜¯ï¼š
   Â Â
- 节制性é™åˆ¶ï¼šå¯¹P的修改必须在sequence point处进行。
 Â- Påªèƒ½ä¿®æ”¹ä¸ºæŒ‡å‘原始指å‘的相åŒå‰¯æœ¬ã€‚
 Â
(而且,由于通常,我们å¯ä»¥æƒ³åˆ°æ€»æ˜¯æŒ‡å‘数组对象的指针-Påªèƒ½è®¾ç½®ä¸ºæŒ‡å‘该数组对象的副本)。
ç”案 3 :(得分:0)
第3点å¯ä»¥ç”¨ä»£ç 大致表示:
#define E(P) ( (P) + 1 ) // put the expression you want to test here
extern T obj; // T is some type
T copy = obj;
if ( E(&obj) != E(©) )
printf("the expression in the macro is based on P")
æ ‡å‡†ä¸ä½¿ç”¨çš„å½¢å¼è¯è¨€å®šä¹‰å…许E
是ä¸ç¡®å®šçš„和其他病ç†æƒ…况(例如(P) + rand() % 5
),而我的示例则没有。
æ ‡å‡†ç‰ˆæœ¬æ˜¯æˆ‘ä»¬åœ¨ç›¸åŒçš„上下文ä¸æ¯”较E(&obj)
的结果和E(©)
的结果。