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] 的下一个元素。但问题是为什么这个过程在字符串的情况下是不同的。请帮我在这里形象化这个概念。
在 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。格式说明符和参数类型不匹配会导致未定义的行为。