孤世星辰 发表于 2020-4-23 19:22:41

参数和指针的问题

#include <stdio.h>

void func(int b[]);

void func(int b[])
{
      printf("%d\n", b);
}

int main(void)
{
      int a = {
                {1, 2, 3, 4},
                {5, 6, 7, 8},
                {9, 10, 11, 12}
      };

      func(a);       //这个a传的应该是数组第一个元素的地址吧吧,那应该是1??
      return 0;
}

函数里面就应该是然后b【1】【3】,这个数组应该还是去a的数,但是怎么会有b【2】【2】???不是越界么,但是越界就还是取a的值,有没有大佬解释一下

永恒的蓝色梦想 发表于 2020-4-23 19:28:55

c 数组越界不管的

孤世星辰 发表于 2020-4-23 19:31:44

永恒的蓝色梦想 发表于 2020-4-23 19:28
c 数组越界不管的

那他是怎么运行的呢,怎么取值输出的??

倒戈卸甲 发表于 2020-4-23 19:33:43

本帖最后由 倒戈卸甲 于 2020-4-23 19:35 编辑

孤世星辰 发表于 2020-4-23 19:31
那他是怎么运行的呢,怎么取值输出的??

你这a不是三行四列12个元素吗?b才取到第9个元素怎么会越界

孤世星辰 发表于 2020-4-23 19:36:46

倒戈卸甲 发表于 2020-4-23 19:33
你这a不是三行四列12个元素吗?b才取到第9个元素怎么会越界

但是你把a传过去不是传第一个元素的地址么,不是1么,然后调用函数里面就应该是int b 【1】【3】啊

永恒的蓝色梦想 发表于 2020-4-23 19:39:58

孤世星辰 发表于 2020-4-23 19:31
那他是怎么运行的呢,怎么取值输出的??

内存上写着什么就输出什么

孤世星辰 发表于 2020-4-23 19:42:49

永恒的蓝色梦想 发表于 2020-4-23 19:39
内存上写着什么就输出什么

最后答案输出是9,但是我不知道为什么,我觉得应该不是随机访问,应该是输出了a里面的9吧,不是很懂

倒戈卸甲 发表于 2020-4-23 19:43:32

孤世星辰 发表于 2020-4-23 19:36
但是你把a传过去不是传第一个元素的地址么,不是1么,然后调用函数里面就应该是int b 【1】【3】啊

什么b啊,你这理解有误,b[]是一个定义了列数为3,但没有定义行数的二维数组。参数传值是让它拿到一个地址就行,不是要把1放进下标里面。

永恒的蓝色梦想 发表于 2020-4-23 19:45:04

孤世星辰 发表于 2020-4-23 19:42
最后答案输出是9,但是我不知道为什么,我觉得应该不是随机访问,应该是输出了a里面的9吧,不是很懂

这块内存在main里写入了,所以说能正确输出。
但是c不会检查越不越界,越界了写出什么来都可能

倒戈卸甲 发表于 2020-4-23 19:54:10

事实上,你完全可以int *p=a,然后func(p)这样调用func函数,这个总不会觉得一个p有能力给int[]添个数字进去吧?

倒戈卸甲 发表于 2020-4-23 20:00:22

你对数组的本质还没建立一个认识。数组是一段连续的内存。这里的a就是12个连续的int组成的数据结构。a这个数组名只是把首元素交出去。不会交什么序号下标之类的东西给别人。一个int指针或者一个数组都能接收这个首地址。int指针接受后就按着指针的方式对这段内存进行访问。数组接收后也按自己的方式去访问这段内层。一维数组、二维数组、三维数组都能接受这个首地址,接受后就分别以自己的规则去访问后续地址。

孤世星辰 发表于 2020-4-23 20:21:14

倒戈卸甲 发表于 2020-4-23 20:00
你对数组的本质还没建立一个认识。数组是一段连续的内存。这里的a就是12个连续的int组成的数据结构。a这个 ...

这个是小甲鱼29的课后题,他问我这个代码会输出啥,答案是9,看你的解释我知道他不会放进那个b【】【】但是这个a的值传哪里去了呢,我不知道他他是怎么运行输出这个9的

倒戈卸甲 发表于 2020-4-23 20:29:51

本帖最后由 倒戈卸甲 于 2020-4-23 21:39 编辑

孤世星辰 发表于 2020-4-23 20:21
这个是小甲鱼29的课后题,他问我这个代码会输出啥,答案是9,看你的解释我知道他不会放进那个b【】【】但 ...

b[][]拿到a的首地址啊。这怎么还能不理解。看来要举个例子了。a数组的12个元素存放在10001到10048这段内存上,只要访问内存10001就能拿到1,访问10005就能拿到2……访问10048就能拿到12。a传值是把10001这个内存传给b,b现在是个二维数组,按自己的规则去访问这段内存,b会找到10001,b找到10005,b找到10009,b找到10013……这里b则找到10033拿出里面的9。再说不懂我要怒了{:10_247:}

