uint32_t指针如何工作?

时间:2015-06-17 04:51:18

标签: c++ uint32-t

我对uint32_t指针在C ++中的工作原理感到困惑

我只是在试图学习TEA,我不明白他们何时将uint32_t参数传递给encrypt函数,然后在函数中声明了一个uint32_t变量并将参数分配给它,就像参数是一个阵列。

像这样:

void encrypt (uint32_t* v, uint32_t* k) {
uint32_t v0=v[0], v1=v[1], sum=0, i;

所以我决定玩uint32_t指针,写了一个很小的代码

int main ()
{
    uint32_t *plain_text;
    uint32_t key;
    unsigned int temp=123232;
    plain_text=&temp;
    key=7744;

    cout<<plain_text[1]<<endl;

    return 0;
}

当输出是“key”的值时,它引起了我的注意。我不知道它是如何工作的...然后当我尝试使用plain_text [0]时,它返回了“temp”的值。

所以我一直在努力去理解发生了什么。

编辑:回顾TEA代码,uint32_t * v指向数组而不是单个unsigned int吗?而我所做的只是侥幸?

4 个答案:

答案 0 :(得分:3)

unsigned int是一种类型。它表示无符号的32位整数。在您的系统上,它可能是[]的typedef名称。

指向这种特定类型的指针并没有什么特别之处;你可以指向任何类型的指针。

C和C ++中的p[0]实际上是指针索引符号p[1]表示检索指针指向的位置的值。 p[2]之后获取下一个内存位置的值。然后plain_text[1]是之后的下一个位置,依此类推。

你也可以在数组中使用这种表示法,因为当像这样使用时,数组的名称会被转换为指向第一个元素的指针。

因此,您的代码temp会尝试在temp之后读取下一个元素。由于temp实际上不是数组,因此会导致undefined behaviour。在您的特定情况下,此未定义行为的表现形式是它设法在key之后读取内存地址而不会崩溃,并且该地址与存储import win32com.client speaker = win32com.client.Dispatch("SAPI.SpVoice") speaker.Speak("Hello, it works!") 的地址相同。

答案 1 :(得分:1)

您的程序正式有未定义的行为。

表达式plain_text[1]相当于*(plain_text + 1)([expr.sub] / 1)。虽然你可以指向一个超出数组末尾的对象(对于指针算术([expr.unary.op] / 3)而言,不是数组的对象仍然被认为是单元素数组),你不能解除引用这个地址([expr.unary.op] / 1)。

此时编译器可以执行任何想要的操作,在这种情况下,它只是决定将表达式视为 指向数组并且plain_text + 1,即&temp + 1指向堆栈中的下一个uint32_t对象,在这种情况下巧合为key

如果查看程序集,您可以看到正在进行的操作

mov DWORD PTR -16[rbp], 123232 ; unsigned int temp=123232;
lea rax, -16[rbp]
mov QWORD PTR -8[rbp], rax     ; plain_text=&temp;
mov DWORD PTR -12[rbp], 7744   ; key=7744;
mov rax, QWORD PTR -8[rbp]
add rax, 4                     ; plain_text[1], i.e. -16[rbp] + 4 == -12[rbp] == key
mov eax, DWORD PTR [rax]
mov edx, eax
mov rcx, QWORD PTR .refptr._ZSt4cout[rip]
call    _ZNSolsEj              ; std::ostream::operator<<(unsigned int)
mov rdx, QWORD PTR .refptr._ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_[rip]
mov rcx, rax
call    _ZNSolsEPFRSoS_E       ; std::ostream::operator<<(std::ostream& (*)(std::ostream&))
mov eax, 0
add rsp, 48
pop rbp
ret

答案 2 :(得分:0)

在C和C ++数组中衰减为指针,导致array/pointer equivalence

a[1]

a是简单类型时,等同于

*(a + 1)

如果a是一个简单类型数组,a将尽早衰减到元素0的地址。

int arr[5] = { 0, 1, 2, 3, 4 };
int i = 10;

int* ptr;

ptr = arr;
std::cout << *ptr << "\n"; // outputs 0
ptr = &arr[0]; // same address
std::cout << *ptr << "\n"; // outputs 0
std::cout << ptr[4] << "\n"; // outputs 4
std::cout << *(ptr + 4) << "\n"; // outputs 4
ptr = &i;
std::cout << *ptr << "\n"; // outputs 10
std::cout << ptr[0] << "\n";
std::cout << ptr[1] << "\n"; // UNDEFINED BEHAVIOR.
std::cout << *(ptr + 1) << "\n"; // UNDEFINED BEHAVIOR.

要了解ptr[0]ptr[1],您只需了解pointer arithmetic

答案 3 :(得分:-1)

uint32_t * plain_text; //在内存中为 plain_text

保留4个字节

uint32_t key; //在 plain_text 之后的 密钥

因此:&amp; plain_text [0]是plain_text而&amp; plain_text [1]指的是

接下来的4个字节是&amp; key

这种情况可以解释这种行为。