在 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);

在此示例中,p1p2 将具有完全相同的值。 p0 + 42会将char大小的42倍添加到p0中包含的地址,但是由于char的大小始终为1,所以这与第二个完全相同版本。

对于大小不为 1 的类型,结果会有所不同(例如,如果 p0int*float*)。但是,如果您想对指针值进行简单的整数计算(例如,添加或减去偏移量),我仍然建议转换为 char* 而不是 intptr_t ,除非您确实需要进行专门的整数运算根据 the answers to this question.

的建议,指针的值(例如反转一些位或类似的东西)