C语言 我做了一个指针数组.名字和名字有什么区别[0]?



https://i.stack.imgur.com/7Fgkp.jpg输出)这是输出图像的链接

my code ---->

#include <stdio.h>

const int MAX = 5;

int main () {
char *names[] = {
"Zara Ali",
"Hina Ali",
"Nuha Ali",
"Sara Ali",
"Zara Ali"
};

int i = 0;
for ( i = 0; i < MAX; i++) {
printf("Value of *names[%d] = %c charn", i, *names[i] );
}

for ( i = 0; i < MAX; i++) {
printf("Value of *(names+%d) = %dn", i, *(names+i) );
}
for ( i = 0; i < MAX; i++) {
printf("Value of names[%d] = %dn", i, names[i] );
}
for ( i = 0; i < MAX; i++) {
printf("Value of *(names+%d) = %sn", i, *(names+i) );
}
for ( i = 0; i < MAX; i++) {
printf("Value of names[%d] = %sn", i, names[i] );
}



printf("Value of names = %dn",names );
printf("Value of names+1 = %dn",names+1 );
return 0;
}

时,namesnames[0]的值不相同。我在哪里可以正确地学习这个主题。问题是"我不知道……"哪个变量存储了哪个地址或值

首先,下面一行是错误的:

printf("Value of names = %dn",names );

使用%d格式说明符不是打印指针的正确方式。虽然它可以在大多数32位平台上工作(指针的大小通常为4),但它肯定不能在64位平台上正常工作(指针的大小通常为8)。

打印指针的正确方法是使用%p格式说明符并将指针强制转换为void*:

printf( "Value of names = %pn", (void*)names );

在大多数平台上,没有必要强制转换为void*,因此您可以安全地忽略它(即使ISO C正式要求强制转换)。

正如在评论部分已经指出的那样,根据定义,编写names[i]等同于编写*(names+i)

namesnames+1之间的差异是8的原因是因为在两个表达式中,数组names衰减为指向其第一个元素的指针,即指向&names[0]。给一个指针增加1不会使地址增加1,而是使它指向下一个元素。由于数组names的每个元素都是一个指针,并且在您的平台上似乎具有8的大小(您似乎在具有64位指针的64位平台上),因此当您将指针增加1时,地址将增加8

在你的图片中,你似乎也在问为什么*(names+0)*(names+1)之间的差异是9。表达式*(names+0)相当于names[0],后者是指向字符串字面值"Zara Ali"的指针。表达式*(names+1)等价于names[1],后者是指向字符串字面值"Hina Ali"的指针。所以这两个表达式都表示字符串字面量的地址,即编译器存储某个字符串字面量的地址。编译器存储字符串字面量的位置由编译器决定,编译器的行为可能不同。然而,在这种情况下,编译器似乎决定在内存中相邻地存储两个字符串字面值。字符串字面值"Zara Ali"的长度为9(包括空终止字符),因此这就解释了为什么地址的差异是9

图片会有帮助:

char *                char
+–––+                +–––+
|   | names[0] ––––> |'Z'| names[0][0]
+–––+                +–––+
|   | names[1] ––+   |'a'| names[0][1]
+–––+            |   +–––+
...             |    ...
|   +–––+
|   |'i'| names[0][7]
|   +–––+
|   | 0 | names[0][8]
|   +–––+
|
|   +–––+
+-> |'H'| names[1][0]
+–––+
|'i'| names[1][1]
+–––+
...
+–––+
|'i'| names[1][7]
+–––+
| 0 | names[1][8]
+———+

每个字符串字面值("Zara Ali","Hina Ali"等)存储在内存中的某个地方,作为char的零终止数组(字符串字面值的存储方式是在程序的整个生命周期内都可用)。

每个names[i]存储每个字符串字面值的第一个字符的地址。

表达式names的类型为"指向指向char的指针";(char **)1并求值为names数组第一个元素的地址——相当于写&names[0]。表达式names[0]求值为"Zara Ali"字符串字面量中第一个字符的地址——这与写&names[0][0]是一样的。

使用%p转换说明符来打印指针值而不是%d-%d期望其对应的参数类型为int,并且指针不是整数:

printf( "Value of names[%d] = %pn", i, (void *) names[i] );
printf( "Value of names = %pn", (void *) names );
printf( "Value of names+1 = %pn", (void *) (names + 1) );

在c中,这几乎是唯一需要显式转换指向void *的指针的时候。


  1. 除非它是sizeof或单元&操作符的操作数,或者它是用于在声明中初始化字符类型数组的字符串字面值,否则类型为"T的n元素数组"的表达式将被转换或"衰减"为类型为"指向T的指针"的表达式,该表达式的值将是数组的第一个元素的地址。

    变量names被声明为指向char(char *[])的指针数组。但是,当names出现在表达式中,并且它不是sizeof或一元&的操作数时,它被转换为"指向char(char **)的指针"类型。

    这就是为什么nameschar *的数组——每个字符串字量本身就是一个数组表达式("char的9元素数组"),但在这种情况下"衰减"为类型char *

相关内容

  • 没有找到相关文章

最新更新