添加解引用指针时的操作顺序

Order of operations when adding dereferenced pointers

我在 c 中给出了这些代码行,并要求我解释其输出:

char  str [50] = "hello [=10=] worl\bd";
printf("\n %s ",str);
printf("%s \n",str+str[4]-*str);

输出:

 hello   word

根据我的理解,第二行打印字符串,直到 '\0' 字符表示结束。 第三个代码然后添加字符串的其余部分(从 space 开始 'w' 跳过 'l' 因为它被后面的 space.

覆盖

我不明白的是表达式中到底发生了什么:

str+str[4]-*str

表达式不是这样执行的吗:

  1. 添加指向char数组第一个元素的指针:str+str
  2. 将结果指针增加 4 并取消引用它(return 应该是一个字符?)
  3. 从2.?
  4. 的字符中减去*char returns的字符

看来情况并非如此。有人可以向我解释这里究竟发生了什么吗? 非常感谢!

str[4]='o' // 111 in ascii
*str='h'   // 104 in ascii

str+str[4]-*str= str+111-104=&str[7] => ' worl\bd'

给定

char  str [50] = "hello [=10=] worl\bd";

代码

str+str[4]-*str

评估为

str + 'o' - 'h'

因为str[4]是字符'o'*str是字符'h'.

注意一个指针加上(或减去)一个整型值的结果是另一个指针值。

但是我们不知道'o''h'是什么,因为问题没有指定字符集。

如果我们假设字符集是ASCII,那么字符'o'就是整数值111,而'h'的整数值是104 , 所以值为

str + 111 - 104

(但请参阅@dbush 的 ,因为 str + 111 - 104 被评估为 ( str + 111 ) - 104 并且 str + 111 调用未定义的行为,因为它已经超过了 str数组)

str + 7

所以是str中第七个字符的地址 - &str[7]:

printf("\n %s ",str);

会发射

"\n hello "

不带引号(引号用于显示结尾的 space),并且

printf("%s \n",str+str[4]-*str);

printf( "%s \n" str + 7 );

并将发射

" worl\bd \n"

同样没有引号。但是 '\b' 是后面的 space 字符,所以您可能会看到

" word \n"

打印在您的屏幕上 - 可能。

但是问题中的一些假设阻止了任何人明确说明将输出什么:

  • 字符集可能不是 ASCII,在这种情况下程序可能会调用未定义的行为
  • 显示媒体可能无法按预期处理后退space字符

没有这些信息,无法回答问题。

C 中的精度很重要。像这样的问题,如果没有精确指定能够回答问题所需的条件和环境,那就太糟糕了,而且考虑不周。

在这个表达式中:

str+str[4]-*str

数组下标运算符[]的优先级最高,其次是解引用运算符*,其次是+-,它们具有相同的优先级和分组左到右。所以上面是一样的:

(str+(str[4]))-(*str)

所以发生的事情是数组 str 被转换为指向其第一个元素的指针,然后 str[4] 的字符代码被添加到该指针,然后 [= 的字符代码从中减去 21=](或等效的 str[0])。

代入问题字符,上同:

(str + 'o') - 'h'

其中,假定 ASCII 编码,与以下内容相同:

(str + 111) - 104

但是现在我们遇到了问题。

子表达式 str + 111 创建了一个远远超过数组末尾的指针,这样做会调用 undefined behavior,因此您的程序格式不正确。下一个操作似乎给你一个有效的指针并不重要。只是 创建 指针值 str + 111 无效。

这在 C standard 关于指针 addition/subtraction 的第 6.5.6p8 节中有描述:

When an expression that has integer type is added to or subtracted from a pointer, the result has the type of the pointer operand. If the pointer operand points to an element o fan array object, and the array is large enough, the result points to an element offset from the original element such that the difference of the subscripts of the resulting and original array elements equals the integer expression. ... If both the pointer operand and the result point to elements of the same array object, or one past the last element of the array object, the evaluation shall not produce an overflow; otherwise, the behavior is undefined.

所以您很“幸运”,程序生成的输出乍看之下似乎符合预期。

如果是这样写的:

str+(str[4]-*str)

程序的格式会很好。