为什么Serial.println()会改变函数内部数组的值
Why does Serial.println() change the value of an array inside a function?
这个问题类似于这个问题:Serial。println改变函数(Arduino)返回值
我有一个函数test(byte _b[])
,它接收字节数组并使用本地临时字节数组更改其值。当函数test
返回时,本地字节数组将被销毁,因此调用者应该无法访问它。但是,Serial.println()使调用者可以访问本地数组。为什么呢?这是不是有点像内存泄漏?
代码(在Arduino 1.6.12, 64位Debian Jessie中测试):
uint32_t timer;
void setup () {
Serial.begin(57600);
Serial.println("init");
}
void loop () {
if (millis() > timer) {
timer = millis() + 1000;
// many bytes need escaping, so we better use the URLencode function
byte testarray[3];
test(testarray);
Serial.print("testing: ");
Serial.println((char *) testarray);
Serial.println("---------");
}
}
void test(byte _b[]) {
byte c[4];
c[0] = 95; c[1] = 48; c[2] = 55; c[3] = 0;
_b = c;
Serial.println((char *) c); // MARKED: this is the line that causes the unexpected behaviour
}
使用标记行,我得到以下输出:init
_07
testing: _07
---------
_07
testing: _07
---------
没有标记行,我得到这个:
init
testing:
---------
testing:
---------
testing:
---------
testing:
---------
testing:
---------
将未初始化的字节传递给函数:
byte testarray[3];
// ... code that does not write to testarray ...
Serial.println((char *) testarray);
这会导致未定义的行为;使用未初始化值的一个常见影响是,它们可能包含最近被程序的另一部分使用过的其他内容。
请注意,您标记了导致意外行为的特定行,但该行正常工作。输出_07
。然后,当执行到未定义的行为行时,在本例中表现为也输出_07
。
在函数test
中有一些你可能忽略了的东西:
- c风格数组作为指针传递-函数与
void test(byte * _b)
相同。_b
是指向testarray
的第一个元素的指针。 - 形参使用值传递(除非特别标记为引用传递):形参是通过复制实参值进行初始化的函数的局部变量。因此,更改
_b
不会对复制的初始化_b
的参数产生任何影响。(需要明确的是,_b
是一个指针-我们谈论的是指针,而不是_b
可能指向的任何东西)。对指针使用赋值操作符意味着改变指针指向的位置。(也许你认为这意味着在指针指向的两个位置之间复制一些字节——但它不是)。
所以这行:
_b = c;
改变了局部变量_b
的位置,而不改变testarray
的位置。
相关文章:
- C++ SSE 内部函数:将结果存储在变量中
- C++代码停止工作错误使用cout内部函数
- 为什么从具有较大阵列的 SIMD 内部函数中获得的相对加速比标量更大?
- 使用英特尔内部函数 (AVX) 中的混合说明
- 英特尔汇编与内部函数,AVX
- 使用SSE内部函数复制少量数据时出现问题
- 在为函数编写单元测试时,我应该模拟所做的内部函数调用吗?
- 用于平铺矩阵乘法的 AVX 内部函数
- 是否可以使用类的析构函数内部函数来重置值?
- 我在理解 AVX 随机内部函数如何为 8 位时遇到一些问题
- 无法执行内部函数 strlen
- COUT 内部函数调用的顺序
- GCC(通过 CUDA)内部函数的编译器错误,但我没有使用任何
- C++ ld 链接器 --wrap 选项不适用于内部函数调用
- 通过Visual Studio将小型结构逐值传递到非内部函数的速度很慢
- 使用内部函数递增数组的特定元素
- 在使用英特尔内部函数对 SIMD 代码进行编程时,如何强制使用 vmovapd 而不是 vmovupd?
- 如何最大限度地减少使用标量 SIMD 内部函数的 SIMD 注册表的双重负载开销
- 有符号整数溢出、内部函数和未定义的行为
- SSE2 内部函数 - 找到两个无符号短向量的最大值