gpt4 book ai didi

c - 使用指针访问数组和通过指针访问非数组变量之间有什么区别

转载 作者:行者123 更新时间:2023-11-30 20:11:47 25 4
gpt4 key购买 nike

我试图更深入地学习C。我已经写了下面显示的代码。

#include "includes.h"

int main() {
char *array[1];
array[0] = "cloud";
char *ll[1];
ll[0] = array[0];
int n = 20, *pointer; // actual and pointer decaration

pointer = &n; // assign the memory address of int n to pointer
printf("the address of the variable in pointer is: %x\n", pointer);
printf("the value of *pointer is %d\n", *pointer);
printf("the value of &pointer is %x\n", &n);
//return 0;

// to access the value provided by a pointer, you would use *pointer
// accessing an array directly
printf("value of array[0] %s\n", array[0]);
printf("address of &array[0] %x\n", &array[0]);

// accessing array through the pointer ll
printf("value of *ll %s\n", *ll);
printf("address of ll %x\n", ll);
printf("pointer: %p\n", (void*) pointer); //inclusion from @chux
}


头文件“ includes.h”包含以下代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <ctype.h>

#define DEF1 20
#define DEF2 2


这是我的Bash终端的程序输出:

[carl@sparknohss c]$ ./pointers.bin 
the address of the variable in pointer is: 4a8c27dc
the value of *pointer is: 20
the value of &pointer is: 4a8c27dc
value of array[0]: cloud
address of &array[0]: 4a8c27f0
value of *ll: cloud
address of ll: 4a8c27e0
pointer: 0x7ffc4a8c27dc
[carl@sparknohss c]$


我看到,至少在我看来,访问指向非数组的指针和访问指向数组的指针有区别。有没有人可以更详细地解释这一点?

另外,除了 %x提供的“ 0x7ffc”前缀以外, %p%x有什么区别?有什么我可以深入研究的更好的解释资源吗?

最佳答案

我看到,至少在我看来,访问指向非数组的指针和访问指向数组的指针是有区别的。有没有人可以更详细地解释这一点?


处理数组和指针对象时存在一些差异。

将代码搁置一秒钟,假设您有声明

int arr[10];


这将创建一个足以容纳10个整数的数组 arr。它像这样在内存中布局:

     +---+ 
arr: | | arr[0]
+---+
| | arr[1]
+---+
...
+---+
| | arr[9]
+---+


事情变得显而易见-数组第一个元素( &arr[0])的地址将与整个数组对象( &arr)的地址相同。表达式 &arr[0]&arr将具有相同的值,但是它们的类型将有所不同- &arr[0]的类型将为“指向 int的指针”( int *),而 &arr的类型将是“指向 int的10个元素的数组的指针”( int (*)[10])。

现在是产生皱纹的地方-除非它是 sizeof或一元 &运算符的操作数,或者是用于在声明中初始化另一个数组的字符串文字,即类型为“ T的数组”的表达式“将被转换(” decay“)为” pointer to T“类型的表达式,该表达式的值将为数组第一个元素的地址。

这意味着表达式 arr也将求值为数组的第一个元素的地址,就像 &arr[0]&arr一样;它从“由10个元素组成的 int数组”类型“衰减”到“指向 int的指针”(与 &arr[0]相同)。

这绝对不同于常规指针变量的行为。给定

int *ptr;


表达式 ptr不能为您提供与 &ptr相同的值-可以为您提供 ptr中存储的任何值。

返回您的代码一秒钟

array[0] = "cloud";


字符串文字 "cloud"本身是一个数组表达式-类型为“ char的6元素数组”(计算0终止符)。由于它不是 sizeof或一元 &运算符的操作数,也不用于初始化声明中的另一个数组,因此该表达式将从类型“ char的数组”转换为“指向 ”,表达式的值就是字符串中第一个字符的地址。由于您将 char声明为 array的数组,因此可以使用; char *的类型是 array[0]

那么,为什么数组表达式会“衰减”到指针表达式?

数组索引操作 char *定义为 a[i]-给定一个地址值,从该地址偏移 *(a + i)个元素(不是字节)并取消引用结果。这是B编程语言的保留,它是C的来源,并且在设置数组对象时在内部使用了指针。 C摆脱了内部指针,但保留了下标的语义。因此,要使 i在C中工作,首先必须将 a[i]转换为指针值。请注意,这意味着您可以对指针类型使用 a运算符- []pointer[0]将为您提供相同的结果( *pointer所指向的值)。

因此,如果您打印出以下表达式:

printf( "&array[0] = %p\n", (void *) &array[0] );
printf( "array = %p\n", (void *) array );
printf( "&array = %p\n", (void *) &array );


您应该看到所有三个值都相同- pointer第一个元素的地址。如果您打印出表达式

printf( "array[0]  = %p\n", (void *) array[0] );


您应该看到 array字符串文字的第一个字符的地址。

如果您打印表达式

printf( "array     = %s\n", array );


您应该看到字符串 "cloud"。请记住, cloud转换说明符希望其对应的参数是指向 %s的指针,并且它将打印从该地址开始的字符序列,直到看到0终止符为止。

如果您打印表达式

printf( "*array[0] = %c\n", *array[0] );


您会看到字符 char- c字符串中的第一个字母。请注意, "cloud"*array[0]相同。要打印 array[0][0],您需要编写

printf( "array[0][1] = %c\n", array[0][1] );


如果您打印表达式

printf( "pointer  = %p\n", (void *) pointer );
printf( "&pointer = %p\n", (void *) &pointer );


您肯定会看到不同的值,因为 l不是数组对象。


  另外,%x和%p有什么区别


pointer期望其对应的参数具有类型 %x,并以十六进制格式设置输出。

unsigned int期望其对应的参数具有类型 %p,并以实现定义的方式格式化输出(通常为十六进制,但不一定必须如此)。

您不想使用 void *(或 %x以外的任何其他东西)来打印出指针值。一方面,指针值可能比 %p宽(这在我的系统上是正确的),因此输出可能会出现乱码。

关于c - 使用指针访问数组和通过指针访问非数组变量之间有什么区别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39400217/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com