4goodworld 发表于 2020-4-23 21:52:04

#include <stdio.h>

void func(int b[]);

void func(int b[])
{
        printf("%d\n", b);
}

int main(void)
{
        int a = {
                        {1, 2, 3, 4},
                        {5, 6, 7, 8},
                        {9, 10, 11, 12}
        };
        /*
       
        b={
       
        {1,2,3},
        {4,5,6},
        {7,8,9},
        {10,11,12}
        }
       
       
        */
        func((int(*))a);       //
        return 0;
}

我用vs2017调试的时候,不能直接传a的,需要传确定的指针类型
总的来说
作为函数参数的数组,其实你传递进去的是数组的地址,啥意思,就是你传递的是一个指针而已
那么请问,指针如何与数组相转换?
相比你应该见过这样子的例子,b = *(*(b+2)+2)
对于指针的偏移,你要理解它不同的含义,你可以试着sizeof(b) 和sizeof(*b),看看两个的长度
对于这个式子: *(*(b+2)+2)
我们像因式分解一样,慢慢分析
b+2 这是啥意思,是从b指针这个地址开始,偏移 sizeof(b)*2个长度
*(b+2)+2 是指 从b+2的所处的地址开始,偏移sizeof(*b)*2的长度
如果在再琢磨下,就会发现
对于一个
假设是

b={
       
        {1,2,3},//0
        {4,5,6},//1
        {7,8,9},//2
        {10,11,12}//3
        }
       
所谓 b+2其实就是让指针指向 大数组的{7,8,9}这个小数组的头部
所谓 *(b+2)+2   其实就是让指针从小数组的头部偏移两个单位 从7偏移两个,是多少?
请记住,此刻还是地址,那取地址上的内容,则应该是 *(*(b+2)+2) =9

你把这个搞明白了,问题就迎刃而解了。

孤世星辰 发表于 2020-4-23 21:58:19

倒戈卸甲 发表于 2020-4-23 20:29
b[][]拿到a的首地址啊。这怎么还能不理解。看来要举个例子了。a数组的12个元素存放在10001到10048这段 ...

哦哦哦我会了我老是对着a数组找【2】【2】原来b换了一下

倒戈卸甲 发表于 2020-4-23 22:20:50

本帖最后由 倒戈卸甲 于 2020-4-23 22:22 编辑

孤世星辰 发表于 2020-4-23 21:58
哦哦哦我会了我老是对着a数组找【2】【2】原来b换了一下

小甲鱼的课你肯定没认真听,这个知识点小甲鱼讲的很清楚,这种用内存编号来举例,小甲鱼同样讲过

倒戈卸甲 发表于 2020-4-23 22:44:16

4goodworld 发表于 2020-4-23 21:52
我用vs2017调试的时候,不能直接传a的,需要传确定的指针类型
总的来说
作为函数参数的数组,其实你传 ...

b指向{1,2,3}整个数组,b+2指向{7,8,9}整个数组,*(b+2)才真正指向{7,8,9}的头部,所以*(b+2)+2 能指向9.
这其中的原理在于数组的地址和数组的首地址相等,数组设计的很巧妙,假如二级指针p指向一维数组a,那*p指向a的首地址,但*p与p又是相等的。p二层解引用能访问a,同时还可以令一级指针q=p,q一级解引用就访问到a。
不过在C99标准以前,这样的转换常常会令编译器崩溃

4goodworld 发表于 2020-4-23 22:52:00

本帖最后由 4goodworld 于 2020-4-23 22:53 编辑

倒戈卸甲 发表于 2020-4-23 22:44
b指向{1,2,3}整个数组,b+2指向{7,8,9}整个数组,*(b+2)才真正指向{7,8,9}的头部,所以*(b+2)+2 能指向9.
...

你是认为我的解释有问题吗?
但 正如你说言 数组的地址和数组的首地址相等

倒戈卸甲 发表于 2020-4-23 22:53:34

4goodworld 发表于 2020-4-23 22:52
你是认为我的解释有问题吗?

解释不准确。b+2不会指向你所谓的小数组的头部

倒戈卸甲 发表于 2020-4-23 23:09:25

4goodworld 发表于 2020-4-23 22:52
你是认为我的解释有问题吗?
但 正如你说言 数组的地址和数组的首地址相等

数组地址与数组首地址相等,只能说明你的这个解释也不算错。但不够精准。
当然C11标准以后,实际使用的中也无所谓了。这里的b虽然是数组指针,但可以被普通指针接收,在必要的时候编译器还能将其自动解释为*b。
不过原理还是归原理,数组指针不会指向一个数值
页: [1] 2
查看完整版本: 参数和指针的问题