在 C 中,如何将一个地址的值设置为另一个地址的值?
In C, How does one set the value at one address to the value at another address?
我正在尝试编写一些 UART 代码,将一个小字符串放在堆栈上,以通过中断系统传输。这专门用于 Atmel SAM 微控制器
#define UART_BUF_LEN 16
//GPS SERIAL INSTANCE
struct usart_module usart_instance;
char buffer[UART_BUF_LEN];
uintptr_t bufferPtr = (uintptr_t)buffer;
bool transmitting(){
return (uintptr_t)buffer == bufferPtr; //If the read head is at the top of the array, then we are not transmitting.
}
bool transmit(char* c, uint len){
if(!transmitting() && len<=UART_BUF_LEN){
bufferPtr= (uintptr_t)buffer + len;//set write head to top of the len stack
while(transmitting()){
*bufferPtr = *c; //Set the value at the address of bufferPtr to the value at the address of c.
bufferPtr --; //Move the buffer closer to the head of the array
c++; //Move the head of the array down some.
}
}else{
return false;
}
bufferPtr= (uintptr_t)buffer + len; //reset the read head so that our transmit code knows where to read from.
return true;
}
这里的问题是 *bufferPtr = *c;
行。当我构建解决方案时,bufferptr
似乎不可取消引用。我收到以下错误:
invalid type argument of unary '*' (have 'uintptr_t {aka unsigned int}')
我在网上看过,所有消息来源都告诉我必须将 uintptr_t
转换回内存地址指向的本机数据类型的指针。我不确定如何执行此操作,因为使用类型转换 (char *)
,表明缓冲区指针是字符指针无法编译,给我与上面相同的错误。
现在,当我将行更改为 \*(char\*)bufferPtr = \*c;
时,兔子洞更深了一层,这不会给我任何错误。这条线是什么意思?
我希望这意味着将bufferPtr
类型转换为char指针的地址处的值设置为c地址处的值。这是正确的吗?
由于 bufferPtr
是一个 uintptr_t
,它是一个整数类型,而不是指针类型,您必须在取消引用之前将其转换回指针类型。
*(char *)bufferPtr = *c;
很好,因为 bufferPtr
的值来自 char
数组。
char buffer[UART_BUF_LEN];
uintptr_t bufferPtr = (uintptr_t)buffer;
改变这个:
uintptr_t bufferPtr = (uintptr_t)buffer;
对此:
char *bufferPtr = buffer;
删除程序中所有地方的(uintptr_t)
。
我不知道你为什么决定使用 uintptr_t
,但你不需要它。
uintptr_t
是一个 integer 类型,提供它是为了能够安全地将指针的值存储在整数中。由于不同的机器和架构有不同的指针大小,这种类型允许将指针转换为整数类型,而不必担心根据机器选择正确的整数大小(例如 32 位或 64 位整数)。这使得编写可移植代码更加容易。
uintptr_t
是 不是 指针类型。这意味着您不能取消引用它,就像您不能取消引用 int
一样。为了能够将其用作指针,您必须将其转换回指针。
char* char_ptr = (char*)bufferptr;
*char_ptr = *c;
如果您想进行指针操作(包括指针运算),我建议您将指针保留为指针并且不要将它们转换为uintptr_t
。
由于保证 char
的大小为 1,因此您对 char*
进行的所有计算与您对整数进行的计算完全相同,例如
char c = 'A'
char* p0 = &c;
uintptr_t p_casted = (uintptr_t)p0;
char* p1 = p0 + 42;
char* p2 = (char*)(p_casted + 42);
在此示例中,p1
和 p2
将具有完全相同的值。 p0 + 42
会将char
大小的42倍添加到p0
中包含的地址,但是由于char
的大小始终为1,所以这与第二个完全相同版本。
对于大小不为 1 的类型,结果会有所不同(例如,如果 p0
是 int*
或 float*
)。但是,如果您想对指针值进行简单的整数计算(例如,添加或减去偏移量),我仍然建议转换为 char*
而不是 intptr_t
,除非您确实需要进行专门的整数运算根据 the answers to this question.
的建议,指针的值(例如反转一些位或类似的东西)
我正在尝试编写一些 UART 代码,将一个小字符串放在堆栈上,以通过中断系统传输。这专门用于 Atmel SAM 微控制器
#define UART_BUF_LEN 16
//GPS SERIAL INSTANCE
struct usart_module usart_instance;
char buffer[UART_BUF_LEN];
uintptr_t bufferPtr = (uintptr_t)buffer;
bool transmitting(){
return (uintptr_t)buffer == bufferPtr; //If the read head is at the top of the array, then we are not transmitting.
}
bool transmit(char* c, uint len){
if(!transmitting() && len<=UART_BUF_LEN){
bufferPtr= (uintptr_t)buffer + len;//set write head to top of the len stack
while(transmitting()){
*bufferPtr = *c; //Set the value at the address of bufferPtr to the value at the address of c.
bufferPtr --; //Move the buffer closer to the head of the array
c++; //Move the head of the array down some.
}
}else{
return false;
}
bufferPtr= (uintptr_t)buffer + len; //reset the read head so that our transmit code knows where to read from.
return true;
}
这里的问题是 *bufferPtr = *c;
行。当我构建解决方案时,bufferptr
似乎不可取消引用。我收到以下错误:
invalid type argument of unary '*' (have 'uintptr_t {aka unsigned int}')
我在网上看过,所有消息来源都告诉我必须将 uintptr_t
转换回内存地址指向的本机数据类型的指针。我不确定如何执行此操作,因为使用类型转换 (char *)
,表明缓冲区指针是字符指针无法编译,给我与上面相同的错误。
现在,当我将行更改为 \*(char\*)bufferPtr = \*c;
时,兔子洞更深了一层,这不会给我任何错误。这条线是什么意思?
我希望这意味着将bufferPtr
类型转换为char指针的地址处的值设置为c地址处的值。这是正确的吗?
由于 bufferPtr
是一个 uintptr_t
,它是一个整数类型,而不是指针类型,您必须在取消引用之前将其转换回指针类型。
*(char *)bufferPtr = *c;
很好,因为 bufferPtr
的值来自 char
数组。
char buffer[UART_BUF_LEN];
uintptr_t bufferPtr = (uintptr_t)buffer;
改变这个:
uintptr_t bufferPtr = (uintptr_t)buffer;
对此:
char *bufferPtr = buffer;
删除程序中所有地方的(uintptr_t)
。
我不知道你为什么决定使用 uintptr_t
,但你不需要它。
uintptr_t
是一个 integer 类型,提供它是为了能够安全地将指针的值存储在整数中。由于不同的机器和架构有不同的指针大小,这种类型允许将指针转换为整数类型,而不必担心根据机器选择正确的整数大小(例如 32 位或 64 位整数)。这使得编写可移植代码更加容易。
uintptr_t
是 不是 指针类型。这意味着您不能取消引用它,就像您不能取消引用 int
一样。为了能够将其用作指针,您必须将其转换回指针。
char* char_ptr = (char*)bufferptr;
*char_ptr = *c;
如果您想进行指针操作(包括指针运算),我建议您将指针保留为指针并且不要将它们转换为uintptr_t
。
由于保证 char
的大小为 1,因此您对 char*
进行的所有计算与您对整数进行的计算完全相同,例如
char c = 'A'
char* p0 = &c;
uintptr_t p_casted = (uintptr_t)p0;
char* p1 = p0 + 42;
char* p2 = (char*)(p_casted + 42);
在此示例中,p1
和 p2
将具有完全相同的值。 p0 + 42
会将char
大小的42倍添加到p0
中包含的地址,但是由于char
的大小始终为1,所以这与第二个完全相同版本。
对于大小不为 1 的类型,结果会有所不同(例如,如果 p0
是 int*
或 float*
)。但是,如果您想对指针值进行简单的整数计算(例如,添加或减去偏移量),我仍然建议转换为 char*
而不是 intptr_t
,除非您确实需要进行专门的整数运算根据 the answers to this question.