Bug: Application called a GL11 Pointer method with an indirect Buffer

本文介绍了一种解决Android Studio中OpenGL ES应用崩溃的方法。通过改进FloatBuffer和IntBuffer的创建方式,避免了直接使用wrap方法导致的问题,确保了应用能够正常运行。


在Android studio 中测试OpenGL es,app运行崩溃,然后查看日志,发现Error:



原因: 不能直接使用

FloatBuffer.wrap(float [] arr), IntBuffer.wrap(int [] arr)


解决办法:


    public IntBuffer bufferUtil(int[] arr){
        IntBuffer buffer;

        ByteBuffer byteBuffer = ByteBuffer.allocateDirect(arr.length * 4);
        byteBuffer.order(ByteOrder.nativeOrder());

        buffer = byteBuffer.asIntBuffer();
        buffer.put(arr);
        buffer.position(0);

        return buffer;
    }


    public FloatBuffer bufferUtil(float[] arr){
        FloatBuffer buffer;

        ByteBuffer byteBuffer = ByteBuffer.allocateDirect(arr.length * 4);
        byteBuffer.order(ByteOrder.nativeOrder());

        buffer = byteBuffer.asFloatBuffer();
        buffer.put(arr);
        buffer.position(0);

        return buffer;
    }

修改之后,运行成功。

