C 当声明指向数组的指针并传递给函数时,指针是如何工作的

C 当声明指向数组的指针并传递给函数时,指针是如何工作的,c,arrays,pointers,C,Arrays,Pointers,好吧,出于某种原因,我无法理解这一点,但这是我所知道的或认为我知道的 如果要声明char类型的数组,chara[8][8]然后声明char类型的指针: char *p = a; 我知道,如果我在print语句中遵从a,我得到的是第一行的地址——如果我只是打印数组a,我仍然得到相同的地址,因为数组a指向第一行。现在如果我打印p,我知道我将得到a的地址,因为指针变量就是这样做的 不管我是否这样做: char*p=&a或char*p=a或char*p=*a,都是同一个东西-指向同一个地址 当我决定以

好吧,出于某种原因,我无法理解这一点,但这是我所知道的或认为我知道的

如果要声明char类型的数组,
chara[8][8]
然后声明char类型的指针:

char *p = a;
我知道,如果我在print语句中遵从a,我得到的是第一行的地址——如果我只是打印数组a,我仍然得到相同的地址,因为数组a指向第一行。现在如果我打印p,我知道我将得到a的地址,因为指针变量就是这样做的

不管我是否这样做:

char*p=&a
char*p=a
char*p=*a
,都是同一个东西-指向同一个地址

当我决定以尊重的态度打印变量
p
时,问题就出现了。当我打印
*p
时,我得到
a[0][0]
的值。问题是,当我尝试打印
a
的差异时,我再次得到第一行的地址,而不是值
a[0][0]

这是否意味着当我创建指向数组的指针变量时,它会跳过指向数组的操作,直接指向数组的行?意思是:

[*p]=[**a]
而不是
[*p]=[*a]
,因为
[char*p=*a]=[char*p=a]

那么,通过创建指针,它会向下跳过?我可能想得太多了,或者发现了一个我的大脑不愿意接受的规则或属性


编辑:我现在似乎从弗拉德的回答中明白了。这很奇怪,因为当我为我的课堂做学习题时,有人告诉我做这样一个函数,而不使用[]作为练习,这就是我试图避免使用这种方法的原因。

char a[3][8]
意味着你有

由8个字符组成的数组(由3个成员组成)

你需要有

char (*ptr)[8]=a; // Pointer to an array(of 3 members) of 8 characters
请注意,作为程序员,您需要注意不要访问 超出合法数组界限,即当计数从零开始时,您可以选择的最大值是
(*(ptr+2))
。(零比二等于三)

它可以表示为

(*ptr)[8]  // the pointer ptr points to
   V       // the first element of
arr[0][8]  // arr, ie arr[0]
由于C指针支持类似数组的解引用,您可以

ptr[0][1] which is the same as (*(ptr+0))[1]
同样地

ptr[2][7] which is the same as (*(ptr+2))[7] 
//note [2][7] is the maximum bound  for legal access
最后,问题出在哪里

char *ptr=a;
使用
char*ptr
可以获得指针。是 啊这是正确的。当您考虑
*ptr
a
的兼容性时,就会出现问题
a
具有类型
char[8]
。但是,仅使用
char*ptr=a
,您没有考虑
a
中的
[8]
部分。当您选择
尺寸时,差异变得明显

char a[3][8];
char (*ptr)[8]=a;
char *ptr1=a; // A good compiler will warn you about this line.
printf("ptr : %zd\n",sizeof *ptr);
printf("ptr1 : %zd\n",sizeof *ptr1);
给我

ptr : 8 // accounts for eight characters. Here ptr covers the entire
block of eight charactes, so that if you need to go to the next block
of eight characters you could just do "ptr+1" or "ptr[1]
ptr1 : 1 // accounts for just one character.

chara[3][8]
表示您有

由8个字符组成的数组(由3个成员组成)

你需要有

char (*ptr)[8]=a; // Pointer to an array(of 3 members) of 8 characters
请注意,作为程序员,您需要注意不要访问 超出合法数组界限,即当计数从零开始时,您可以选择的最大值是
(*(ptr+2))
。(零比二等于三)

它可以表示为

(*ptr)[8]  // the pointer ptr points to
   V       // the first element of
arr[0][8]  // arr, ie arr[0]
由于C指针支持类似数组的解引用,您可以

ptr[0][1] which is the same as (*(ptr+0))[1]
同样地

ptr[2][7] which is the same as (*(ptr+2))[7] 
//note [2][7] is the maximum bound  for legal access
最后,问题出在哪里

char *ptr=a;
使用
char*ptr
可以获得指针。是 啊这是正确的。当您考虑
*ptr
a
的兼容性时,就会出现问题
a
具有类型
char[8]
。但是,仅使用
char*ptr=a
,您没有考虑
a
中的
[8]
部分。当您选择
尺寸时,差异变得明显

char a[3][8];
char (*ptr)[8]=a;
char *ptr1=a; // A good compiler will warn you about this line.
printf("ptr : %zd\n",sizeof *ptr);
printf("ptr1 : %zd\n",sizeof *ptr1);
给我

ptr : 8 // accounts for eight characters. Here ptr covers the entire
block of eight charactes, so that if you need to go to the next block
of eight characters you could just do "ptr+1" or "ptr[1]
ptr1 : 1 // accounts for just one character.

如果您有这样一个数组的声明

char a[8][8];
那么这个声明呢,

char *p = a;
这是无效的

正如您在表达式中正确指出的,二维数组指示符(很少有例外)被转换为指向其第一行的指针。因此,用作初始值设定项的变量
a
被转换为
char(*)[8]
类型的
rvalue
char*
char(*)[8]
类型的指针不兼容。它们指向不同类型的对象。第一个指向类型为
char
的对象,而第二个指向类型为
char[8]
的对象

至于地址,那么数组就是内存的一部分。因此,数组本身或其第一行或其第一行中的第一个元素的地址彼此相等,因为它们都是数组占用的内存范围的地址

可以将二维数组解释为一维数组。比如说

char *p = ( char * )a;

当然,在这种情况下,只能对指针应用一次下标运算符。数组范围将被视为被
char[8*8]
类型的一维数组占用的内存,即
char[64]
。但是,如果原始数组的每一行都包含一个字符串,则可能会出现问题。

如果您有这样的数组声明

char a[8][8];
那么这个声明呢,

char *p = a;
这是无效的

正如您在表达式中正确指出的,二维数组指示符(很少有例外)被转换为指向其第一行的指针。因此,用作初始值设定项的变量
a
被转换为
char(*)[8]
类型的
rvalue
char*
char(*)[8]
类型的指针不兼容。它们指向不同类型的对象。第一个指向类型为
char
的对象,而第二个指向类型为
char[8]
的对象

至于地址,那么数组就是内存的一部分。因此,数组本身或其第一行或其第一行中的第一个元素的地址彼此相等,因为它们都是数组占用的内存范围的地址

可以将二维数组解释为一维数组。比如说

char *p = ( char * )a;
当然在这种情况下你可以