字符串文字和数组的地址

San*_*rma 1 c arrays string pointers string-literals

    int main(){
        char *str1="Hi", *str2 = "Bye";
        printf("%u,%u\n",&str1,str1);
        int arr[5]={1,2,3,4,5};
        printf("%u,%u",arr,&arr);
    }
Run Code Online (Sandbox Code Playgroud)

这里发生了什么?str&str给出不同的地址,arr&arr给出相同的地址。

我的理解是arr指向第一个元素的地址,即&arr[0]&arr也会给出相同的地址,但它是整个地址arr[5]。如果我们增加&arr1,那么它将指向 arr[4] 的下一个元素。但问题是为什么这个过程在字符串的情况下是不同的。请帮我在这里形象化这个概念。

Som*_*ude 6

在 C 中,所有字符串文字实际上都存储为(只读)字符数组,包括空终止符。与任何其他数组一样,它们衰减为指向其第一个元素的指针。

因为str1在您的代码中,编译器生成了一些与此类似的代码:

// Compiler-generated array for the string
char global_array_for_Hi[] = { 'H', 'i', '\0' };

int main(void)
{
    char *str1 = global_array_for_Hi;
    ...
}
Run Code Online (Sandbox Code Playgroud)

您的指针变量str1指向'H'此数组的第一个元素 (the )。当您打印该值时str1,您将获得该值。

当你打印你的值时,&str1你会得到变量str1本身的位置,你会得到一个指向str1类型的指针char **

从某种意义上说,它可以被看作是

+-------+ +------+ +-----+-----+------+
| &str1 | --> | STR1 | --> | 'H' | '我' | '\0' |
+-------+ +------+ +-----+-----+------+

对于arr您有一个数组,它会衰减为指向其第一个元素的指针。当您使用arr它时,它与&arr[0](它来自arr[i]完全等于的事实*(arr + i))相同。arr(和&arr[0])的类型是int *

当你使用时,&arr你会得到一个指向整个数组的指针,它的类型是int (*)[5].

该位置是相同的两个&arr[0]&arr,但它们的类型有很大的不同。


在相关说明中,printf格式说明符%u用于打印类型的值unsigned int。要打印指针(更具体地说是 type 的值void *),您必须使用格式说明符%p。格式说明符和参数类型不匹配会导致未定义的行为