<think>我们想要将区域A1:B5转换为B2:B5的引用。注意,A1:B5是一个矩形区域,而B2:B5是其中一列的一部分。 在Excel中,我们可以使用INDIRECT函数来构建一个对单元格区域的引用。但是,INDIRECT函数要求我们提供一个表示单元格地址的文本字符串。 目标:通过INDIRECT函数引用区域B2:B5(即从第2行到第5行的B列)。 思路: 1. 我们可以构建一个文本字符串"B2:B5",然后用INDIRECT函数将其转换为引用。 2. 但是,如果我们需要从A1:B5这个区域描述中提取出B2:B5,那么我们需要知道如何动态地构建这个字符串。 然而,题目中要求将A1:B5区域转换为B2:B5区域引用,但并没有说明转换的规则。实际上,A1:B5区域包含10个单元格(5行2列),而B2:B5区域包含4个单元格(4行1列)。它们之间并没有直接的转换关系。 但是,如果我们理解题目意图可能是:我们有一个区域A1:B5,现在想通过INDIRECT函数来引用这个区域中的一部分,即从第2行开始到第5行,并且只取第2列(即B列)的部分。 因此,我们可以这样操作: - 首先,我们知道A1:B5的左上角是A1,右下角是B5。 - 我们想要的部分是:列从第2列(B列)开始,行从第2行到第5行。 我们可以用INDIRECT函数构建一个引用,该引用的起始位置是B2,结束位置是B5。文本字符串为:"B2:B5"。 但是,如果我们要动态地生成这个字符串,我们可以利用行列号来构造。 步骤: 1. 确定起始单元格:第2行,第2列(因为A1:B5的第一列是A,第二列是B,所以第2列就是B列)。 2. 确定结束单元格:第5行,第2列。 因此,我们可以这样写: =INDIRECT("B" & 2 & ":" & "B" & 5) 但是,如果我们希望这个引用能够根据原始区域(A1:B5)的大小和位置动态调整,那么我们需要计算: - 起始列:原始区域的第2列(即列偏移1列,因为原始区域从第1列开始)。 - 起始行:原始区域的第2行(即行偏移1行,因为原始区域从第1行开始)。 - 结束列:原始区域的第2列。 - 结束行:原始区域的第5行(即起始行+3,因为原始区域有5行,但我们从第2行开始,取4行,即到第5行)。 然而,我们也可以这样理解:原始区域是A1:B5,即行号从1到5,列号从1到2(A列是1,B列是2)。 我们想要的部分是:行号从2到5,列号2。 所以,我们可以用以下方法: 方法1:直接构建字符串(如果区域固定): =INDIRECT("B2:B5") 方法2:动态构建(假设原始区域左上角在A1): =INDIRECT(ADDRESS(2,2) & ":" & ADDRESS(5,2)) 但是,ADDRESS函数返回的是文本形式的单元格地址。例如,ADDRESS(2,2)返回"$B$2"。我们可以通过设置第三个参数来省略绝对引用符号: =INDIRECT(ADDRESS(2,2,4) & ":" & ADDRESS(5,2,4)) // 4表示相对引用 但是,如果我们希望这个区域能够随着原始区域的位置变化而变化,那么我们需要知道原始区域的左上角单元格(A1)的行号和列号,以及区域的行数和列数。 假设原始区域左上角在单元格A1(行1,列1),区域是5行2列。那么: - 起始行:1+1=2,起始列:1+1=2(即B列) - 结束行:1+5-1=5(因为区域有5行,所以结束行是第5行),结束列:1+1=2(因为我们要第2列,即原始区域的第2列) 因此,我们可以这样写: =INDIRECT(ADDRESS(1+1, 1+1, 4) & ":" & ADDRESS(1+5, 1+1, 4)) 但是,如果我们希望原始区域是任意位置,比如左上角在单元格(r0, c0)(行号r0,列号c0),区域有n行m列,那么我们要提取的区域是: 起始行:r0+1,起始列:c0+1 结束行:r0+n-1,结束列:c0+1 (因为我们要第二列,所以列偏移1列,即c0+1) 注意:题目中原始区域是A1:B5,所以r0=1, c0=1, n=5, m=2。 那么,我们要提取的区域是B2:B5,即起始行1+1=2,起始列1+1=2(B列),结束行1+5-1=5,结束列1+1=2。 因此,公式可以写为: =INDIRECT(ADDRESS(r0+1, c0+1, 4) & ":" & ADDRESS(r0+n-1, c0+1, 4)) 但是,在公式中,我们需要知道r0, c0, n, m的值。我们可以将这些值放在单元格中,或者用函数获取。 然而,题目要求通过INDIRECT函数将A1:B5区域转换为B2:B5区域引用。这里并没有要求动态适应,所以我们可以直接写: =INDIRECT("B2:B5") 但是,如果我们需要从A1:B5这个区域描述中提取信息,那么我们可以使用以下公式: =INDIRECT(ADDRESS(ROW(A1:B5)+1, COLUMN(A1:B5)+1, 4) & ":" & ADDRESS(ROW(A1:B5)+ROWS(A1:B5)-1, COLUMN(A1:B5)+1, 4)) 但是,这个公式中ROW(A1:B5)返回的是区域第一行的行号(即1),COLUMN(A1:B5)返回的是区域第一列的列号(即1)。然后我们计算: 起始行:1+1=2 起始列:1+1=2(即B列) 结束行:1+5-1=5(因为ROWS(A1:B5)=5) 结束列:1+1=2 因此,公式可以简化为: =INDIRECT(ADDRESS(ROW(A1:B5)+1, COLUMN(A1:B5)+1, 4) & ":" & ADDRESS(ROW(A1:B5)+ROWS(A1:B5)-1, COLUMN(A1:B5)+1, 4)) 但是,这个公式在输入时需要注意,它是一个数组公式吗?实际上,ROW(A1:B5)和COLUMN(A1:B5)会返回多个值,但这里我们只需要区域左上角的行号和列号,所以我们可以用: =INDIRECT(ADDRESS(ROW(A1)+1, COLUMN(A1)+1, 4) & ":" & ADDRESS(ROW(A1)+ROWS(A1:B5)-1, COLUMN(A1)+1, 4)) 这样,我们只取A1单元格的行列号,然后加上区域的行数和列数。 因此,最终公式为: =INDIRECT(ADDRESS(ROW(A1)+1, COLUMN(A1)+1, 4) & ":" & ADDRESS(ROW(A1)+ROWS(A1:B5)-1, COLUMN(A1)+1, 4)) 注意:这里ROW(A1)得到1,COLUMN(A1)得到1,ROWS(A1:B5)得到5(行数),COLUMNS(A1:B5)得到2(列数,但我们没有用到列数,因为结束列也是c0+1)。 但是,这个公式返回的是对B2:B5区域的引用,我们可以将其用于需要区域引用的函数中,比如SUM: =SUM(INDIRECT(ADDRESS(ROW(A1)+1, COLUMN(A1)+1, 4) & ":" & ADDRESS(ROW(A1)+ROWS(A1:B5)-1, COLUMN(A1)+1, 4))) 然而,这种方法比较繁琐,而且INDIRECT函数是易失性函数,可能会影响性能。 有没有更简单的方法? 我们可以使用INDEX函数来提取区域: =INDEX(A1:B5, 2, 2): 返回B2单元格 但是,要返回一个区域,我们可以这样: 起始单元格:INDEX(A1:B5,2,2) 结束单元格:INDEX(A1:B5,5,2) 然后,我们可以构建一个区域:从INDEX(A1:B5,2,2)到INDEX(A1:B5,5,2)的区域。 在Excel中,我们可以用以下方式表示一个区域: 起始单元格:结束单元格 所以,公式可以写为: =INDEX(A1:B5,2,2):INDEX(A1:B5,5,2) 这个公式直接返回一个区域引用,而且是非易失性函数(INDEX是非易失性的)。 因此,更推荐使用INDEX函数来构建区域。 那么,动态的方式就是: =INDEX(原始区域, start_row, start_col) : INDEX(原始区域, end_row, end_col) 其中,原始区域是A1:B5,start_row=2, start_col=2, end_row=5, end_col=2。 所以,公式为: =INDEX(A1:B5,2,2):INDEX(A1:B5,5,2) 这个公式的结果就是B2:B5区域。 总结: 如果原始区域固定为A1:B5,且需要引用的子区域固定为B2:B5,那么直接使用: =B2:B5 或者,如果希望用公式动态构建(比如原始区域可能变化,但相对位置不变),那么使用INDEX构建区域引用: =INDEX(A1:B5,2,2):INDEX(A1:B5,5,2) 如果原始区域的位置和大小可能变化,我们可以将原始区域定义为名称(比如MyRange),然后公式写为: =INDEX(MyRange,2,2):INDEX(MyRange,5,2) 这样,当MyRange变化时,公式也会相应变化。 因此,回答用户的问题:使用INDIRECT函数将A1:B5转换为B2:B5区域引用,我们可以这样写: =INDIRECT("B2:B5") 或者,为了动态性(基于原始区域A1:B5的位置和大小),我们可以用之前提到的ADDRESS方法,但更推荐INDEX方法。 但是,用户明确要求使用INDIRECT函数,所以我们给出INDIRECT的解决方案: =INDIRECT(ADDRESS(ROW(A1:B5)+1, COLUMN(A1:B5)+1, 4) & ":" & ADDRESS(ROW(A1:B5)+ROWS(A1:B5)-1, COLUMN(A1:B5)+1, 4)) 但请注意,ROW(A1:B5)返回的是区域中第一行的行号(数组),所以我们可以用ROW(A1)代替,同样,COLUMN(A1)代替第一列的列号。 =INDIRECT(ADDRESS(ROW(A1)+1, COLUMN(A1)+1, 4) & ":" & ADDRESS(ROW(A1)+ROWS(A1:B5)-1, COLUMN(A1)+1, 4)) 简化:由于A1:B5的起始单元格是A1,所以ROW(A1)=1, COLUMN(A1)=1,ROWS(A1:B5)=5,所以公式变为: =INDIRECT(ADDRESS(2,2,4) & ":" & ADDRESS(5,2,4)) 而ADDRESS(2,2,4)返回"B2", ADDRESS(5,2,4)返回"B5",所以连接后为"B2:B5",再通过INDIRECT函数转换为引用。 因此,最终公式可以简化为: =INDIRECT("B2:B5") 所以,如果区域固定,直接写字符串即可。 但是,如果用户希望这个公式能够适应原始区域的位置变化(比如原始区域不是从A1开始,而是从C3开始,但区域大小仍然是5行2列,那么我们要提取的区域应该是D4:D7),那么我们就需要动态计算。 因此,我们给出一个通用的INDIRECT公式,假设原始区域为rng(我们可以用rng代表A1:B5,但公式中需要知道rng的起始位置和大小): =INDIRECT( ADDRESS(ROW(rng)+1, COLUMN(rng)+1, 4) & ":" & ADDRESS(ROW(rng)+ROWS(rng)-1, COLUMN(rng)+1, 4) ) 在公式中,rng可以用一个区域引用来代替。但是,在公式中直接使用区域引用(如A1:B5)时,ROW(rng)会返回一个数组(即区域中每一行的行号),而我们只需要第一行的行号,所以我们可以用INDEX(ROW(rng),1)来获取第一行的行号,同理,COLUMN(rng)可以用INDEX(COLUMN(rng),1)来获取第一列的列号。 因此,更严谨的写法: =INDIRECT( ADDRESS(INDEX(ROW(rng),1)+1, INDEX(COLUMN(rng),1)+1, 4) & ":" & ADDRESS(INDEX(ROW(rng),1)+ROWS(rng)-1, INDEX(COLUMN(rng),1)+1, 4) ) 例如,rng为A1:B5,则: INDEX(ROW(rng),1) -> 1 INDEX(COLUMN(rng),1) -> 1 ROWS(rng) -> 5 COLUMNS(rng) -> 2 (这里没有用到) 公式变为:ADDRESS(1+1,1+1,4) 即 "B2",ADDRESS(1+5-1,1+1,4)即"B5",所以结果为B2:B5。 如果rng是C3:D7(即3行3列,5行2列),那么: INDEX(ROW(rng),1) -> 3 INDEX(COLUMN(rng),1) -> 3 ROWS(rng) -> 5 那么公式变为:ADDRESS(3+1,3+1,4) -> "D4", ADDRESS(3+5-1,3+1,4) -> "D7",所以结果为D4:D7。 这正是我们想要的:原始区域C3:D7,我们要提取的是第2列(即D列)的第2行到第5行(即4到7行)。 因此,最终的通用公式为: =INDIRECT(ADDRESS(INDEX(ROW(rng),1)+1, INDEX(COLUMN(rng),1)+1, 4) & ":" & ADDRESS(INDEX(ROW(rng),1)+ROWS(rng)-1, INDEX(COLUMN(rng),1)+1, 4)) 注意:这个公式中的rng需要替换为实际的区域引用,如A1:B5。 但是,由于公式较长,且INDIRECT是易失性函数,如果数据量较大,建议使用INDEX方法(非易失性): =INDEX(rng,2,2):INDEX(rng,ROWS(rng),2) 解释:INDEX(rng,2,2)返回rng区域中第2行第2列的单元格,INDEX(rng,ROWS(rng),2)返回rng区域中最后一行第2列的单元格。用冒号连接这两个单元格,就形成了一个区域。 所以,如果用户不强制使用INDIRECT,推荐使用INDEX方法。 根据问题,用户要求使用INDIRECT函数,所以我们提供INDIRECT的解决方案。 但是,在回答中,我们也可以提供INDEX方法作为备选。 现在,我们按照用户要求,用INDIRECT函数实现: 公式如下: =INDIRECT(ADDRESS(ROW(A1)+1, COLUMN(A1)+1, 4) & ":" & ADDRESS(ROW(A1)+ROWS(A1:B5)-1, COLUMN(A1)+1, 4)) 或者,使用通用公式(将A1:B5替换为实际区域引用): =INDIRECT(ADDRESS(INDEX(ROW(A1:B5),1)+1, INDEX(COLUMN(A1:B5),1)+1, 4) & ":" & ADDRESS(INDEX(ROW(A1:B5),1)+ROWS(A1:B5)-1, INDEX(COLUMN(A1:B5),1)+1, 4)) 注意:在Excel中,输入公式时,区域引用要写为实际区域。 但是,这个公式很长,而且ADDRESS函数返回的是文本,INDIRECT再将其转换为引用。如果用户只是需要引用B2:B5,那么直接写INDIRECT("B2:B5")更简单。 因此,我们判断用户可能是想动态地根据原始区域来获取子区域,所以提供了通用公式。 总结回答: 1. 直接方法(适用于固定区域):=INDIRECT("B2:B5") 2. 动态方法(适用于原始区域位置和大小变化):使用通用公式。 同时,我们推荐使用INDEX方法作为替代(非易失性,效率更高): =INDEX(A1:B5,2,2):INDEX(A1:B5,5,2) 或者动态的INDEX方法: =INDEX(A1:B5,2,COLUMN(B1)):INDEX(A1:B5,5,COLUMN(B1)) (这里COLUMN(B1)返回2,即第2列) 或者更通用的INDEX方法(假设列索引固定为2,行从2到5): =INDEX(A1:B5,2,2):INDEX(A1:B5,ROWS(A1:B5)-0,2) // 这里ROWS(A1:B5)是5,所以减0,但也可以写成ROWS(A1:B5)表示最后一行 注意:行索引2和5也可以根据需要进行计算。 由于问题要求使用INDIRECT,所以我们主要给出INDIRECT的解决方案。 最终答案: 使用以下公式: =INDIRECT("B2:B5") 或者,动态公式(假设原始区域在A1:B5): =INDIRECT(ADDRESS(ROW(A1)+1, COLUMN(A1)+1, 4) & ":" & ADDRESS(ROW(A1)+ROWS(A1:B5)-1, COLUMN(A1)+1, 4)) 但为了通用性,我们使用: =INDIRECT(ADDRESS(INDEX(ROW(A1:B5),1)+1, INDEX(COLUMN(A1:B5),1)+1, 4) & ":" & ADDRESS(INDEX(ROW(A1:B5),1)+ROWS(A1:B5)-1, INDEX(COLUMN(A1:B5),1)+1, 4)) 注意:在输入公式时,将A1:B5替换为你的实际区域。 另外,ADDRESS函数的第三个参数为4,表示相对引用(无$符号),这样构建的地址字符串是相对地址,但实际在INDIRECT中使用时,相对引用是相对于当前工作表的。如果原始区域在另一个工作表,我们需要在字符串中加入工作表名称。 由于问题没有提到工作表,我们假设在同一工作表。 如果原始区域在另一个工作表(比如Sheet1),那么我们需要在地址前加上工作表名,例如: =INDIRECT("Sheet1!B2:B5") 在动态公式中,我们可以将工作表名也作为变量,但问题没有要求,所以不展开。 因此,我们给出最终答案。 注意:用户的问题中,引用[1]提到了INDIRECT函数跨表引用的用法,所以如果涉及跨表,可以参考引用[1]的方法。 根据以上分析,我们回答用户。</think>### Excel INDIRECT函数实现区域引用转换(A1:B5 → B2:B5) #### 方法1:直接文本拼接法(适用于固定区域) ```excel =INDIRECT("B2:B5") ``` - **原理**:直接构建目标区域的文本地址,通过INDIRECT转换为引用[^1]。 - **特点**:简单直接,但区域固定无法动态调整。 #### 方法2:动态行列计算法(推荐,适应区域变化) ```excel =INDIRECT( ADDRESS(ROW(A1:B5)+1, COLUMN(A1:B5)+1, 4) & ":" & ADDRESS(ROW(A1:B5)+ROWS(A1:B5)-1, COLUMN(A1:B5)+1, 4) ) ``` - **拆解说明**: 1. `ROW(A1:B5)`:获取原始区域起始行号(1) 2. `COLUMN(A1:B5)`:获取原始区域起始列号(1=A列) 3. `ROWS(A1:B5)`:获取原始区域总行数(5) 4. **起始单元格**:`(1+1, 1+1) = B2` (行号+1跳过头行,列号+1跳到第2列) 5. **结束单元格**:`(1+5-1, 1+1) = B5` (起始行+总行数-1,保持列不变) 6. `ADDRESS(...,4)`:生成相对引用地址(无$符号) 7. 最终拼接为`"B2:B5"`并转换引用 #### 方法3:INDEX组合法(更高效的非易失性方案) ```excel =INDEX(A1:B5, 2, 2) : INDEX(A1:B5, ROWS(A1:B5), 2) ``` - **优势**: - 非易失性函数,计算效率高于INDIRECT[^2] - 逻辑清晰:`INDEX(区域,2,2)`定位B2,`INDEX(区域,5,2)`定位B5 - **动态扩展**:替换`ROWS(A1:B5)`可自动适应行数变化 --- ### 关键参数说明 | 函数 | 作用 | 示例返回值 | |--------------|-------------------------------|------------| | `ROW(区域)` | 获取区域起始行号 | 1 | | `COLUMN(区域)`| 获取区域起始列号(A=1,B=2) | 1 | | `ROWS(区域)` | 获取区域总行数 | 5 | | `ADDRESS(行,列,4)`| 生成相对引用地址 | "B2" | > **动态调整示例**: > 若原始区域改为`C3:D7`(5行2列),公式自动返回`D4:D7` > (起始:行3+1=4,列3+1=4→D列;结束:行3+5-1=7) --- ### 性能优化建议 1. **避免全表引用**:明确限定区域范围(如`A1:B1000`而非`A:B`) 2. **优先选择INDEX**:非易失性函数减少计算负担[^2] 3. **跨表引用需包含工作表名**: ```excel =INDIRECT("Sheet1!" & ADDRESS(...)) ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值