C指针:数组变量

hqt*_*hqt 3 c arrays pointers

我在书中看到了这一点(以及互联网上的许多消息来源):

数组变量指向数组中的第一个元素.

如果这是真的,那么数组变量和第一个元素是不同的.对?

它意味着通过以下代码,它将产生两个不同的结果:

int main(){
    char msg[] = "stack over flow";
    printf("the store string is store at :%p\n",&msg);
    printf("First element: %p\n",&msg[0]);
}
Run Code Online (Sandbox Code Playgroud)

但是我对这两个案例得到的结果相同.所以,通过这个例子,我认为我们应该说:数组变量第一个元素.(因为它有相同的地址)

我不知道这是真还是错.请教我.

Dan*_*her 8

数组变量表示数组占用的整个内存块,而不仅仅是数组的第一个元素.所以array一样的array[0](参见sizeof array / sizeof array[0]).但是数组的第一个元素与数组本身位于相同的内存地址.

假设数组指向第一个元素也是不正确的,在大多数情况下,数组表达式衰变成指向其第一个元素的指针,但它们是不同的东西(sizeof例如,参见cf ).

  • 这就像说你的手和拇指从太空中的同一点开始.一个是手指阵列就是全部 (3认同)
  • @hqt尺寸不同.数组`msg`占用16个字节,其第一个元素仅占用这些字节中的第一个.这就像结构的第一个成员的地址与结构的地址相同,但它们是不同的东西.如果你有一个x字节的实体A位于某个地址,而一个实体B的y字节位于同一个地址,则A和B是不同的实体,如果`x!= y`.(即使`x == y`,它们也可以是不同的实体.) (2认同)

cni*_*tar 5

它们指向相同的地址,printf即将显示相同的值但它们具有不同的类型.

  • &msgis 的类型是char(*)[16]指向char数组16的指针
  • &msg[0]is 的类型是char *指向char的指针

一种廉价的测试方法是做一些指针算法.尝试打印&msg + 1.

这个C FAQ可能有用.


Sha*_*baz 5

数组变量整个数组.它变成指向数组第一个元素的指针.

如果你看看类型:

  • msg 是类型的 char [16]
  • &msg 是类型的 char (*)[16]
  • &msg[0] 是类型的 char *

因此,在msg可以衰减为数组的上下文中,例如当作为参数传递时,其值将等于&msg[0].

让我画出这个:

+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+--+
|s|t|a|c|k| |o|v|e|r| |f|l|o|w|\0|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+--+
Run Code Online (Sandbox Code Playgroud)

想象一下这个数组的起点,其中's'的位置是地址0x12345678.

  • msg本身,指的是整个16字节的内存.就像你说的那样int a;,a指的是4字节的内存.
  • msg[0] 是16个字节的第一个字节.
  • &msg 是数组开始的地址: 0x12345678
  • &msg[0] 是数组的第一个元素的地址: 0x12345678

这就是为什么值&msg&msg[0]它们相同,但它们的类型不同.

现在的问题是,msg它本身并不是一流的公民.例如,您无法分配数组.这就是为什么在大多数情况下,数组会衰减成指针.

如果你知道函数指针,这非常相似:

int array[10];
int function(int);
Run Code Online (Sandbox Code Playgroud)
  • int *var = array,array衰减指针(&array)
  • void *var = function,function衰减指针(&function)

注意,在函数指针的情况下,我们喜欢保留类型,所以我们写:

int (*var)(int) = function;
Run Code Online (Sandbox Code Playgroud)

同样,您可以使用数组:

int (*var)[10] = array;
Run Code Online (Sandbox Code Playgroud)