为什么在C中不允许这个指针算术?

Jin*_*Jin 39 c arrays pointers

char arr[] = "Hello";
arr = arr + 1;  // error occurs
Run Code Online (Sandbox Code Playgroud)

据我所知,具有数组类型的表达式将转换为指向数组初始元素的指针类型.因此,我期望arr = arr + 1(指向数组的第一个元素(arr)的指针成为指向数组的第二个元素的指针).为什么这不适用于C?

AnT*_*AnT 55

arr + 1确实是指向数组的第二个元素的指针(即&arr[1]).

但是,这并不意味着您可以以某种方式将指针值写回arr.至少有两个原因你不能这样做.

首先,arr是一个阵列char元件,而不是一个指针.这里有明显的类型不匹配.

其次,作为一个数组,arr一个不可修改的左值.你不能改变arr自己,你只能改变它的元素(这种区别有点难以掌握,但它就在那里).

最后,如果我们忽略更深层次的复杂性并关注顶层正式发生的事情,由于数组类型衰减,你的表达式相当于

(char *) arr = (char *) arr + 1;
Run Code Online (Sandbox Code Playgroud)

分配是不可能的,因为左侧是[隐式]类型转换的结果.在C类型转换中,始终生成rvalues.您无法分配到右值.

换句话说,它不是这里不允许的"指针算术".指针算术很好.这是你用导致错误的指针算法的结果.

  • @AbdulGafoor:最好不要,因为在C的上下文中说"常量数组变量"听起来就像你的意思是它是一个`const char [6]`,而实际上它是一个`char [6]`.这不是数组的常量,而是任何类型的数组变量都不能分配给它. (3认同)
  • @AbdulGafoor你可以说'arr`是一个"不可修改的l值".获得你想要的效果的唯一方法是例如`char arr [] ="Hello"; char*ptr = arr; ptr = ptr + 1;`和`ptr`一起工作. (2认同)

hac*_*cks 23

数组是不可修改的左值.它们不能是赋值运算符的左操作数.

C11-§6.3.2.1:

修改的左值是不具有阵列型左值,不具有不完整的类型,[...]

§6.5.16/ 2:

赋值运算符应具有可修改的左值作为其左操作数.

在声明中

arr = arr + 1; 
Run Code Online (Sandbox Code Playgroud)

arr是运算=符的左操作数,是数组类型.它无法修改.
因此,它不是指针算术,而是由赋值运算符上的语言约束,这是语法错误的原因.


请注意,在某些上下文中,数组会衰减为指向其第一个元素的指针,尽管指针和数组是不同的类型.数组不是指针.它只是指针算术和数组索引是等价的.例如

char *ptr = &arr[0] + 1 => &(*(arr + 0)) + 1 => &(*arr) + 1 => arr + 1 // * and & nullify each other 
Run Code Online (Sandbox Code Playgroud)

  • 您甚至可以将其称为"数组索引*语法*":它将数组衰减为指针,然后对其进行索引. (3认同)

Nat*_*ina 10

这是因为数组与指针类似,只是它们无法修改.但是,您可以修改指向数组的指针.对于上面的示例,您可以这样做:

char arr[]="Hello";
char *ptr=arr;
ptr=ptr+1;
Run Code Online (Sandbox Code Playgroud)

最初,指针ptr将指向数组的第一个字符,即'H'在修改值之后,它将指向第二个字符即'e'.您还可以执行以下操作:

char arr[]="Hello";
char *ptr=arr;
ptr=arr+1;
Run Code Online (Sandbox Code Playgroud)

两者都产生相同的效果,表明它arr+1确实是指针算术.但是,您无法修改其值,arr因为其类型是字符数组的类型而不是指向字符数组的指针.


R S*_*ahu 8

据我所知,具有数组类型的表达式将转换为指向数组的初始元素的指针类型.

在大多数情况下都是如此.在以下情况下并非如此:

  1. 使用addressof运算符(&arr)时.类型&arrchar (*)[6].事实并非如此char**.

  2. 使用sizeof运营商时.sizeof(arr)6.如果它是一个指针,它将是指针的大小(在大多数常见平台中为4或8).

  3. 用作赋值运算符的LHS时.数组类型的变量不可修改.

因此,我期望arr = arr + 1(指向数组的第一个元素(arr)的指针成为指向数组的第二个元素的指针).为什么这不适用于C?

表达式的RHS求值为指向第二个元素的指针arr.但是,由于上述(3),该行不起作用.arr不是可修改的值.它不能用作赋值运算符的LHS.